閱讀820 返回首頁    go 阿裏雲 go 技術社區[雲棲]


時間子係統6_高分辨率定時器框架初始化

//	高分辨率定時器框架初始化
//	調用路徑:start_kernel->hrtimers_init
//	函數任務:
//		1.創建cpu時鍾基礎
//		2.注冊監聽cpu狀態變化
//		3.注冊高分辨率模式下的定時器軟中斷
//	注:
//		1.高分辨率定時器框架的通用部分總是編譯進內核
//		2.高分辨率定時器框架初始為未激活狀態,由低分辨率定時器軟中斷中切換到高分辨率
1.1 void __init hrtimers_init(void)
{
	//通知clockevent設備管理,創建cpu時鍾基礎
	hrtimer_cpu_notify(&hrtimers_nb, (unsigned long)CPU_UP_PREPARE,
			  (void *)(long)smp_processor_id());
	//注冊監聽cpu 狀態信息
	register_cpu_notifier(&hrtimers_nb);
	//高分辨率定時功能通過預處理編譯進內核
#ifdef CONFIG_HIGH_RES_TIMERS
	//注冊高分辨率模式下的定時器軟中斷
	open_softirq(HRTIMER_SOFTIRQ, run_hrtimer_softirq);
#endif
}
//	cpu狀態監聽控製塊
2.1 static struct notifier_block __cpuinitdata hrtimers_nb = {
	.notifier_call = hrtimer_cpu_notify,
};

//	處理cpu狀態變化
//	函數任務:
//		1.cpu up,初始化cpu的時鍾基礎
//		2.針對熱插拔cpu
//			2.1 cpu dying、frozen,選擇cpu,接管do_timer
//			2.2 cpu dead、frozen
//				2.2.1 通知clockevent設備管理,cpu dead
//				2.2.2 遷移dead cpu上的hrtimer到本cpu
3.1 static int __cpuinit hrtimer_cpu_notify(struct notifier_block *self,
					unsigned long action, void *hcpu)
{
	int scpu = (long)hcpu;

	switch (action) 
	{
		//cpu up,初始化此cpu的時鍾基礎
	case CPU_UP_PREPARE:
	case CPU_UP_PREPARE_FROZEN:
		init_hrtimers_cpu(scpu);
		break;
		//下列情況隻針對熱插拔cpu
#ifdef CONFIG_HOTPLUG_CPU
	case CPU_DYING:
	case CPU_DYING_FROZEN:
		//選擇cpu接管do_timer
		clockevents_notify(CLOCK_EVT_NOTIFY_CPU_DYING, &scpu);
		break;
	case CPU_DEAD:
	case CPU_DEAD_FROZEN:
		//通知clockevent設備管理,cpu dead
		clockevents_notify(CLOCK_EVT_NOTIFY_CPU_DEAD, &scpu);
		//遷移cpu上的定時任務到本cpu
		migrate_hrtimers(scpu);
		break;
#endif
	default:
		break;
	}
	return NOTIFY_OK;
}

//	初始化cpu的時鍾基礎
//	函數任務:
//		1.初始化REALTIME、MONOTOMIC兩個時鍾基礎
//		2.更新時鍾基礎到期時間為KTIME_MAX,即沒有hrtimer會到期
//		3.更新高分辨率定時器未激活狀態
//	調用路徑:init_hrtimers_cpu->init_hrtimers_cpu
4.1 static void __cpuinit init_hrtimers_cpu(int cpu)
{
	//per cpu時鍾基礎設備,用於維護該cpu的hrtimer
	struct hrtimer_cpu_base *cpu_base = &per_cpu(hrtimer_bases, cpu);
	int i;

	raw_spin_lock_init(&cpu_base->lock);
	//初始化cpu時鍾基礎
	for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++)
		cpu_base->clock_base[i].cpu_base = cpu_base;
	hrtimer_init_hres(cpu_base);
}
4.2 static inline void hrtimer_init_hres(struct hrtimer_cpu_base *base)
{
	//下一次事件到期的絕對時間,KTIME_MAX表示沒有hrtimer會到期
	base->expires_next.tv64 = KTIME_MAX;
	//高分辨率未激活狀態
	base->hres_active = 0;
}


//	cpu時鍾基礎數據結構
//		提供兩種時鍾基礎
//			CLOCK_MONOTOMIC,係統啟動時從0開始,不會跳變,始終單調的運行
//			CLOCK_REALTIME,係統的實際時間,當係統時間改變時,會發生跳變
5.1 struct hrtimer_cpu_base {
	raw_spinlock_t			lock;
	struct hrtimer_clock_base	clock_base[HRTIMER_MAX_CLOCK_BASES];//當前cpu的時鍾基礎
#ifdef CONFIG_HIGH_RES_TIMERS
	ktime_t				expires_next;	//下一次事件到期的絕對時間
	int				hres_active;		//高分辨率狀態
	int				hang_detected;		//最近一次hrtimer檢測到掛起
	unsigned long			nr_events;	//中斷事件總數
	unsigned long			nr_retries;	//有效的中斷事件總數
	unsigned long			nr_hangs;	//中斷掛起的次數
	ktime_t				max_hang_time;	//中斷處理程序hrtimer_interrupt可花費的最大時間
#endif
}; 

//	時鍾基礎數據結構
//		hrtimer組織成紅黑樹的形式
5.2 struct hrtimer_clock_base {
	struct hrtimer_cpu_base	*cpu_base;
	clockid_t		index;			//用於區分CLOCK_MONOTONIC,CLOCK_REALTIME
	struct rb_root		active;		//所有活躍的hrtimer組織在紅黑樹中,active指向其樹根
	struct rb_node		*first;		//第一個到期的hrtimer
	ktime_t			resolution;		//時鍾基礎的分辨率,納秒為單位
	ktime_t			(*get_time)(void);	//讀取該時鍾基礎的時間
	ktime_t			softirq_time;	//在軟中斷中開始運行hrtimer的時間
#ifdef CONFIG_HIGH_RES_TIMERS
	ktime_t			offset;			//時鍾相對於單調時鍾的偏移
#endif
};

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

  上一篇:go 時間子係統2_tick device管理機製
  下一篇:go 時間子係統8_動態時鍾(NO_HZ)