Overview
3种机制时钟源:struct clocksource, 时间管理的基础,提供单调递增的counter,精度取决于底层硬件时钟事件设备 : struct clocl_event_device, 也称时钟事件源,可以设定在未来的某个时刻发生,通过中断通知系统时钟设备 : 扩展了时钟事件源的功能,提供一个时钟事件的连续流,各个时钟事件定时触发,如果使用动态时钟(只有在有些任务需要实际执行时,才激活周期时钟),可以在一定时间间隔内停止周期时钟。 两种时钟类型局部时钟:每个CPU一个,用来进行进程统计,性能剖析和实现高分辨率定时器,有可能在进入DEEP IDLE的时候不能正常工作,这个时候需要broadcast timer的协助全局时钟 : 负责更新时钟周期,主要是用于更新jiffies值,可以由单独的硬件来负责,也可以由局部时钟中的某一个来负责
用于时间管理的对象
时间表示ktimer_t,参考头文件 ktime.h 时钟源
struct clocksource {
char *name;
struct list_head list;
int rating;
cycle_t (*read)(void);
cycle_t mask;
u32 mult;
u32 shift;
unsigned long flags
}
list : 用于将所有的时钟源连接到一个标准的内核链表上rating : 时钟质量,内核会优先选用最好的cyc2ns : 将cycle转换成ns (cycles * mult >> shift)使用clocksource_register将时钟源注册到系统中 时钟事件设备
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;
}
event_handler : 时间过期时由体系结构相关代码调用,将时钟事件传递到时间子系统层cpumask : 设备所服务的CPU, 局部时钟通常只负责一个CPUbroadcast : 实现广播机制,用于进入DEEP IDLE是会停止工作的局部时钟list : 将相关实例保存到clockevent_devices上clockevents_register_device注册一个新的时钟事件设备features :
CLOCK_EVT_FEAT_PERIODIC : 按固定周期触发CLOCK_EVT_FEAT_ONESHOT : 只触发一次 clockevents_program_event(struct clock_event_device *dev, ktime_t expires, ktime_t now) 时钟设备
struct tick_device {
struct clock_event_device *evtdev;
enum tick_device_mode mode;
}
enum tick_device_mode {
TICKDEV_MODE_PERIODIC,
TICKDEV_MODE_ONESHOT
}
注册一个新的时钟事件设备时,内核会自动创建一个时钟设备。tick_cpu_device : Per-CPU链表,包含了系统中每个CPU对应的struct tick_device实例tick_next_peroid : 下一个全局时钟事件发生的时间tick_do_timer_cpu : 负责全局时钟的CPU编号tick_period : 时钟周期的长度,单位为nstick_setup_device
Y
N
Y
N
Y
N
tick_notify
tick_check_new_device
tick_setup_device
!td->evtdev
update tick_do_timer_cpu
td->mode = TICKDEV_MODE_PERIODIC
handler = td->evtdev->event_handler
td->evtdev = newdev
td->mode == TICKDEV_MODE_PERIODIC
tick_setup_periodic
tick_setup_oneshot
tick_set_periodic_handler
!broadcast
dev->event_handler = tick_handle_periodic
dev->event_handler = tick_handle_periodic_broadcast
newdev->event_handler = hrtimer_interrupt/tick_nohz_handler