|
楼主 |
发表于 2012-8-26 19:54:22
|
显示全部楼层
Clock Event
Clock event的主要作用是分发clock事件及设置下一次触发条件. 在没有clock event之前,
时钟中断都是周期性地产生, 也就是熟知的jiffies和HZ.
Clock Event device主要的结构:
struct clock_event_device {
const char *name;
unsigned int features;
unsigned long max_delta_ns;
unsigned long min_delta_ns;
unsigned long mult;
int shift;
int rating;
int irq;
cpumask_t cpumask;
int (*set_next_event)(unsigned long evt,
struct clock_event_device *);
void (*set_mode)(enum clock_event_mode mode,
struct clock_event_device *);
void (*event_handler)(struct clock_event_device *);
void (*broadcast)(cpumask_t mask);
struct list_head list;
enum clock_event_mode mode;
ktime_t next_event;
};
最重要的是set_next_event(), event_handler(). 前者是设置下一个clock事件的触发条件,
一般就是往clock device里重设一下定时器. 后者是event handler, 事件处理函数.
该处理函数会在时钟中断ISR里被调用. 如果这个clock用来做为ticker时钟,
那么handler的执行和之前kernel的时钟中断ISR基本相同, 类似timer_tick().
事件处理函数可以在运行时动态替换, 这就给kernel一个改变整个时钟中断处理方式的机会,
也就给highres tick及dynamic tick一个动态挂载的机会.
目前kernel内部有periodic/highres/dynamic tick三种时钟中断处理方式. 后面会介绍.
hrtimer & timer wheel
首先说一下timer wheel. 它就是kernel一直采用的基于jiffies的timer机制,
接口包括init_timer(), mod_timer(), del_timer()等, 很熟悉把.
hrtimer 的出现, 并没有抛弃老的timer wheel机制(也不太可能抛弃).
hrtimer做为kernel里的timer定时器, 而timer wheel则主要用来做timeout定时器.
分工比较明确. hrtimers采用红黑树来组织timers, 而timer wheel采用链表和桶.
hrtimer精度由原来的timer wheel的jiffies提高到nanosecond.
主要用于向应用层提供nanosleep, posix-timers和itimer接口,
当然驱动和其他子系统也会需要high resolution的timer.
kernel 里原先每秒周期性地产生HZ个ticker(中断),
被在下一个过期的hrtimer的时间点上产生中断代替. 也就是说时钟中断不再是周期性的,
而是由timer来驱动(靠clockevent的set_next_event接口设置下一个事件中断),
只要没有hrtimer加载, 就没有中断. 但是为了保证系统时间(进程时间统计,
jiffies的维护)更新, 每个tick_period(NSEC_PER_SEC/HZ,
再次强调hrtimer精度是nsec)都会有一个叫做tick_sched_timer的hrtimer加载.
接下来对比一下, hrtimer引入之前及之后, kernel里时钟中断的处理的不同. (这里都是基于arm
arch的source去分析)
1)no hrtimer
kernel 起来, setup_arch()之后的time_init()会去初始化相应machine结构下的timer.
初始化timer函数都在各个machine的体系结构代码中, 初始化完硬件时钟, 注册中断服务函数,
使能时钟中断. 中断服务程序会清中断, 调用timer_tick(), 它执行:
1. profile_tick(); /* kernel profile, 不是很了解 */
2. do_timer(1); /* 更新jiffies */
3. update_process_times(); /* 计算进程耗时, 唤起TIMER_SOFTIRQ(timer wheel),
重新计算调度时间片等等 */
最后中断服务程序设置定时器, 使其在下一个tick产生中断.
这样的框架, 使得high-res的timer很难加入. 所有中断处理code都在体系结构代码里被写死,
并且代码重用率很低, 毕竟大多的arch都会写同样的中断处理函数.
|
|