Linux时间子系统之clocksource的注册
来源:互联网 发布:ubuntu gcc 安装包 编辑:程序博客网 时间:2024/05/21 11:06
clocksource注册流程
clocksource_register / clocksource_register_hz / clocksource_register_khz __clocksource_register_scale __clocksource_updatefreq_scale clocks_calc_mult_shift /* 计算->mult和->shift */ clocksource_max_adjustment /* 计算->maxadj 11% */ clocksource_max_deferment /* 计算->max_idle_ns */ clocksource_enqueue clocksource_enqueue_watchdog clocksource_select一个问题是clocksource的->mult和->shift是如何确定的。clocksource_register由调用者直接指定,clocksource_register_hz和clocksource_register_khz则根据时钟源频率和->mult的最大位数按以下算法计算得到。
->mult与->shift的算法
nsecs = (cycles / F) * NSEC_PER_SEC = (cycles * mult) >> shift其中F为时钟频率,NSEC_PER_SEC为纳秒时钟频率,即10^9。将cycles=F带入上式,得
NSEC_PER_SEC = (F * mult) >> shift
根据频率单位可缩放scale(1为Hz,1000为KHz),得
NSEC_PER_SEC / scale = ((F / scale) * mult) >> shift
令to = NSEC_PER_SEC / scale,from = F / scale,得
to = (from * mult) >> shift
mult = (to << shift) / from
->shift的取值范围为[32:1],优先取大值,但须要确保->mult不超过有效位数。
for (sft = 32; sft > 0; sft--) { tmp = (u64)to << sft; tmp += from / 2; do_div(tmp, from); if ((tmp >> sftacc) == 0) break;}*mult = tmp;*shift = sft;
现在的问题是->mult的最大位数sftacc如何确定。
->mult最大位数的算法
若cycles小于32位,->mult最大32位;若cycles大于32位,->mult最大为64 - 最大10分钟cylces的位数。
u64 sec = (cs->mask - (cs->mask >> 3)); /* 最大cycles,减去12.5% */do_div(sec, freq); /*转换成秒或毫秒 */do_div(sec, scale); /* 转换成秒*/if (!sec) sec = 1;else if (sec > 600 && cs->mask > UINT_MAX) /* 若cycles大于32位,有10分钟限制;若cycles不大于32位,没有时间限制(因为最大32位左移不会导致溢出) */ sec = 600;u32 maxsec = sec * scale; /* 转换成秒或毫秒 */u32 sftacc = 32;u64 tmp = ((u64)maxsec * freq) >> 32;while (tmp) { tmp >>= 1; sftacc--;}
为什么有10分钟限制
首先看clocksource计数值与实际时间单位的转换关系
s64 clocksource_cyc2ns(cycle_t cycles, u32 mult, u32 shift){ return ((u64)cycles * mult) >> shift;}这里cycles是两次计数值增量,即->read()返回值与->cycle_last之差。
cycles和->mult都不能无限大,否则乘法结果溢出。内核需要限定一个更新->cycle_last的最大周期,10分钟被认为是合理的强制限定。因为从idle状态退出一定会更新->cycle_last,最大休眠时间->max_idle_ns可以通过以上得到的->mult计算出来。
max_cycles = 1ULL << (63 - (ilog2(cs->mult + cs->maxadj) + 1)); /* ->mult与cycles共同占用63位 */max_cycles = min_t(u64, max_cycles, (u64)cs->mask); /* 不超过有效位数 */max_nsecs = clocksource_cyc2ns(max_cycles, cs->mult - cs->maxadj, cs->shift);return max_nsecs - (max_nsecs >> 3);这里+1,11%的修正值和12.5%的余量都是防止溢出的保守的算法。
参考并感谢
http://blog.csdn.net/droidphone/article/details/7975694
- Linux时间子系统之clocksource的注册
- linux时间子系统 - clocksource/timekeeper
- Linux时间子系统(二) -- clocksource, timekeeper
- Linux时间管理之clocksource
- linux clocksource
- Linux时间子系统之三:时间的维护者:timekeeper
- Linux时间子系统之三:时间的维护者:timekeeper
- Linux时间子系统之三:时间的维护者:timekeeper
- Linux时间子系统之三:时间的维护者:timekeeper .
- Linux时间子系统之三:时间的维护者:timekeeper
- Linux时间子系统之三:时间的维护者:timekeeper
- Linux时间子系统之三:时间的维护者:timekeeper
- Linux时间子系统之三:时间的维护者:timekeeper
- Linux时间子系统之(一):时间的基本概念
- Linux时间子系统之三:时间的维护者:timekeeper
- Linux时间子系统之三:时间的维护者:timekeeper
- Linux时间子系统之(一):时间的基本概念
- Linux时间子系统之三:时间的维护者:timekeeper
- oracle中角色中权限剥离
- PuTTY and SSH Stuff
- acm 2096
- Vim 基本配置
- c++编写函数验证哥德巴赫猜想
- Linux时间子系统之clocksource的注册
- 服务器环境搭建
- 通用量规辅助设计程序更新说明
- 21个强大的Javascript框架
- 2013-2014学年第1学期软件工程和软件外包课程安排
- 聚类小文(一)
- 蓝桥杯第7题
- C# 根据SLIP协议封装报文
- 外设寄存器的访问