820
技术社区[云栖]
时间子系统6_高分辨率定时器框架初始化
// 高分辨率定时器框架初始化
// 调用路径:start_kernel->hrtimers_init
// 函数任务:
// 1.创建cpu时钟基础
// 2.注册监听cpu状态变化
// 3.注册高分辨率模式下的定时器软中断
// 注:
// 1.高分辨率定时器框架的通用部分总是编译进内核
// 2.高分辨率定时器框架初始为未激活状态,由低分辨率定时器软中断中切换到高分辨率
1.1 void __init hrtimers_init(void)
{
//通知clockevent设备管理,创建cpu时钟基础
hrtimer_cpu_notify(&hrtimers_nb, (unsigned long)CPU_UP_PREPARE,
(void *)(long)smp_processor_id());
//注册监听cpu 状态信息
register_cpu_notifier(&hrtimers_nb);
//高分辨率定时功能通过预处理编译进内核
#ifdef CONFIG_HIGH_RES_TIMERS
//注册高分辨率模式下的定时器软中断
open_softirq(HRTIMER_SOFTIRQ, run_hrtimer_softirq);
#endif
}
// cpu状态监听控制块
2.1 static struct notifier_block __cpuinitdata hrtimers_nb = {
.notifier_call = hrtimer_cpu_notify,
};
// 处理cpu状态变化
// 函数任务:
// 1.cpu up,初始化cpu的时钟基础
// 2.针对热插拔cpu
// 2.1 cpu dying、frozen,选择cpu,接管do_timer
// 2.2 cpu dead、frozen
// 2.2.1 通知clockevent设备管理,cpu dead
// 2.2.2 迁移dead cpu上的hrtimer到本cpu
3.1 static int __cpuinit hrtimer_cpu_notify(struct notifier_block *self,
unsigned long action, void *hcpu)
{
int scpu = (long)hcpu;
switch (action)
{
//cpu up,初始化此cpu的时钟基础
case CPU_UP_PREPARE:
case CPU_UP_PREPARE_FROZEN:
init_hrtimers_cpu(scpu);
break;
//下列情况只针对热插拔cpu
#ifdef CONFIG_HOTPLUG_CPU
case CPU_DYING:
case CPU_DYING_FROZEN:
//选择cpu接管do_timer
clockevents_notify(CLOCK_EVT_NOTIFY_CPU_DYING, &scpu);
break;
case CPU_DEAD:
case CPU_DEAD_FROZEN:
//通知clockevent设备管理,cpu dead
clockevents_notify(CLOCK_EVT_NOTIFY_CPU_DEAD, &scpu);
//迁移cpu上的定时任务到本cpu
migrate_hrtimers(scpu);
break;
#endif
default:
break;
}
return NOTIFY_OK;
}
// 初始化cpu的时钟基础
// 函数任务:
// 1.初始化REALTIME、MONOTOMIC两个时钟基础
// 2.更新时钟基础到期时间为KTIME_MAX,即没有hrtimer会到期
// 3.更新高分辨率定时器未激活状态
// 调用路径:init_hrtimers_cpu->init_hrtimers_cpu
4.1 static void __cpuinit init_hrtimers_cpu(int cpu)
{
//per cpu时钟基础设备,用于维护该cpu的hrtimer
struct hrtimer_cpu_base *cpu_base = &per_cpu(hrtimer_bases, cpu);
int i;
raw_spin_lock_init(&cpu_base->lock);
//初始化cpu时钟基础
for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++)
cpu_base->clock_base[i].cpu_base = cpu_base;
hrtimer_init_hres(cpu_base);
}
4.2 static inline void hrtimer_init_hres(struct hrtimer_cpu_base *base)
{
//下一次事件到期的绝对时间,KTIME_MAX表示没有hrtimer会到期
base->expires_next.tv64 = KTIME_MAX;
//高分辨率未激活状态
base->hres_active = 0;
}
// cpu时钟基础数据结构
// 提供两种时钟基础
// CLOCK_MONOTOMIC,系统启动时从0开始,不会跳变,始终单调的运行
// CLOCK_REALTIME,系统的实际时间,当系统时间改变时,会发生跳变
5.1 struct hrtimer_cpu_base {
raw_spinlock_t lock;
struct hrtimer_clock_base clock_base[HRTIMER_MAX_CLOCK_BASES];//当前cpu的时钟基础
#ifdef CONFIG_HIGH_RES_TIMERS
ktime_t expires_next; //下一次事件到期的绝对时间
int hres_active; //高分辨率状态
int hang_detected; //最近一次hrtimer检测到挂起
unsigned long nr_events; //中断事件总数
unsigned long nr_retries; //有效的中断事件总数
unsigned long nr_hangs; //中断挂起的次数
ktime_t max_hang_time; //中断处理程序hrtimer_interrupt可花费的最大时间
#endif
};
// 时钟基础数据结构
// hrtimer组织成红黑树的形式
5.2 struct hrtimer_clock_base {
struct hrtimer_cpu_base *cpu_base;
clockid_t index; //用于区分CLOCK_MONOTONIC,CLOCK_REALTIME
struct rb_root active; //所有活跃的hrtimer组织在红黑树中,active指向其树根
struct rb_node *first; //第一个到期的hrtimer
ktime_t resolution; //时钟基础的分辨率,纳秒为单位
ktime_t (*get_time)(void); //读取该时钟基础的时间
ktime_t softirq_time; //在软中断中开始运行hrtimer的时间
#ifdef CONFIG_HIGH_RES_TIMERS
ktime_t offset; //时钟相对于单调时钟的偏移
#endif
};
最后更新:2017-04-03 14:54:29
上一篇:
时间子系统2_tick device管理机制
下一篇:
时间子系统8_动态时钟(NO_HZ)
天气预报执行计划及完成程度+简单而又不简单获取当前时间和解析农历时间的纯JAVA代码
每年14PB数据存储需求,海量交通安全数据如何安放?
判断用户输入的数字是一个合法的电话号码的正则表达式
PostgreSQL Oracle兼容性 - 计算字符长度与字节长度(char(?) 与varchar(?)空格如何计算长度)
[WCF权限控制]基于Windows用户组的授权方式[下篇]
生产者消费者模式浅析
SQL Server vs Oracle 简单语法比较
VS2010运行速度优化
2009.06.18 20:00天体15号球场连中六个三分,四个NBA三分,要多锻炼!
“分布式事务”的理解(适用于访问多个数据库之间)