閱讀83 返回首頁    go 技術社區[雲棲]


時間子係統14_全局時間維護

//	更新全局時間(由動態時鍾調用)
//	函數任務:
//		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();
}

最後更新:2017-04-03 14:54:38

  上一篇:go 使用GRC Any Blocks
  下一篇:go 程控交換課外實習報告