// 更新全局时间(由动态时钟调用)
// 函数任务:
// 1.更新last_jiffies_update,记录距离上次更新jiffies经历的ns
// 2.更新jiffies_64,墙上时间,计算cpu负载
// 3.更新下次周期时钟的到期时间
// 注:
// 1.在关中断情况下调用该函数
// 2.last_jiffies_update,记录距离上次更新经历的时钟周期(ns)
1.1 static void tick_do_update_jiffies64(ktime_t now)
{
unsigned long ticks = 0;
ktime_t delta;
write_seqlock(&xtime_lock);
//距离上次更新jiffies经历的ns
delta = ktime_sub(now, last_jiffies_update);
if (delta.tv64 >= tick_period.tv64) {
//一个时钟周期剩余的ns
delta = ktime_sub(delta, tick_period);
//正常情况下,相邻更新的jiffies差一个时钟周期
last_jiffies_update = ktime_add(last_jiffies_update,
tick_period);
//慢速路径:
// jiffies距离上次更新的时间超过一个时钟周期
if (unlikely(delta.tv64 >= tick_period.tv64)) {
s64 incr = ktime_to_ns(tick_period);
//剩余的时钟周期
ticks = ktime_divns(delta, incr);
last_jiffies_update = ktime_add_ns(last_jiffies_update,
incr * ticks);
}
//更新jiffies_64,更新墙上时间,计算cpu间负载
do_timer(++ticks);
//周期时钟下次到期时间
tick_next_period = ktime_add(last_jiffies_update, tick_period);
}
write_sequnlock(&xtime_lock);
}
// 更新全局时间
// 函数任务:
// 1.更新jiffies_64
// 2.更新墙上时间
// 3.计算cpu间负载
// 调用路径:tick_do_update_jiffies64->do_timer
1.2 void do_timer(unsigned long ticks)
{
jiffies_64 += ticks;
update_wall_time();
calc_global_load();
}
// 更新墙上时间(xtime)
// 函数任务:
// 1.计算距离上次更新墙上时间经历的cycle
// 2.每隔一个NTP间隔相应的cycle数
// 2.1 以clock->cycle_interval为单位,更新clock->cycle_last
// 2.2 以xtime_interval为单位,更新clock->xtime_nsec
// 2.3 进位clock->xtime_nsec到s
// 3.根据NTP矫正clocksource
// 4.更新xtime的纳秒数
// 5.检查是否有更好的时钟源
// 注:
// #define NTP_SCALE_SHIFT 32
1.3 void update_wall_time(void)
{
cycle_t offset;
struct clocksource *clock;
clock = timekeeper.clock;
//距离上次更新墙上时间经历的cycle
#ifdef CONFIG_GENERIC_TIME
offset = (clocksource_read(clock) - clock->cycle_last) & clock->mask;
#else
offset = clock->cycle_interval;
#endif
//墙上时钟的纳秒数
clock->xtime_nsec = (s64)xtime.tv_nsec << clock->shift;
//通过时钟源的cycle计算经历的NTP间隔
while (offset >= clock->cycle_interval)
{
//以NTP间隔对应的内部时钟cycle更新xtime
offset -= clock->cycle_interval;
clock->cycle_last += clock->cycle_interval;
clock->xtime_nsec += clock->xtime_interval;
//ns进位到s
if (clock->xtime_nsec >= (u64)NSEC_PER_SEC << clock->shift) {
clock->xtime_nsec -= (u64)NSEC_PER_SEC << clock->shift;
xtime.tv_sec++;
second_overflow();
}
clock->raw_time.tv_nsec += clock->raw_interval;
if (clock->raw_time.tv_nsec >= NSEC_PER_SEC)
{
clock->raw_time.tv_nsec -= NSEC_PER_SEC;
clock->raw_time.tv_sec++;
}
//累积时间相对于NTP的误差
clock->error += tick_length;
//等效:
// 1.将t1 = clock->xtime_interval>>clock->shift,得到一个NTP间隔相应的cycle数
// 2.将t2 = t1<<NTP_SCALE_SHIFT, 放大t1指定的位数
clock->error -= clock->xtime_interval << (NTP_SCALE_SHIFT - clock->shift);
}
//矫正clocksource
clocksource_adjust(offset);
if (unlikely((s64)clock->xtime_nsec < 0)) {
s64 neg = -(s64)clock->xtime_nsec;
clock->xtime_nsec = 0;
clock->error += neg << (NTP_SCALE_SHIFT - clock->shift);
}
//更新xtime的纳秒数
xtime.tv_nsec = ((s64)clock->xtime_nsec >> clock->shift) + 1;
clock->xtime_nsec -= (s64)xtime.tv_nsec << clock->shift;
clock->error += clock->xtime_nsec << (NTP_SCALE_SHIFT - clock->shift);
//检查是否有更好的时钟源
change_clocksource();
}