时间子系统4_低分辨率定时器处理

//	触发低分辨率定时器软中断
//	调用路径:update_process_times->run_local_timers
//	注:
//		1.update_process_times以HZ频率被调用,因此低分辨率定时器的分辨率为HZ
//		2.当未激活高分辨率定时器框架时,高分辨率定时器在时钟中断被运行,因此高分辨率定时器的分辨率也HZ
1.1 void run_local_timers(void)
{
	//如果高分辨率定时器框架未激活,则在周期时钟中断中运行高分辨率率定时器
	hrtimer_run_queues();
	//触发低分辨率定时器软中断
	raise_softirq(TIMER_SOFTIRQ);
}

//	低分辨率定时器软中断
//	函数任务:
//		1.尝试切换低分辨率动态时钟模式、或高分辨率模式
//		2.运行到期的timer_list
//	注:
//		1.timer_list的分辨率为jiffies
2.1 static void run_timer_softirq(struct softirq_action *h)
{
	//per-cpu tvec_base
	struct tvec_base *base = __get_cpu_var(tvec_bases);
	//尝试切换低分辨率动态时钟模式、或高分辨率模式
	hrtimer_run_pending();
	//执行到期的timer_list
	if (time_after_eq(jiffies, base->timer_jiffies))
		__run_timers(base);
}

//	运行本cpu到期的timer_list
//	函数任务:
//		1.如果tvec_root 遍历了一遍
//			1.1 从tv中移动timer_list向前补充
//		2.更新timer_jiffies
//		3.设置base->running_timer,表示当前cpu上正在运行的timer_list
//		4.开中断下运行到期的timer_list的函数
//		5.清空base->running_timer
2.2 static inline void __run_timers(struct tvec_base *base)
{
	struct timer_list *timer;

	spin_lock_irq(&base->lock);
	while (time_after_eq(jiffies, base->timer_jiffies)) {
		struct list_head work_list;
		struct list_head *head = &work_list;
		//tvec_root 255个位置的索引
		int index = base->timer_jiffies & TVR_MASK;
		//tvec_root已经遍历了一遍,tv向前补充timer_list
		if (!index &&
			(!cascade(base, &base->tv2, INDEX(0))) &&
				(!cascade(base, &base->tv3, INDEX(1))) &&
					!cascade(base, &base->tv4, INDEX(2)))
			cascade(base, &base->tv5, INDEX(3));
		//更新timer_jiffies,运行timer_list
		++base->timer_jiffies;
		//取当前jiffies对应的list
		list_replace_init(base->tv1.vec + index, &work_list);
		while (!list_empty(head)) {
			void (*fn)(unsigned long);
			unsigned long data;

			timer = list_first_entry(head, struct timer_list,entry);
			fn = timer->function;
			data = timer->data;
			//设置base->running_timer,表示当前cpu上正在运行的timer_list
			set_running_timer(base, timer);
			//将timer_list从链表上取下
			detach_timer(timer, 1);
			//开中断运行timer_list
			spin_unlock_irq(&base->lock);
			{
				//执行timer_list函数
				fn(data);
			}
			spin_lock_irq(&base->lock);
		}
	}
	//设置base->running_timer=null
	set_running_timer(base, NULL);
	spin_unlock_irq(&base->lock);
}

//	计算tv对应的bit区间
2.3 #define INDEX(N) ((base->timer_jiffies >> (TVR_BITS + (N) * TVN_BITS)) & TVN_MASK)
;
//	向上一级tv补充timer_list
//	函数任务:
//		1.取当前jiffies对应tv中的timer_list
//		2.将timer_list从链表删除,根据当前jiffies计算timer_list应该移动到的tv
2.4 static int cascade(struct tvec_base *base, struct tvec *tv, int index)
{
	struct timer_list *timer, *tmp;
	struct list_head tv_list;

	//取当前jiffies对应tv中的timer_list链表
	list_replace_init(tv->vec + index, &tv_list);
	//将timer_list从链表中删除,计算新位置
	list_for_each_entry_safe(timer, tmp, &tv_list, entry) {
		internal_add_timer(base, timer);
	}
	return index;
}
//	根据当前jiffies移动timer_list
//	函数任务:
//		1.计算timer_list的到期时间相对目前已经到期timer_list的偏移量
//		2.根据偏移量确定对应的tv,以及tv内的链表
//		3.将timer_list加入到相应tv的链表中
2.5 static void internal_add_timer(struct tvec_base *base, struct timer_list *timer)
{
	unsigned long expires = timer->expires;
	//timer_list的到期时间相对目前已经到期timer_list的偏移量
	unsigned long idx = expires - base->timer_jiffies;
	struct list_head *vec;
	//确定idx对应的tv
	if (idx < TVR_SIZE) {
		int i = expires & TVR_MASK;
		vec = base->tv1.vec + i;
	} else if (idx < 1 << (TVR_BITS + TVN_BITS)) {
		int i = (expires >> TVR_BITS) & TVN_MASK;
		vec = base->tv2.vec + i;
	} else if (idx < 1 << (TVR_BITS + 2 * TVN_BITS)) {
		int i = (expires >> (TVR_BITS + TVN_BITS)) & TVN_MASK;
		vec = base->tv3.vec + i;
	} else if (idx < 1 << (TVR_BITS + 3 * TVN_BITS)) {
		int i = (expires >> (TVR_BITS + 2 * TVN_BITS)) & TVN_MASK;
		vec = base->tv4.vec + i;
	} else if ((signed long) idx < 0) {
		vec = base->tv1.vec + (base->timer_jiffies & TVR_MASK);
	} else {
		int i;
		if (idx > 0xffffffffUL) {
			idx = 0xffffffffUL;
			expires = idx + base->timer_jiffies;
		}
		i = (expires >> (TVR_BITS + 3 * TVN_BITS)) & TVN_MASK;
		vec = base->tv5.vec + i;
	}
	//将timer_list加入到相应tv的链表中
	list_add_tail(&timer->entry, vec);
}
时间: 2024-10-22 03:28:05

时间子系统4_低分辨率定时器处理的相关文章

Linux时间子系统之七:定时器的应用--msleep(),hrtimer_nanosleep()【转】

  转自:http://blog.csdn.net/droidphone/article/details/8104433 我们已经在前面几章介绍了低分辨率定时器和高精度定时器的实现原理,内核为了方便其它子系统,在时间子系统中提供了一些用于延时或调度的API,例如msleep,hrtimer_nanosleep等等,这些API基于低分辨率定时器或高精度定时器来实现,本章的内容就是讨论这些方便.好用的API是如何利用定时器系统来完成所需的功能的. /*************************

时间子系统6_高分辨率定时器框架初始化

// 高分辨率定时器框架初始化 // 调用路径:start_kernel->hrtimers_init // 函数任务: // 1.创建cpu时钟基础 // 2.注册监听cpu状态变化 // 3.注册高分辨率模式下的定时器软中断 // 注: // 1.高分辨率定时器框架的通用部分总是编译进内核 // 2.高分辨率定时器框架初始为未激活状态,由低分辨率定时器软中断中切换到高分辨率 1.1 void __init hrtimers_init(void) { //通知clockevent设备管理,创建

时间子系统3_低分辨率定时框架初始化

// 低分辨率定时器框架初始化 // 调用路径:start_kernel->init_timers // 函数任务: // 1.创建当前cpu的定时器框架数据结构 // 2.监听cpu状态信息 // 3.注册低分辨率软中断 1.1 void __init init_timers(void) { //创建当前cpu的定时器框架数据结构 int err = timer_cpu_notify(&timers_nb, (unsigned long)CPU_UP_PREPARE, (void *)(l

时间子系统7_高分辨率定时器处理

// 高分辨率下的定时器软中断 // 当增加一个hrtimer到rbtree中后,会raise高分辨率定时器软中断 // 函数任务: // 1.关中断下,运行所有hrtimer // 注: // 在hrtimers_init中,open_softirq(HRTIMER_SOFTIRQ, run_hrtimer_softirq); 1.1 static void run_hrtimer_softirq(struct softirq_action *h) { //遍历运行所有到期的hrtimer h

时间子系统5_低分辨率切换高分辨率

// 切换低分辨率动态时钟模式.或高分辨率模式 // 调用路径:run_timer_softirq->hrtimer_run_pending // 函数任务: // 1.如果高分辨率定时器框架已经激活,则直接返回 // 2.切换到高分辨率模式的条件: // 2.1 没有开启低分辨率动态时钟 // 2.2 有高分辨率的clocksource // 2.3 clockevent设备支持单触发模式 // 3.切换到低分辨率动态时钟的条件: // 3.1 启动时,没有激活高分辨率率定时框架 // 3.2

Linux时间子系统之八:动态时钟框架(CONFIG_NO_HZ、tickless)【转】

转自:http://blog.csdn.net/droidphone/article/details/8112948 版权声明:本文为博主原创文章,未经博主允许不得转载.   目录(?)[-] 数据结构 低分辨率下的动态时钟 1  切换至动态时钟模式 2  低分辨率动态时钟下的事件中断处理函数 3  动态时钟停止周期tick时钟事件 3  动态时钟重新开启周期tick时钟事件 高精度模式下的动态时钟 动态时钟对中断的影响   在前面章节的讨论中,我们一直基于一个假设:Linux中的时钟事件都是由

时间子系统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 enu

时间子系统9_timekeeper初始化

//Timekeeping // Timekeeping子系统负责更新xtime, 调整误差, 及提供get/settimeofday接口. //Times in Kernel //kernel的time基本类型: // 1) system time // A monotonically increasing value that represents the amount of time the system has been running. // 单调增长的系统运行时间, 可以通过time

时间子系统17_hard lockup机制

// 使能hard lockup探测 // 调用路径:watchdog_enable->watchdog_nmi_enable // 函数任务: // 1.初始化hard lockup检测事件 // 2.hard lockup阈值为10s // 2.向performance monitoring子系统注册hard lockup检测事件 // 3.使能hard lockup检测事件 // 注: // performance monitoring,x86中的硬件设备,当cpu clock经过了指定个