阅读434 返回首页    go 王者荣耀


时间子系统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
	hrtimer_peek_ahead_timers();
}

//	遍历运行hrtimer
//	函数任务:
//		1.关中断
//		2.运行hrtimer
//	调用路径:run_hrtimer_softirq->hrtimer_peek_ahead_timers
1.2 void hrtimer_peek_ahead_timers(void)
{
	unsigned long flags;
	//关中断
	local_irq_save(flags);
	hrtimer_interrupt(&__get_cpu_var(tick_cpu_device)->evtdev);
	local_irq_restore(flags);
}

//	高分辨率tick device事件处理函数
//		遍历执行本cpu上的hrtimer
//	调用路径:
//		1.run_hrtimer_softirq->....->hrtimer_interrupt 软中断路径。
//		2.当激活高分辨率模式时,安装此函数作为tick device的事件处理函数。
//	函数任务:
//		1.遍历时钟基础
//			1.1 运行到期的hrtimer
//		2.如果处理完所有hrtimer,关闭时钟事件设备,退出
//		3.重复步骤1,最多遍历3次
//		4.更新统计信息
//			4.1 cpu_base->nr_hangs统计一次hrtimer未能处理完所有hrtimer的次数
//			4.2 cpu_base->hang_detected指示有hrtimer待处理
//			4.3 cpu_base->max_hang_time记录hrtimer_interrupt花费的最大时间,即hrtimer可能被延迟的最大时间
//		5.根据花费的时间计算时钟事件设备下一次到期的时间
//			5.1 如果处理hrtimer花费时间超过1ms,推迟下一次到期时间为1ms后
//			5.2 否则下一次到期时间为花费的时间
1.3 void hrtimer_interrupt(struct clock_event_device *dev)
{
	struct hrtimer_cpu_base *cpu_base = &__get_cpu_var(hrtimer_bases);
	struct hrtimer_clock_base *base;
	ktime_t expires_next, now, entry_time, delta;
	int i, retries = 0;

	cpu_base->nr_events++;
	dev->next_event.tv64 = KTIME_MAX;

	entry_time = now = ktime_get();
retry:
	expires_next.tv64 = KTIME_MAX;
	//防止此段时间内其他cpu的hrtimer迁移到本cpu时
	raw_spin_lock(&cpu_base->lock);
	cpu_base->expires_next.tv64 = KTIME_MAX;
	base = cpu_base->clock_base;
	//遍历所有时钟基础的hrtime
	for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++) {
		ktime_t basenow;
		struct rb_node *node;
		//时钟基础的时间与实际时间可能有偏移,hrtimer的到期时间为实际时间的绝对值
		basenow = ktime_add(now, base->offset);

		while ((node = base->first)) {
			struct hrtimer *timer;

			timer = rb_entry(node, struct hrtimer, node);
			//如果当前hrtimer还没有到期
			if (basenow.tv64 < hrtimer_get_softexpires_tv64(timer)) {
				ktime_t expires;
				//更新时钟事件下一次到期时间
				expires = ktime_sub(hrtimer_get_expires(timer),
						    base->offset);
				if (expires.tv64 < expires_next.tv64)
					expires_next = expires;
				break;
			}
			//否则立即执行定时器
			__run_hrtimer(timer, &basenow);
		}
		base++;
	}

	//更新时钟基础下一次到期时间
	cpu_base->expires_next = expires_next;
	raw_spin_unlock(&cpu_base->lock);

	//没有要到期的hrtimer,关闭时间事件设备
	if (expires_next.tv64 == KTIME_MAX ||
	    !tick_program_event(expires_next, 0)) {
		cpu_base->hang_detected = 0;
		return;
	}

	//防止一直处理hrtimer,最大遍历次数3
	now = ktime_get();
	cpu_base->nr_retries++;
	if (++retries < 3)
		goto retry;
	//有挂起的hrtimer需要处理
	cpu_base->nr_hangs++;
	cpu_base->hang_detected = 1;
	//计算hrtimer_interrupt处理hrtimer花费的时间
	delta = ktime_sub(now, entry_time);
	if (delta.tv64 > cpu_base->max_hang_time.tv64)
		cpu_base->max_hang_time = delta;
	//根据花费的时间计算时钟事件设备下一次到期的时间
	//	如果处理hrtimer花费时间超过1ms,推迟下一次到期时间为1ms后
	//	否则下一次到期时间为花费的时间
	if (delta.tv64 > 100 * NSEC_PER_MSEC)
		expires_next = ktime_add_ns(now, 100 * NSEC_PER_MSEC);
	else
		expires_next = ktime_add(now, delta);
	tick_program_event(expires_next, 1);

}
//	运行hrtimer
//	调用路径:hrtimer_interrupt->__run_hrtimer
//	函数任务:
//		1.从红黑树中删除hrtimer
//		2.设置其为执行状态
//		3.执行hrtimer回调函数
//			3.1 如果hrtimer需要继续执行,重新建hrtimer加入到红黑树中
//		4.清除其正在执行标志
1.4 static void __run_hrtimer(struct hrtimer *timer, ktime_t *now)
{
	struct hrtimer_clock_base *base = timer->base;
	struct hrtimer_cpu_base *cpu_base = base->cpu_base;
	enum hrtimer_restart (*fn)(struct hrtimer *);
	int restart;

	//从红黑树中删除hrtimer,设置其为执行状态
	__remove_hrtimer(timer, base, HRTIMER_STATE_CALLBACK, 0);
	fn = timer->function;

	raw_spin_unlock(&cpu_base->lock);
	//执行hrtimer回调函数
	restart = fn(timer);
	raw_spin_lock(&cpu_base->lock);
	//将hrtimer重新入队
	if (restart != HRTIMER_NORESTART) {
		enqueue_hrtimer(timer, base);
	}
	//清除其正在执行标志
	timer->state &= ~HRTIMER_STATE_CALLBACK;
}


//	运行高分辨率定时器
//	调用路径:
//		update_process_times->run_local_timers->hrtimer_run_queues
//		当没有开启高分辨率模式时,高分辨率定时器由低分辨率时钟软中断调用,此函数在低分辨率中衔接高分辨率
//	函数任务:
//		1.检查高分辨率率定时器框架是否已经被激活
//			1.1 当高分辨率定时器框架被激活时,hrtimer已经通过hrtimer_interrupt被运行
//		2.获取当前时间
//		3.遍历时钟基础,如果hrtimer到期,运行其回调函数
//	注:
//		当高分辨率率定时器框架为激活时,高分辨率定时器通过时钟中断运行,频率为jiffiy。
2.1 void hrtimer_run_queues(void)
{
	struct timerqueue_node *node;
	struct hrtimer_cpu_base *cpu_base = &__get_cpu_var(hrtimer_bases);
	struct hrtimer_clock_base *base;
	int index, gettime = 1;
	//如果高分辨率定时器框架已经激活,则hrtimer已经通过hrtimer_interrupt被运行,直接返回
	if (hrtimer_hres_active())
		return;
	//遍历cpu的时钟基础,运行到期的hrtimer
	for (index = 0; index < HRTIMER_MAX_CLOCK_BASES; index++) {
		base = &cpu_base->clock_base[index];
		//当前时钟基础已经没有active的hrtimer,则遍历下一个
		if (!timerqueue_getnext(&base->active))
			continue;
		//获取当前时间
		if (gettime) {
			hrtimer_get_softirq_time(cpu_base);
			gettime = 0;
		}

		raw_spin_lock(&cpu_base->lock);
		//获取下一个active的hrtimer
		while ((node = timerqueue_getnext(&base->active))) {
			struct hrtimer *timer;

			timer = container_of(node, struct hrtimer, node);
			//如果hrtimer到期,则运行其回调函数
			if (base->softirq_time.tv64 <=
					hrtimer_get_expires_tv64(timer))
				break;

			__run_hrtimer(timer, &base->softirq_time);
		}
		raw_spin_unlock(&cpu_base->lock);
	}
}

最后更新:2017-04-03 14:54:27

  上一篇:go SQL Server 2005企业版下载一已亲自下载安装,下载速度暴快!
  下一篇:go 思维导图Minimanager9 “参数错误”问题