- 论坛徽章:
- 0
|
呵呵,查了很长时间才搞清楚 v2.6.0
如果在tsk->state = TASK_UNINTERRUPTIBLE;时间片被用完,而此时恰巧发生时钟中断
do_timer->update_process_times->scheduler_tick->set_tsk_need_resched
static inline void set_tsk_need_resched(struct task_struct *tsk)
{
set_tsk_thread_flag(tsk,TIF_NEED_RESCHED);
}
设置need resched标志
中断返回
ret_from_intr:
GET_THREAD_INFO(%ebp)
movl EFLAGS(%esp), %eax # mix EFLAGS and CS
movb CS(%esp), %al
testl $(VM_MASK | 3), %eax
jz resume_kernel # returning to kernel or vm86-space
#ifdef CONFIG_PREEMPT
ENTRY(resume_kernel)
cmpl $0,TI_PRE_COUNT(%ebp) # non-zero preempt_count ?
jnz restore_all
need_resched:
movl TI_FLAGS(%ebp), %ecx # need_resched set ?
testb $_TIF_NEED_RESCHED, %cl
jz restore_all
testl $IF_MASK,EFLAGS(%esp) # interrupts off (exception path) ?
jz restore_all
movl $PREEMPT_ACTIVE,TI_PRE_COUNT(%ebp)
sti
call schedule
movl $0,TI_PRE_COUNT(%ebp)
cli
jmp need_resched
#endif
注意这里
movl $PREEMPT_ACTIVE,TI_PRE_COUNT(%ebp)
sti
call schedule
movl $0,TI_PRE_COUNT(%ebp)
cli
先置 ti->preempt_count = PREEMPT_ACTIVE;然后调度schedule
在schedule中
if (unlikely(preempt_count() & PREEMPT_ACTIVE))
goto pick_next_task;
switch (prev->state) {
case TASK_INTERRUPTIBLE:
if (unlikely(signal_pending(prev))) {
prev->state = TASK_RUNNING;
break;
}
default:
deactivate_task(prev, rq);
prev->nvcsw++;
break;
case TASK_RUNNING:
prev->nivcsw++;
}
pick_next_task:
直接跳到pick_next_task,而不将该进程脱离run queue,则下次还会被调度到 |
|