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

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

	if (tick_check_oneshot_change(!hrtimer_is_hres_enabled()))
	{
		//切换到高分辨率模式
		hrtimer_switch_to_hres();
	}
}

//	切换低分辨率模式的动态时钟
//	函数任务:
//		1.更新tick device单触发方式,安装nohz事件处理函数
//		2.初始化动态时钟数据结构
//			2.1 标识动态时钟当前为低分辨率模式
//			2.2 动态时钟通过单调时钟基础管理
//			2.3 更新动态时钟到期时间
//		3.更新动态时钟,tick device到期时间
2.1 static void tick_nohz_switch_to_nohz(void)
{
	struct tick_sched *ts = &__get_cpu_var(tick_cpu_sched);
	ktime_t next;
	local_irq_disable();

	//更新tick device单触发方式,安装nohz事件处理函数
	if (tick_switch_to_oneshot(tick_nohz_handler)) {
		local_irq_enable();
		return;
	}
	//低分辨率动态时钟标识
	ts->nohz_mode = NOHZ_MODE_LOWRES;

	//低分辨率动态时钟依赖单调时钟
	hrtimer_init(&ts->sched_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
	//下次到期时间
	next = tick_init_jiffy_update();

	//更新动态时钟,tick device到期时间
	for (;;) {
		hrtimer_set_expires(&ts->sched_timer, next);
		if (!tick_program_event(next, 0))
			break;
		next = ktime_add(next, tick_period);
	}
	local_irq_enable();

}
//	低分辨率动态事件处理函数
//	函数任务:
//		1.选择cpu负责更新jiffies
//		2.如果距离上次更新jiffies已经有1 jiffy,更新jiffies
//		3.如果动态时钟已经停止,说明当前在idle状态,喂狗,防止发生softlockup
//		4.更新当前进程的运行时间
//		6.更新动态时钟的下个周期时间
//		7.重编程tick device在动态时钟的下个周期时间到期
//	注:tick_do_timer_cpu 保存负责更新jiffies的cpu
2.2 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();
	//保证tick device在最近的时间内不会到期
	dev->next_event.tv64 = KTIME_MAX;
	//选择cpu负责更新jiffies
	if (unlikely(tick_do_timer_cpu == TICK_DO_TIMER_NONE))
		tick_do_timer_cpu = cpu;

	//更新jiffies
	if (tick_do_timer_cpu == cpu)
		tick_do_update_jiffies64(now);
	//动态时钟停止,说明当前在idle状态,喂狗,防止发生softlockup
	if (ts->tick_stopped) {
		touch_softlockup_watchdog();
		ts->idle_jiffies++;
	}

	//更新进程的运行时间
	update_process_times(user_mode(regs));
	//重编程clockevent设备
	while (tick_nohz_reprogram(ts, now)) {
		now = ktime_get();
		tick_do_update_jiffies64(now);
	}
}


//	切换高分辨率模式
//	函数任务:
//		1.更新clockevent为单触发模式,安装高分辨率事件处理程序
//		2.初始化动态时钟
//			2.1 更新高分辨率激活标志
//			2.2 更新时钟基础为高分辨率标志
//		3.初始化动态时钟
//		4.更新tick device到期时间为时钟基础中所有hrtimer最短的到期时间
3.1 static int hrtimer_switch_to_hres(void)
{
	int cpu = smp_processor_id();
	struct hrtimer_cpu_base *base = &per_cpu(hrtimer_bases, cpu);
	unsigned long flags;

	local_irq_save(flags);

	//更新clockevent为单触发模式,安装高分辨率事件处理程序
	if (tick_init_highres()) {
		local_irq_restore(flags);
		return 0;
	}
	//高分辨率激活标志
	base->hres_active = 1;
	base->clock_base[CLOCK_REALTIME].resolution = KTIME_HIGH_RES;
	base->clock_base[CLOCK_MONOTONIC].resolution = KTIME_HIGH_RES;
	//初始化动态时钟
	tick_setup_sched_timer();
	//更新tick device到期时间为时钟基础中所有hrtimer最短的到期时间
	retrigger_next_event(NULL);
	local_irq_restore(flags);
	return 1;
}

//	更新clockevnet为单触发模式,安装事件处理程序
//	调用路径:hrtimer_switch_to_hres->tick_switch_to_oneshot
3.2 int tick_init_highres(void)
{
	return tick_switch_to_oneshot(hrtimer_interrupt);
}

//	更新clockevnet为单触发模式,安装事件处理程序
//	调用路径:hrtimer_switch_to_hres->...->tick_switch_to_oneshot
//	函数任务:
//		1.更新设备为单触发方式
//		2.安装事件处理程序
//		3.更新广播设备为单触发方式
3.3 int tick_switch_to_oneshot(void (*handler)(struct clock_event_device *))
{
	struct tick_device *td = &__get_cpu_var(tick_cpu_device);
	struct clock_event_device *dev = td->evtdev;
	//更新设备为单触发方式
	td->mode = TICKDEV_MODE_ONESHOT;
	//安装事件处理程序
	dev->event_handler = handler;
	//编程clockevent设备为单触发方式
	clockevents_set_mode(dev, CLOCK_EVT_MODE_ONESHOT);
	//切换广播设备为单触发方式
	tick_broadcast_switch_to_oneshot();
	return 0;
}

//	初始化动态时钟
//	调用路径:hrtimer_switch_to_hres->tick_setup_sched_timer
//	函数任务:
//		1.初始化动态时钟的hrtimer
//		2.安装动态时钟的回调函数
//		3.更新动态时钟下一个jiffies到期
3.4 void tick_setup_sched_timer(void)
{
	struct tick_sched *ts = &__get_cpu_var(tick_cpu_sched);
	ktime_t now = ktime_get();
	u64 offset;
	//初始化hrtimer
	hrtimer_init(&ts->sched_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
	//动态时钟的回调函数
	ts->sched_timer.function = tick_sched_timer;
	//下一个jiffies到期
	hrtimer_set_expires(&ts->sched_timer, tick_init_jiffy_update());
	offset = ktime_to_ns(tick_period) >> 1;
	do_div(offset, num_possible_cpus());
	offset *= smp_processor_id();
	hrtimer_add_expires_ns(&ts->sched_timer, offset);

	//编程启动动态时钟
	for (;;) {
		hrtimer_forward(&ts->sched_timer, now, tick_period);
		hrtimer_start_expires(&ts->sched_timer,
				      HRTIMER_MODE_ABS_PINNED);
		if (hrtimer_active(&ts->sched_timer))
			break;
		now = ktime_get();
	}
	....
}

目录
相关文章
|
4月前
|
编解码 人工智能 测试技术
无需训练,这个新方法实现了生成图像尺寸、分辨率自由
【4月更文挑战第25天】研究人员提出FouriScale方法,解决了扩散模型在生成高分辨率图像时的结构失真问题。通过膨胀卷积和低通滤波,该方法实现不同分辨率下图像的结构和尺度一致性,无需重新训练模型。实验显示FouriScale在保持图像真实性和完整性的同时,能生成任意尺寸的高质量图像,尤其在处理高宽比图像时表现出色。尽管在极高分辨率生成上仍有局限,但为超高清图像合成技术提供了新思路。[链接: https://arxiv.org/abs/2403.12963]
54 5
|
传感器 编解码 监控
工业相机的帧率和曝光(快门)之间的关系
工业相机的帧率和曝光(快门)之间的关系
795 0
|
14天前
|
存储 安全 Linux
高分辨率定时器和动态时钟设计笔记 【ChatGPT】
高分辨率定时器和动态时钟设计笔记 【ChatGPT】
|
1月前
51开发板独立按键调节时钟的应用实验、可以使用独立按键进行时间的调节(可对时间重新自定义)
51开发板独立按键调节时钟的应用实验、可以使用独立按键进行时间的调节(可对时间重新自定义)
|
2月前
|
传感器 数据采集 算法
LabVIEW中PID控制器系统的噪声与扰动抑制策略
LabVIEW中PID控制器系统的噪声与扰动抑制策略
55 21
|
2月前
|
数据采集 存储 数据处理
LabVIEW利用旋转编码器脉冲触发数据采集
LabVIEW利用旋转编码器脉冲触发数据采集
36 0
|
4月前
|
数据采集 数据处理
LabVIEW编码器自动校准系统
LabVIEW编码器自动校准系统
33 3
|
4月前
|
编解码 缓存
LabVIEW最快能以什么速率采集图像
LabVIEW最快能以什么速率采集图像
30 0
|
4月前
LabVIEW连续采样与有限采样模式
LabVIEW连续采样与有限采样模式
133 0
|
4月前
|
机器学习/深度学习 编解码 异构计算
ELAN:用于图像超分辨率的高效远程注意力网络
ELAN:用于图像超分辨率的高效远程注意力网络
133 1