时间子系统11_tsc时钟初始化

简介:
//	tsc时钟源初始化
//	调用路径:time_init->tsc_init
//	函数任务:
//		1.矫正tsc,获取tsc频率,设置cpu频率等于tsc频率
//		2.初始化基于tsc的延迟函数
//		3.检查tsc的特性
//			3.1 tsc之间是否同步
//				3.1.1 如果tsc之间不同步,标记tsc不稳定,设置rating=0
//			3.2 tsc是否稳定
//		4.注册tsc时钟源设备
1.1 void __init tsc_init(void)
{
	u64 lpj;
	int cpu;

	//矫正tsc,获取tsc频率
	tsc_khz = x86_platform.calibrate_tsc();
	//cpu频率等于tsc频率
	cpu_khz = tsc_khz;
	//计算辅助cycle到ns转换的辅助参数scale
	for_each_possible_cpu(cpu)
		set_cyc2ns_scale(cpu_khz, cpu);
	//初始化基于tsc的延迟函数,ndely,udelay,mdelay
	use_tsc_delay();
	//检查cpu之间tsc是否同步
	if (unsynchronized_tsc())
		mark_tsc_unstable("TSCs unsynchronized");
	//检查tsc是否可靠
	check_system_tsc_reliable();
	//注册tsc时钟源设备
	init_tsc_clocksource();
}

//	延迟函数ndelay,udelay,mdelay
//		通过tsc实现短延迟
2.1 void use_tsc_delay(void)
{
	//通过tsc进行短延迟
	delay_fn = delay_tsc;
}
//	tsc延迟函数
//		通过rep_nop实现轮询时的短延迟,查询tsc时禁止内核抢占,确保不受不同cpu间影响。
2.2 static void delay_tsc(unsigned long loops)
{
	unsigned long bclock, now;
	int cpu;
	//短延迟,禁止内核抢占
	preempt_disable();
	//delay_tsc当前运行的cpu
	cpu = smp_processor_id();
	rdtsc_barrier();
	rdtscl(bclock);
	for (;;) {
		rdtsc_barrier();
		rdtscl(now);
		if ((now - bclock) >= loops)
			break;
		//允许rt策略进程运行
		preempt_enable();
		//空操作
		rep_nop();
		preempt_disable();

		//delay_tsc在运行过程中,可能会迁移到不同的cpu
		//tsc
		if (unlikely(cpu != smp_processor_id())) {
			loops -= (now - bclock);
			cpu = smp_processor_id();
			rdtsc_barrier();
			rdtscl(bclock);
		}
	}
	preempt_enable();
} 

//	检查tsc是否同步
//	调用路径:tsc_init->unsynchronized_tsc
//	检查办法:
//		1.如果apic在多块板卡,则tsc不同步
//		2.如果cpuid显示具有稳定的tsc,则tsc同步
//		3.intel cpu的tsc都是同步的
//		4.默认其他品牌的多核的tsc不同步
3.1 __cpuinit int unsynchronized_tsc(void)
{
	//如果apic分布在多块板卡上,tsc可能不同步
	if (apic_is_clustered_box())
		return 1;
	//cpu具有稳定的tsc
	if (boot_cpu_has(X86_FEATURE_CONSTANT_TSC))
		return 0;
	//intel cpu的tsc都是同步的
	if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL) {
		//非intel cpu,如果cpu个数>1,则认为不同步
		if (num_possible_cpus() > 1)
			tsc_unstable = 1;
	}
	return tsc_unstable;
}

//	标记tsc不稳定
//	调用路径:tsc_init->mark_tsc_unstable
//	函数任务:
//		1.如果tsc时钟已经注册,异步设置tsc的rating=0,标识其不稳定
//		2.如果tsc时钟还未注册,同步设置tsc的rating=0,标识其不稳定
3.2 void mark_tsc_unstable(char *reason)
{
	if (!tsc_unstable) {
		tsc_unstable = 1;
		sched_clock_stable = 0;
		//tsc已经注册,
		if (clocksource_tsc.mult)
		{
			clocksource_mark_unstable(&clocksource_tsc);
		}
		//如果tsc时钟源未注册,修改rating为最低,从而不会被当做最佳的时钟源
		else {
			clocksource_tsc.flags |= CLOCK_SOURCE_UNSTABLE;
			clocksource_tsc.rating = 0;
		}
	}
}



//	注册tsc时钟源
//	函数任务:
//		1.计算tsc的mult
//		2.检查tsc是否稳定
//			2.1 如果tsc不稳定,降低其rating,清除时钟源连续标志
//		3.向系统注册tsc clocksource
//	调用路径:tsc_init->init_tsc_clocksource
4.1 static void __init init_tsc_clocksource(void)
{
	//计算tsc的mult
	clocksource_tsc.mult = clocksource_khz2mult(tsc_khz,
			clocksource_tsc.shift);
	//如果tsc的可靠性已经验证,则清除 必须验证 标记
	if (tsc_clocksource_reliable)
		clocksource_tsc.flags &= ~CLOCK_SOURCE_MUST_VERIFY;
	
	//检查tsc是否稳定
	//	在tsc_init前通过全局变量标记tsc是否稳定,可靠
	if (check_tsc_unstable()) {
		//如果tsc不稳定,则降低rating最低,清除连续标记
		clocksource_tsc.rating = 0;
		clocksource_tsc.flags &= ~CLOCK_SOURCE_IS_CONTINUOUS;
	}
	//向系统注册tsc clocksource
	clocksource_register(&clocksource_tsc);
}

目录
相关文章
|
Cloud Native 网络协议 数据中心
Overlay网络与Underlay网络:深入探索与全面对比
在当今云原生的世界中🌍☁️,网络是构建和维护任何分布式系统的基石💎。了解Overlay网络和Underlay网络及其之间的区别🔍,对于设计高效、可扩展的云原生应用至关重要🚀。本文旨在全面解析Overlay和Underlay网络,揭示它们的工作原理、优缺点,并说明何种情况下应该使用哪一种网络📚。
Overlay网络与Underlay网络:深入探索与全面对比
|
SQL JSON Prometheus
14-TDengine安装报警模块实现报警监测Webhook回调与邮件推送
14-TDengine安装报警模块实现报警监测Webhook回调与邮件推送
723 0
14-TDengine安装报警模块实现报警监测Webhook回调与邮件推送
|
缓存 自然语言处理 JavaScript
Web服务器的动态内容生成与处理
【8月更文第28天】在Web开发领域,动态内容生成是指根据用户请求实时生成页面内容的过程。这与静态内容生成不同,后者的内容在部署时就已经确定,不会随用户的请求而改变。动态内容生成通常依赖于服务器端脚本语言,例如PHP、Node.js等,它们能够根据不同的请求参数生成特定的响应数据。本文将探讨几种流行的服务器端脚本语言在动态网页生成中的作用及其优化方法,并提供相应的代码示例。
349 0
|
Ubuntu 前端开发 Linux
Linux 发行版 Debian 宣布支持龙芯 LoongArch 架构
近期,龙芯发布了3A6000桌面处理器,芯片的性能又一次大幅度提升,成为国产芯片的又一里程碑。Debian 社区开发者邮件显示,Debian Ports 添加了对龙芯LoongArch 架构的支持。
665 0
|
存储 SQL 运维
使用PowerShell进行自动化脚本编写:入门与实战
【6月更文挑战第6天】本文介绍了PowerShell作为Windows系统管理的自动化工具,用于提升效率和减少错误。内容涵盖PowerShell基础,如变量、命令执行、管道、条件和循环语句、函数。实战案例展示了如何用PowerShell脚本进行文件备份。此外,还提及PowerShell的进阶功能,如模块、远程管理和与其他工具集成。学习和应用PowerShell能有效提升IT运维自动化水平。
|
Shell 开发工具 git
git获取gitee老版本的分支内容
git获取gitee老版本的分支内容
235 0
|
开发工具 git
Git:error: remote origin already exists
Git:error: remote origin already exists
332 2
|
存储 程序员 C++
C++容器初始化方式详解:优缺点、性能与应用场景
C++容器初始化方式详解:优缺点、性能与应用场景
212 0
|
算法 C++ 开发者
【C/C++ 解惑 】std::weak_ptr 背后解决的问题
【C/C++ 解惑 】std::weak_ptr 背后解决的问题
223 0
面试官:如何关闭一个 TCP 连接?
今天聊一个比较轻松的问题:如何关闭一个 TCP 连接? 可能大家第一反应是「杀掉进程」不就行了吗? 是的,这个是最粗暴的方式,杀掉客户端进程和服务端进程影响的范围会有所不同: 在客户端杀掉进程的话,就会发送 FIN 报文,来断开这个客户端进程与服务端建立的所有 TCP 连接,这种方式影响范围只有这个客户端进程所建立的连接,而其他客户端或进程不会受影响。 而在服务端杀掉进程影响就大了,此时所有的 TCP 连接都会被关闭,服务端无法继续提供访问服务。