時間子係統4_低分辨率定時器處理
// 觸發低分辨率定時器軟中斷
// 調用路徑: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);
}
最後更新:2017-04-03 14:54:27