struct thread_info {
unsigned long flags; /* low level flags */
int preempt_count; /* 0 => preemptable, <0 => bug */
};
作为一个正经的程序,它不可能从一开始运行就需要一直占用CPU直到地球毁灭,可能某些时候需要等待一些资源无事可做,或者占用CPU太久需要让出CPU让其他进程也在CPU上跑一跑,这就是就进程(被)调度的时机。内核并不是发现一个进程该(被)调度时立即切换进程,而是在当前进程的thread_info中用flags中标记need_reched来记录当前进程是不是该调度了,在适当的时机检查当前进程的need_reched来决定要不要进行调度。
1.何时设置TIF_NEED_RESCHED(设置抢占)?
任何有必要的时候,例如调用try_to_wake_up尝试唤醒一个任务时发现目标进程优先级比当前高或者周期调度器发现当前进程时间片用完了再或者使能抢占时发现当前进程需要被抢占时都可以给当前进程设置TIF_NEED_RESCHED,用户空间调用ched_yield或在内核中也可以调用cond_resched()/yield()也会设置TIF_NEED_RESCHED自愿让出CPU。
2.何时检查TIF_NEED_RESCHED(执行抢占)?
内核抢占:从中断返回内核空间
el1_irq:
......
ldr w24, [tsk, #TSK_TI_PREEMPT] // get preempt count