schedule -> __schedlue -> deactivate_task -> update_rq_clock
这个时间函数在schedule开始也调用过
void update_rq_clock(struct rq *rq)
{
s64 delta;
lockdep_assert_held(&rq->lock);
if (rq->clock_update_flags & RQCF_ACT_SKIP)
return;
如果flag有RQCF_ACT_SKIP,就返回
在schedule中进行的出队操作不会统计时间,schedule中设置了DEQUEUE_NOCLOCK
#ifdef CONFIG_SCHED_DEBUG
if (sched_feat(WARN_DOUBLE_CLOCK))
SCHED_WARN_ON(rq->clock_update_flags & RQCF_UPDATED);
rq->clock_update_flags |= RQCF_UPDATED;
#endif
如果配置了WARN_DOUBLE_CLOCK特性,如果存在RQCF_UPDATED,就说明
rq在锁定后进行了两次update_rq_clock,赶紧发警告,并且再次设置RQCF_UPDATED
delta = sched_clock_cpu(cpu_of(rq)) - rq->clock;
获取时间差,主要是纳秒
if (delta < 0)
return;
如果是负数,返回,不清楚啥情况下会出现负数?
rq->clock += delta;
更新时间
update_rq_clock_task(rq, delta);
更新其他的一些东西,包括中断计时、中断与rq的pelt机制支持操作
}
u64 sched_clock_cpu(int cpu)
定义CONFIG_HAVE_UNSTABLE_SCHED_CLOCK之后的sched_clock_cpu实现,
应该是进程可能迁移,那么sched_clock_cpu也要进行相应处理的意思,
如果没有定义CONFIG_HAVE_UNSTABLE_SCHED_CLOCK,那么此函数主要调用sched_clock()
{
struct sched_clock_data *scd;
u64 clock;
if (sched_clock_stable())
return sched_clock() + __sched_clock_offset;
跟上面说的意思一样,如果sched_clock_stable,那么只调用sched_clock,
另外 ktime_get_ns() +__gtod_offset == sched_clock() + __sched_clock_offset 具体为什么这么搞不太清楚
if (!static_branch_unlikely(&sched_clock_running))
return sched_clock();
如果sched_clock_running为0,那么返回sched_clock,为什么不返回0?
既然sched_clock都不运行,为什么返回sched_clock???
preempt_disable_notrace();
scd = cpu_sdc(cpu);
scd是per-cpu,这里禁止抢占是因为之后的代码前提是不能再发生抢占,因为cpu必须保持不变
if (cpu != smp_processor_id())
即传入参数rq不属于当前运行进程的cpu,猜测进程之前可能发生了抢占并且迁移了,所以导致rq与cpu不匹配,
具体什么情况下会出现不太清楚
clock = sched_clock_remote(scd);
计算原cpu的clock与当前cpu的clock 需要禁止抢占,如果在函数执行过程中,再次发生抢占、迁移,数据可能会错误失效
else
clock = sched_clock_local(scd);
计算本地clock
preempt_enable_notrace();
return clock;
}