// 高分辨率定时器框架初始化 // 调用路径: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 };
时间: 2024-08-03 23:54:52