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

	//高分辨率模式下,如果支持动态时钟,则需要检查是否本cpu负责更新全局时间
#ifdef CONFIG_NO_HZ
	//负责更新jiffies
	if (unlikely(tick_do_timer_cpu == TICK_DO_TIMER_NONE))
		tick_do_timer_cpu = cpu;
#endif

	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

}


//	低分辨率模式下的动态时钟事件处理函数
//		在低分辨率模式下开启动态时钟时,关闭周期时钟,由该函数处理时钟事件。
4.1 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();

	dev->next_event.tv64 = KTIME_MAX;
	//由本cpu负责更新全局时间
	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);

	//idle状态停用了周期时钟,喂狗,防止误发生softlockup
	if (ts->tick_stopped) {
		touch_softlockup_watchdog();
		//更新idle状态持续的jiffies
		ts->idle_jiffies++;
	}
	//更新本cpu的时间
	update_process_times(user_mode(regs));
	profile_tick(CPU_PROFILING);
	//重编程下一个时钟事件到期时间
	while (tick_nohz_reprogram(ts, now)) {
		now = ktime_get();
		tick_do_update_jiffies64(now);
	}
}

目录
相关文章
|
4月前
|
前端开发 JavaScript
构建一个动态时钟
构建一个动态时钟
|
24天前
|
JavaScript
1.2MHz,固定频率白光LED驱动器
TX6216是一款高效升压转换器,适用于单节锂离子电池驱动7个串联的白光LED。它采用电流模式,1.2MHz固定频率操作,内置功率MOSFET,拥有低104mV反馈电压,提供欠压锁定、限流和热过载保护。此外,其软启动功能降低浪涌电流,小型封装节省空间并降低成本。主要应用于相机闪光灯、手机及数码相机等LED背光。设计中需注意电感、电容和二极管的选择,以及良好的布局以确保性能。
18 0
|
1月前
STM32CubeMX配置时钟无法使用高速外部时钟HSE
STM32CubeMX配置时钟无法使用高速外部时钟HSE
|
11月前
[STM32F10x] 利用定时器测量频率
[STM32F10x] 利用定时器测量频率
91 2
【蓝桥杯嵌入式】STM32定时器的配置,解析预分频系数和重装载值与时钟频率的关系
【蓝桥杯嵌入式】STM32定时器的配置,解析预分频系数和重装载值与时钟频率的关系
435 0
时钟频率是干什么的?底层原理是什么?
时钟频率是干什么的?底层原理是什么?
423 0
FBM232 P0926GW 异步CPU使用全局时钟信号
FBM232 P0926GW 异步CPU使用全局时钟信号
57 0
FBM232 P0926GW 异步CPU使用全局时钟信号
|
异构计算
实验二 基于FPGA的分频器的设计(基本任务:设计一个分频器,输入信号50MHz,输出信号频率分别为1KHz、500Hz及1Hz。拓展任务1:用按键或开关控制蜂鸣器的响与不响。拓展任务2:用按键或开)
实验二 基于FPGA的分频器的设计(基本任务:设计一个分频器,输入信号50MHz,输出信号频率分别为1KHz、500Hz及1Hz。拓展任务1:用按键或开关控制蜂鸣器的响与不响。拓展任务2:用按键或开)
886 0
实验二 基于FPGA的分频器的设计(基本任务:设计一个分频器,输入信号50MHz,输出信号频率分别为1KHz、500Hz及1Hz。拓展任务1:用按键或开关控制蜂鸣器的响与不响。拓展任务2:用按键或开)
|
Unix Linux 定位技术
Linux: 硬件时钟, 系统时钟, 网络时钟, 时区修改和同步
Linux: 硬件时钟, 系统时钟, 网络时钟, 时区修改和同步
1545 0
Linux: 硬件时钟, 系统时钟, 网络时钟, 时区修改和同步