时间子系统13_clockevent周期触发模式

简介:
//	设置clockevent周期处理函数
//	函数参数:
//		broadcast,指示此设备是否为全局广播设备
//	调用路径:tick_setup_periodic->tick_set_periodic_handler
1.1 void tick_set_periodic_handler(struct clock_event_device *dev, int broadcast)
{
	if (!broadcast)
		dev->event_handler = tick_handle_periodic;
	else
		dev->event_handler = tick_handle_periodic_broadcast;
}

//	clockevent周期处理函数(非广播设备)
//	函数任务:
//		1.执行周期任务
//		2.如果设备为单触发模式
//			2.1 重编程下一次事件到期时间
2.1 void tick_handle_periodic(struct clock_event_device *dev)
{
	int cpu = smp_processor_id();
	ktime_t next;
	//执行do_timer更新全局事件,更新进程时间
	tick_periodic(cpu);
	//周期模式不需要手动设置下次到期时间,直接退出
	if (dev->mode != CLOCK_EVT_MODE_ONESHOT)
		return;
	//计算下次到期时间
	next = ktime_add(dev->next_event, tick_period);
	for (;;) {
		//重编程设备事件到期
		if (!clockevents_program_event(dev, next, ktime_get()))
			return;
		//重新编程设备失败,说明已经经过一个tick周期,此时执行tick周期任务
		if (timekeeping_valid_for_hres())
			tick_periodic(cpu);
		//更新下次到期时间
		next = ktime_add(next, tick_period);
	}
}
//	周期处理函数
//	函数任务:
//		1.如果本cpu负责更新全局时间
//			1.1 执行do_timer
//		2.更新进程运行时间
//			2.1 通知调度器更新其虚拟时钟
//			2.2 更新进程cpu上执行时间
//	调用路径:tick_handle_periodic->tick_periodic
2.2 static void tick_periodic(int cpu)
{
	//本cpu负责更新全局时间
	if (tick_do_timer_cpu == cpu) {
		write_seqlock(&xtime_lock);
		//计算下个周期
		tick_next_period = ktime_add(tick_next_period, tick_period);
		//执行do_timer
		do_timer(1);
		write_sequnlock(&xtime_lock);
	}
	//更新进程时间
	update_process_times(user_mode(get_irq_regs()));
}
//	更新全局时间
//	函数任务:
//		1.更新jiffies
//		2.更新墙上时间
//		3.cpu间负载均衡
//	调用路径:tick_periodic->do_timer
2.3 void do_timer(unsigned long ticks)
{
	jiffies_64 += ticks;
	update_wall_time();
	calc_global_load();
}

//	clockevent周期处理函数(广播设备)
//	函数任务:
//		1.执行本cpu的事件处理函数
//		2.通过ipi通知代理的cpu,执行时间处理函数
//		3.重新编程下次事件的到期时间
3.1 static void tick_handle_periodic_broadcast(struct clock_event_device *dev)
{
	ktime_t next;
	//执行事件处理函数
	tick_do_periodic_broadcast();
	//重编程下次事件的到期时间
	if (dev->mode == CLOCK_EVT_MODE_PERIODIC)
		return;
	for (next = dev->next_event; ;) {
		next = ktime_add(next, tick_period);

		if (!clockevents_program_event(dev, next, ktime_get()))
			return;
		tick_do_periodic_broadcast();
	}
}
//	执行事件处理函数
//	函数任务:
//		1.通过tick_broadcast_mask掩码获取代理的cpu
//		2.执行事件处理函数
//	调用路径:tick_handle_periodic_broadcast->tick_do_periodic_broadcast
3.2 static void tick_do_periodic_broadcast(void)
{
	raw_spin_lock(&tick_broadcast_lock);
	//通过tick_broadcast_mask掩码获取代理的cpu
	cpumask_and(to_cpumask(tmpmask),
		    cpu_online_mask, tick_get_broadcast_mask());
	//对代理的cpu执行事件处理函数
	tick_do_broadcast(to_cpumask(tmpmask));
	raw_spin_unlock(&tick_broadcast_lock);
}
//	执行事件处理函数
//	函数任务:
//		1.执行本cpu的事件处理函数
//		2.通过ipi通知代理的cpu,执行事件处理函数
//	调用路径:tick_handle_periodic_broadcast->...->tick_do_broadcast
3.3 static void tick_do_broadcast(struct cpumask *mask)
{
	int cpu = smp_processor_id();
	struct tick_device *td;
	//检查当前cpu是否在掩码
	if (cpumask_test_cpu(cpu, mask)) {
		//从掩码中清除本cpu
		cpumask_clear_cpu(cpu, mask);
		td = &per_cpu(tick_cpu_device, cpu);
		//执行事件处理函数	
		td->evtdev->event_handler(td->evtdev);
	}
	//检查是否有其他cpu需要被代理
	if (!cpumask_empty(mask)) {
		//通过ipi通知其他cpu执行时钟事件处理函数
		td = &per_cpu(tick_cpu_device, cpumask_first(mask));
		td->evtdev->broadcast(mask);
	}
}
//	x86下lapic,clockevent->broadcast函数
//	函数任务:
//		通过ipi通知目标cpu执行事件处理函数
3.4 static void lapic_timer_broadcast(const struct cpumask *mask)
{
#ifdef CONFIG_SMP
	//所有需要通知的cpu均在mask掩码中
	apic->send_IPI_mask(mask, LOCAL_TIMER_VECTOR);
#endif
}

目录
相关文章
|
5月前
|
存储
高效定时器设计方案——层级时间轮
高效定时器设计方案——层级时间轮
64 2
|
程序员 API 数据安全/隐私保护
Flink--8、时间语义、水位线(事件和窗口、水位线和窗口的工作原理、生产水位线、水位线的传递、迟到数据的处理)
Flink--8、时间语义、水位线(事件和窗口、水位线和窗口的工作原理、生产水位线、水位线的传递、迟到数据的处理)
|
5月前
|
运维 Java Serverless
函数计算产品使用问题之是否会受执行超时时间的限制
函数计算产品作为一种事件驱动的全托管计算服务,让用户能够专注于业务逻辑的编写,而无需关心底层服务器的管理与运维。你可以有效地利用函数计算产品来支撑各类应用场景,从简单的数据处理到复杂的业务逻辑,实现快速、高效、低成本的云上部署与运维。以下是一些关于使用函数计算产品的合集和要点,帮助你更好地理解和应用这一服务。
|
12月前
|
Serverless 数据库
FC函数计算开启闲置模式以后解冻CPU时间过长
FC函数计算开启闲置模式以后解冻CPU时间过长问题
104 1
|
Windows
连续时间系统的冲激响应和零状态响应
连续时间系统的冲激响应和零状态响应
221 0
|
Java 程序员 调度
线程的创建方式,状态周期管理
进程是计算机中的程序,关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。
118 0
线程的创建方式,状态周期管理
通过定时器T1查询方式控制LED1周期性闪烁(自由计数模式)
通过定时器T1查询方式控制LED1周期性闪烁(自由计数模式) 宏定义与函数声明 初始化 主函数
280 0
|
C# Windows Java
C#实现定时器的几种方案
前几天写了一篇java的定时器方案,应小伙伴的要求,今天这里一下c#实现定时器的方案。 在C#里关于定时器类就有三个 1、System.Windows.Forms.Timer 2、System.Threading.Timer 3、定义在System.Timers.Timer 下面对这三个类进行讲解。
2670 0
|
存储 Apache 流计算
Flink 1.8.0中的状态生存时间特性:如何自动清理应用程序的状态
在本文中,我们将讨论引入状态生存时间特性的动机并讨论其相关用例。此外,我们还将演示如何使用和配置该特性。同时,我们将会解释Flink如何借用状态生存时间特性在内部管理状态,并对Flink 1.8.0中该功能引入的相关新特性进行一些展示。本文章最后对未来的改进和扩展作了展望。
1574 0