schedule -> __schedule -> deactivate_task
void deactivate_task(struct rq *rq, struct task_struct *p, int flags)
{
p->on_rq = (flags & DEQUEUE_SLEEP) ? 0 : TASK_ON_RQ_MIGRATING;
判断prev是怎么睡眠么?如果是p->on_rq就是0 不是 p->on_rq就是要迁移, 进程撤除是否也应该安排一个?
if (task_contributes_to_load(p))
rq->nr_uninterruptible++;
prev是否属于UNINTERRUPTIBLE? 当prev属于TASK_UNINTERRUPTIBLE 并且 不属于PF_FROZEN
并且不属于TASK_NOLOAD时,就贡献 task_contributes_to_load字面意思应该是权重的意思,不知道出于什么考虑
dequeue_task(rq, p, flags);
进程出队,这个flag就是传入的DEQUEUE_SLEEP | DEQUEUE_NOCLOCK
}
static inline void dequeue_task(struct rq *rq, struct task_struct *p, int flags)
{
if (!(flags & DEQUEUE_NOCLOCK))
update_rq_clock(rq);
如果有DEQUEUE_NOCLOCK,就不更新rq_clock 至于为什么在出队时不更新,可能使在进程休眠时更新了结束时间,出队时间不确定?
if (!(flags & DEQUEUE_SAVE)) {
sched_info_dequeued(rq, p);
貌似是统计进队与运行时间差,之后再看
貌似和psi有关
psi_dequeue(p, flags & DEQUEUE_SLEEP);
CPU压力记录,暂不清楚原理
}
uclamp_rq_dec(rq, p);
涉及uclamp机制,可能是离队的意思?
p->sched_class->dequeue_task(rq, p, flags);
dequeue_task核心代码 ,传入的是DEQUEUE_SLEEP | DEQUEUE_NOCLOCK
}
static inline void sched_info_dequeued(struct rq *rq, struct task_struct *t)
{
unsigned long long now = rq_clock(rq), delta = 0;
if (unlikely(sched_info_on()))
如果配置CONFIG_SCHEDSTATS (调度统计)或者 CONFIG_TASK_DELAY_ACCT (进程延迟计数)
if (t->sched_info.last_queued)
入队时间
delta = now - t->sched_info.last_queued;
计算进程在队列中的时间
sched_info_reset_dequeued(t);
清零last_queued 不在队列中了,就没必要记录了
t->sched_info.run_delay += delta;
rq_sched_info_dequeued(rq, delta);
详细解释一下 记录进程延迟数据分为入队queued、出队dequeued、占有cpu arrive、被动放弃cpu depart
四个时间点,其他的时间点不清楚,应该还有主动放弃cpu这个点 入队时间last_queued 占有cpu时间last_arrival
进程运行延迟run_delay info主要是记录进程运行延迟、队列rq的总?运行延迟,可能还有cpu运行时间。
}