// 触发低分辨率定时器软中断 // 调用路径:update_process_times->run_local_timers // 注: // 1.update_process_times以HZ频率被调用,因此低分辨率定时器的分辨率为HZ // 2.当未激活高分辨率定时器框架时,高分辨率定时器在时钟中断被运行,因此高分辨率定时器的分辨率也HZ 1.1 void run_local_timers(void) { //如果高分辨率定时器框架未激活,则在周期时钟中断中运行高分辨率率定时器 hrtimer_run_queues(); //触发低分辨率定时器软中断 raise_softirq(TIMER_SOFTIRQ); } // 低分辨率定时器软中断 // 函数任务: // 1.尝试切换低分辨率动态时钟模式、或高分辨率模式 // 2.运行到期的timer_list // 注: // 1.timer_list的分辨率为jiffies 2.1 static void run_timer_softirq(struct softirq_action *h) { //per-cpu tvec_base struct tvec_base *base = __get_cpu_var(tvec_bases); //尝试切换低分辨率动态时钟模式、或高分辨率模式 hrtimer_run_pending(); //执行到期的timer_list if (time_after_eq(jiffies, base->timer_jiffies)) __run_timers(base); } // 运行本cpu到期的timer_list // 函数任务: // 1.如果tvec_root 遍历了一遍 // 1.1 从tv中移动timer_list向前补充 // 2.更新timer_jiffies // 3.设置base->running_timer,表示当前cpu上正在运行的timer_list // 4.开中断下运行到期的timer_list的函数 // 5.清空base->running_timer 2.2 static inline void __run_timers(struct tvec_base *base) { struct timer_list *timer; spin_lock_irq(&base->lock); while (time_after_eq(jiffies, base->timer_jiffies)) { struct list_head work_list; struct list_head *head = &work_list; //tvec_root 255个位置的索引 int index = base->timer_jiffies & TVR_MASK; //tvec_root已经遍历了一遍,tv向前补充timer_list if (!index && (!cascade(base, &base->tv2, INDEX(0))) && (!cascade(base, &base->tv3, INDEX(1))) && !cascade(base, &base->tv4, INDEX(2))) cascade(base, &base->tv5, INDEX(3)); //更新timer_jiffies,运行timer_list ++base->timer_jiffies; //取当前jiffies对应的list list_replace_init(base->tv1.vec + index, &work_list); while (!list_empty(head)) { void (*fn)(unsigned long); unsigned long data; timer = list_first_entry(head, struct timer_list,entry); fn = timer->function; data = timer->data; //设置base->running_timer,表示当前cpu上正在运行的timer_list set_running_timer(base, timer); //将timer_list从链表上取下 detach_timer(timer, 1); //开中断运行timer_list spin_unlock_irq(&base->lock); { //执行timer_list函数 fn(data); } spin_lock_irq(&base->lock); } } //设置base->running_timer=null set_running_timer(base, NULL); spin_unlock_irq(&base->lock); } // 计算tv对应的bit区间 2.3 #define INDEX(N) ((base->timer_jiffies >> (TVR_BITS + (N) * TVN_BITS)) & TVN_MASK) ; // 向上一级tv补充timer_list // 函数任务: // 1.取当前jiffies对应tv中的timer_list // 2.将timer_list从链表删除,根据当前jiffies计算timer_list应该移动到的tv 2.4 static int cascade(struct tvec_base *base, struct tvec *tv, int index) { struct timer_list *timer, *tmp; struct list_head tv_list; //取当前jiffies对应tv中的timer_list链表 list_replace_init(tv->vec + index, &tv_list); //将timer_list从链表中删除,计算新位置 list_for_each_entry_safe(timer, tmp, &tv_list, entry) { internal_add_timer(base, timer); } return index; } // 根据当前jiffies移动timer_list // 函数任务: // 1.计算timer_list的到期时间相对目前已经到期timer_list的偏移量 // 2.根据偏移量确定对应的tv,以及tv内的链表 // 3.将timer_list加入到相应tv的链表中 2.5 static void internal_add_timer(struct tvec_base *base, struct timer_list *timer) { unsigned long expires = timer->expires; //timer_list的到期时间相对目前已经到期timer_list的偏移量 unsigned long idx = expires - base->timer_jiffies; struct list_head *vec; //确定idx对应的tv if (idx < TVR_SIZE) { int i = expires & TVR_MASK; vec = base->tv1.vec + i; } else if (idx < 1 << (TVR_BITS + TVN_BITS)) { int i = (expires >> TVR_BITS) & TVN_MASK; vec = base->tv2.vec + i; } else if (idx < 1 << (TVR_BITS + 2 * TVN_BITS)) { int i = (expires >> (TVR_BITS + TVN_BITS)) & TVN_MASK; vec = base->tv3.vec + i; } else if (idx < 1 << (TVR_BITS + 3 * TVN_BITS)) { int i = (expires >> (TVR_BITS + 2 * TVN_BITS)) & TVN_MASK; vec = base->tv4.vec + i; } else if ((signed long) idx < 0) { vec = base->tv1.vec + (base->timer_jiffies & TVR_MASK); } else { int i; if (idx > 0xffffffffUL) { idx = 0xffffffffUL; expires = idx + base->timer_jiffies; } i = (expires >> (TVR_BITS + 3 * TVN_BITS)) & TVN_MASK; vec = base->tv5.vec + i; } //将timer_list加入到相应tv的链表中 list_add_tail(&timer->entry, vec); }