閱讀641 返回首頁    go iPhone_iPad_Mac_apple


時間子係統8_動態時鍾(NO_HZ)

//	高分辨率模式下的周期事件仿真
//		通過hrtimer仿真周期時鍾,由hrtimer_interrupt作為時鍾事件處理函數
//	函數任務:
//		1.更新jiffies
//		2.在irq上下文
//			2.1 如果當前處於idle狀態
//				2.1.1 喂狗softlockup_watchdog,防止誤發生softlockup
//				2.1.2 更新idle狀態經曆的jiffies
//			2.2 更新進程時間
//		3.調度hrtimer下一個周期繼續運行
1.1 static enum hrtimer_restart tick_sched_timer(struct hrtimer *timer)
{
	struct tick_sched *ts =
		container_of(timer, struct tick_sched, sched_timer);
	struct pt_regs *regs = get_irq_regs();
	ktime_t now = ktime_get();
	int cpu = smp_processor_id();

	//高分辨率模式下,如果支持動態時鍾,則需要檢查是否本cpu負責更新全局時間
#ifdef CONFIG_NO_HZ
	//負責更新jiffies
	if (unlikely(tick_do_timer_cpu == TICK_DO_TIMER_NONE))
		tick_do_timer_cpu = cpu;
#endif

	if (tick_do_timer_cpu == cpu)
		tick_do_update_jiffies64(now);
	//在irq上下文
	if (regs) {
		//當前處於idle狀態
		if (ts->tick_stopped) 
		{
			//喂狗,防止誤發生softlockup
			touch_softlockup_watchdog();
			//更新idle狀態的jiffies
			ts->idle_jiffies++;
		}
		//更新進程時間
		update_process_times(user_mode(regs));
	}
	//調度hrtimer下一個周期繼續運行
	hrtimer_forward(timer, now, tick_period);
	return HRTIMER_RESTART;
}
//	關閉時鍾
//	函數任務:
//		1.檢查下一個定時器輪事件是否在一個周期之後
//			1.1 如果是這樣,重新編程clockevent設備,直到未來合適的時間才恢複。
//		2.在tick_sched中更新統計信息
//	注:在idle進程中停用時鍾
2.1 void tick_nohz_stop_sched_tick(int inidle);
..

//	恢複時鍾
//	函數任務:
//		1.更新jiffies
//		2.統計tick_sched中idle時間
//		3.設置tick_sched->tick_stopped=0,因此時鍾現在再次激活
//		4.重編程clockevent設備
2.2 void tick_nohz_restart_sched_tick(void);
..

//	動態時鍾數據結構
3.1
struct tick_sched {
	struct hrtimer			sched_timer;		//用於實現動態時鍾的定時器
	unsigned long			check_clocks;		
	enum tick_nohz_mode		nohz_mode;			//當前動態時鍾所處的模式
	ktime_t				idle_tick;				//存儲在禁用周期時鍾之前,上一個時鍾信號的到期時間
	int				inidle;						//處於idle進程中
	int				tick_stopped;				//1,即當前沒有基於周期時鍾信號的工作要做,否則為0
	unsigned long			idle_jiffies;		//存儲周期時鍾禁用時的jiffies
	unsigned long			idle_calls;			//內核試圖停用周期時鍾的次數
	unsigned long			idle_sleeps;		//存儲了周期時鍾上一次禁用的時間
	int				idle_active;				//激活了idle狀態
	ktime_t				idle_entrytime;			//idle 被調用時的時間
	ktime_t				idle_waketime;			//idle 被打斷的時間
	ktime_t				idle_exittime;			//離開idle狀態的時間
	ktime_t				idle_sleeptime;			//累計時鍾停用的總時間
	ktime_t				idle_lastupdate;		
	ktime_t				sleep_length;			//存儲周期時鍾將禁用的長度,即從時鍾禁用起,到預計將發生下一個時鍾信號為止
	unsigned long			last_jiffies;		//
	unsigned long			next_jiffies;		//存儲了下一個定時器到期的jiffies值
	ktime_t				idle_expires;			//下一個將到期的經典定時器的到期時間
	int				do_timer_last;				//記錄此cpu在停用時鍾之前是否為執行do_timer的cpu

}


//	低分辨率模式下的動態時鍾事件處理函數
//		在低分辨率模式下開啟動態時鍾時,關閉周期時鍾,由該函數處理時鍾事件。
4.1 static void tick_nohz_handler(struct clock_event_device *dev)
{
	struct tick_sched *ts = &__get_cpu_var(tick_cpu_sched);
	struct pt_regs *regs = get_irq_regs();
	int cpu = smp_processor_id();
	ktime_t now = ktime_get();

	dev->next_event.tv64 = KTIME_MAX;
	//由本cpu負責更新全局時間
	if (unlikely(tick_do_timer_cpu == TICK_DO_TIMER_NONE))
		tick_do_timer_cpu = cpu;
	//更新全局時間
	if (tick_do_timer_cpu == cpu)
		tick_do_update_jiffies64(now);

	//idle狀態停用了周期時鍾,喂狗,防止誤發生softlockup
	if (ts->tick_stopped) {
		touch_softlockup_watchdog();
		//更新idle狀態持續的jiffies
		ts->idle_jiffies++;
	}
	//更新本cpu的時間
	update_process_times(user_mode(regs));
	profile_tick(CPU_PROFILING);
	//重編程下一個時鍾事件到期時間
	while (tick_nohz_reprogram(ts, now)) {
		now = ktime_get();
		tick_do_update_jiffies64(now);
	}
}

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

  上一篇:go 時間子係統6_高分辨率定時器框架初始化
  下一篇:go 技術人員談管理之項目風險規避