时间子系统9_timekeeper初始化

//Timekeeping
//	Timekeeping子系统负责更新xtime, 调整误差, 及提供get/settimeofday接口.
//Times in Kernel
//kernel的time基本类型:
//	1) system time
//		A monotonically increasing value that represents the amount of time the system has been running.
//		单调增长的系统运行时间, 可以通过time source, xtime及wall_to_monotonic计算出来.
//	2) wall time
//		A value representing the the human time of day, as seen on a wrist-watch. Realtime时间: xtime.
//	3) time source
//		A representation of a free running counter running at a known frequency, usually in hardware, e.g GPT.
//		可以通过clocksource->read()得到counter值
//	4) tick
//		A periodic interrupt generated by a hardware-timer, typically with a fixed interval defined by HZ: jiffies
//	这些time之间互相关联, 互相可以转换:
//		system_time = xtime + cyc2ns(clock->read() - clock->cycle_last) + wall_to_monotonic;
//		real_time = xtime + cyc2ns(clock->read() - clock->cycle_last)
//		也就是说real time是从1970年开始到现在的nanosecond, 而system time是系统启动到现在的nanosecond.
//		这两个是最重要的时间, 由此hrtimer可以基于这两个time来设置过期时间. 所以引入两个clock base.
//	参考:http://blog.csdn.net/hongjiujing/article/details/7070746

//	全局timekeeper
1.1 struct timekeeper timekeeper;
//	timekeeper框架初始化
//		初始化clocksource
//	调用路径:start_kernel->timekeeping_init
//	函数任务:
//		1.使用默认时间源初始化全局timekeeper
//		2.初始化墙上时间xtime
//		3.初始化wall_to_monotonic,使其与xtime相加得到系统启动以来的单调时间
//	注:
//		Network Time Protocol(NTP)是用来使计算机时间同步化的一种协议,
//		它可以使计算机对其服务器或时钟源(如石英钟,GPS等等)做同步化,
//		它可以提供高精准度的时间校正(LAN上与标准间差小于1毫秒,WAN上几十毫秒).
1.2 static void __init timekeeping_init(void)
{
	struct clocksource *clock;
	unsigned long flags;
	struct timespec now, boot;
	//通过cmos获取当前时间
	read_persistent_clock(&now);
	//系统启动时的时间
	read_boot_clock(&boot);
	write_seqlock_irqsave(&xtime_lock, flags);
	//ntp初始化
	ntp_init();
	//x86架构下默认的时钟源,jiffies_clocksource
	clock = clocksource_default_clock();
	//使能时钟源
	if (clock->enable)
		clock->enable(clock);
	//使用clocksource初始化全局timekeeper
	timekeeper_setup_internals(clock);
	//初始化墙上时间
	xtime.tv_sec = now.tv_sec;
	xtime.tv_nsec = now.tv_nsec;
	raw_time.tv_sec = 0;
	raw_time.tv_nsec = 0;
	//如果体系结构没有提供read_boot_clock,设置启动时间为当前时间
	if (boot.tv_sec == 0 && boot.tv_nsec == 0) {
		boot.tv_sec = xtime.tv_sec;
		boot.tv_nsec = xtime.tv_nsec;
	}
	//通过将wall_to_monotonic加到xtime,获取系统启动以来的单调时间
	set_normalized_timespec(&wall_to_monotonic,
				-boot.tv_sec, -boot.tv_nsec);

	total_sleep_time.tv_sec = 0;
	total_sleep_time.tv_nsec = 0;
	write_sequnlock_irqrestore(&xtime_lock, flags);
}

//	timekeeper初始化
//	函数任务:
//		1.绑定timekeeper到clocksource
//		2.换算NTP间隔为clocksource的cycle
//	调用路径:timekeeping_init->timekeeper_setup_internals
//	注:
//		1.timekeeper.cycle_interval,一个NTP间隔对应的时钟cycle
//		2.timekeeper.xtime_interval, 一个NTP间隔对应的时钟cycle*mult
//		3.timekeeper.raw_interval,	一个NTP间隔(近似值)
1.3 static void timekeeper_setup_internals(struct clocksource *clock)
{
	cycle_t interval;
	u64 tmp;
	//timekeeper使用提供的时钟源
	timekeeper.clock = clock;
	clock->cycle_last = clock->read(clock);

	//NTP_INTERVAL_LENGTH转换为clocksource的cycle
	tmp = NTP_INTERVAL_LENGTH;
	tmp <<= clock->shift;
	tmp += clock->mult/2;
	do_div(tmp, clock->mult);
	if (tmp == 0)
		tmp = 1;

	//一个NTP间隔对应的时钟cycle
	interval = (cycle_t) tmp;
	timekeeper.cycle_interval = interval;

	//一个NTP间隔对应的xtime间隔
	timekeeper.xtime_interval = (u64) interval * clock->mult;
	//
	timekeeper.raw_interval =
		((u64) interval * clock->mult) >> clock->shift;

	timekeeper.xtime_nsec = 0;
	//使用时钟源的shift
	timekeeper.shift = clock->shift;
	//累积的时间相对于NTP的误差
	timekeeper.ntp_error = 0;
	timekeeper.ntp_error_shift = NTP_SCALE_SHIFT - clock->shift;
	timekeeper.mult = clock->mult;

}
时间: 2024-11-02 14:47:45

时间子系统9_timekeeper初始化的相关文章

Linux时间子系统之八:动态时钟框架(CONFIG_NO_HZ、tickless)【转】

转自:http://blog.csdn.net/droidphone/article/details/8112948 版权声明:本文为博主原创文章,未经博主允许不得转载.   目录(?)[-] 数据结构 低分辨率下的动态时钟 1  切换至动态时钟模式 2  低分辨率动态时钟下的事件中断处理函数 3  动态时钟停止周期tick时钟事件 3  动态时钟重新开启周期tick时钟事件 高精度模式下的动态时钟 动态时钟对中断的影响   在前面章节的讨论中,我们一直基于一个假设:Linux中的时钟事件都是由

linux子系统的初始化_subsys_initcall()【转】

转自:http://my.oschina.net/u/572632/blog/305492 目录[-] 概述 section的声明 注册 调用 IN BUILDING 概述        内核选项的解析完成之后,各个子系统的初始化即进入第二部分-入口函数的调用.通常USB.PCI这样的子系统都会有一个名为subsys_initcall的入口,如果你选择它们作为研究内核的切入点,那么就请首先找到它. section的声明     C 语言中attribute属性的section是在目标文件链接时可

Linux时间子系统之七:定时器的应用--msleep(),hrtimer_nanosleep()【转】

  转自:http://blog.csdn.net/droidphone/article/details/8104433 我们已经在前面几章介绍了低分辨率定时器和高精度定时器的实现原理,内核为了方便其它子系统,在时间子系统中提供了一些用于延时或调度的API,例如msleep,hrtimer_nanosleep等等,这些API基于低分辨率定时器或高精度定时器来实现,本章的内容就是讨论这些方便.好用的API是如何利用定时器系统来完成所需的功能的. /*************************

时间子系统6_高分辨率定时器框架初始化

// 高分辨率定时器框架初始化 // 调用路径:start_kernel->hrtimers_init // 函数任务: // 1.创建cpu时钟基础 // 2.注册监听cpu状态变化 // 3.注册高分辨率模式下的定时器软中断 // 注: // 1.高分辨率定时器框架的通用部分总是编译进内核 // 2.高分辨率定时器框架初始为未激活状态,由低分辨率定时器软中断中切换到高分辨率 1.1 void __init hrtimers_init(void) { //通知clockevent设备管理,创建

时间子系统3_低分辨率定时框架初始化

// 低分辨率定时器框架初始化 // 调用路径:start_kernel->init_timers // 函数任务: // 1.创建当前cpu的定时器框架数据结构 // 2.监听cpu状态信息 // 3.注册低分辨率软中断 1.1 void __init init_timers(void) { //创建当前cpu的定时器框架数据结构 int err = timer_cpu_notify(&timers_nb, (unsigned long)CPU_UP_PREPARE, (void *)(l

时间子系统10_hpet时钟初始化

// 时钟mult :mult/2^shift = ns/cyc // 参考:http://www.bluezd.info/archives/reg_clock_event_device_1 // x86平台初始化 // 注:arch/x86/kernel/x86_init.c 1.1 struct x86_init_ops x86_init __initdata = { ... //时钟初始化 .timers = { .setup_percpu_clockev = setup_boot_API

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

时间子系统1_lapic时钟初始化

// 参考:http://www.bluezd.info/archives/reg_clock_event_device_1 // x86平台初始化 // 注:arch/x86/kernel/x86_init.c 1.1 struct x86_init_ops x86_init __initdata = { ... //apic控制器初始化 .irqs = { .pre_vector_init = init_ISA_irqs, .intr_init = native_init_IRQ, .tra

时间子系统17_hard lockup机制

// 使能hard lockup探测 // 调用路径:watchdog_enable->watchdog_nmi_enable // 函数任务: // 1.初始化hard lockup检测事件 // 2.hard lockup阈值为10s // 2.向performance monitoring子系统注册hard lockup检测事件 // 3.使能hard lockup检测事件 // 注: // performance monitoring,x86中的硬件设备,当cpu clock经过了指定个