fastcall signed long __sched schedule_timeout(signed long timeout)
{
struct timer_list timer;
unsigned long expire;
switch (timeout)
{
case MAX_SCHEDULE_TIMEOUT:
schedule();
goto out;
default:
if (timeout < 0) {
printk(KERN_ERR "schedule_timeout: wrong timeout "
"value %lx\n", timeout);
dump_stack();
current->state = TASK_RUNNING;
goto out;
}
}
expire = timeout + jiffies;
setup_timer(&timer, process_timeout, (unsigned long)current);
__mod_timer(&timer, expire);
schedule();
del_singleshot_timer_sync(&timer);
timeout = expire - jiffies;
out:
return timeout < 0 ? 0 : timeout;
}
函數 schedule_timeout 定義了一個軟件時鐘變量 timer ,在計算到期時間後初始化這個軟件時鐘:設置軟件時鐘當時間到期時的處理函數爲 process_timeout ,參數爲當前進程描述符,設置軟件時鐘的到期時間爲 expire 。
之後調用 schedule() 函數。此時當前進程睡眠,交出執行權,內核調用其它進程運行(當前進程被調度出處理器,同時從cpu的run queue中移走,一個新的進程被調度運行起來)。但內核在每一個時鐘中斷處理結束後都要檢測這個軟件時鐘是否到期。如果到期,將調用 process_timeout 函數,參數爲睡眠的那個進程描述符。
其中MAX_SCHEDULE_TIMEOUT是用來檢查任務是否無限期睡眠,如果是,函數不會爲它設置定時器,這時調度會立即執行。
setup_timer()函數對定時器的初始化static inline void setup_timer(struct timer_list * timer,void (*function)(unsigned long),unsigned long data){timer->function = function;timer->data = data;init_timer(timer);} 其中對base字段的賦值是調用了init_timer()函數。
process_timeout()函數static void process_timeout(unsigned long __data){ wake_up_process((struct task_struct *)__data);}
函數 process_timeout 直接調用 wake_up_process 將進程喚醒。當內核重新調用該進程執行時,該進程繼續執行 schedule_timeout 函數,執行流則從 schedule 函數中返回,之後調用del_singleshot_timer_sync 函數將軟件時鐘卸載,然後函數 schedule_timeout 結束。
一個比較重要的步驟是timeout = expire - jiffies,這個主要是用來判斷進程被喚醒的原因,因爲有可能在timer沒到期時,其他進程喚醒了該進程,這種情況下timeout = expire - jiffies算出的timeout是>0的,所以反映到函數的返回值上就是,0意味着進程因爲時間timeout而被喚醒,一個正數意味着進程在時間尚沒有timeout的情況下被喚醒。
MAX_SCHEDULE_TIMEOUT 貌似就是-1, #define INFTIM (-1)