时间子系统8_动态时钟(NO_HZ)

2014-11-24 02:42:02 · 作者: · 浏览: 1
//	动态时钟
//	函数任务:
//		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();

	//负责更新jiffies
	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);
	//在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