本文就schedule函数与各调度器使用逻辑方向来研究学习
函数嵌套调用大体为


#define TASK_RUNNING 0x00000000
#define TASK_INTERRUPTIBLE 0x00000001
#define TASK_UNINTERRUPTIBLE 0x00000002
TASK_RUNNING状态宏定义为0
pick_next_task:
static struct task_struct *
pick_next_task(struct rq *rq, struct task_struct *prev, struct rq_flags *rf)
{
struct task_struct *next, *p, *max = NULL;
const struct cpumask *smt_mask;
bool fi_before = false;
bool core_clock_updated = (rq == rq->core);
unsigned long cookie;
int i, cpu, occ = 0;
struct rq *rq_i;
bool need_sync;
if (!sched_core_enabled(rq))
return __pick_next_task(rq, prev, rf);
走上面的分支,下面代码省略掉
……
__pick_next_task:

这里需要注意的是对于fair调度器,挑选task是有两个流程的,需要结合fair调度器的相关函数来一起看。
put_prev_task_balance:
static void put_prev_task_balance(struct rq *rq, struct task_struct *prev,
struct rq_flags *rf)
{
#ifdef CONFIG_SMP
const struct sched_class *class;
/*
* We must do the balancing pass before put_prev_task(), such
* that when we release the rq->lock the task is in the same
* state as before we took rq->lock.
*
* We can terminate the balance pass as soon as we know there is
* a runnable task of @class priority or higher.
*/
for_class_range(class, prev->sched_class, &idle_sched_class) {
if (class->balance(rq, prev, rf))
break;
}
#endif
put_prev_task(rq, prev);
}
static inline void put_prev_task(struct rq *rq, struct task_struct *prev)
{
WARN_ON_ONCE(rq->curr != prev);
prev->sched_class->put_prev_task(rq, prev);
}
这里最终会调用调度器的回调函数put_prev_task,对于deadline来说这会将当前task进行插入到二叉树当中,因为pick_next_task的时候已经将task从二叉树中删除了,如果没有重新插入二叉树,那么这个task将永远不会运行第二次,对于其它调度器有对应的回调函数。可以对应的去研究学习
2853

被折叠的 条评论
为什么被折叠?



