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)
更多推荐
schedule_timeout
发布评论