時間子係統7_高分辨率定時器處理
// 高分辨率下的定時器軟中斷 // 當增加一個hrtimer到rbtree中後,會raise高分辨率定時器軟中斷 // 函數任務: // 1.關中斷下,運行所有hrtimer // 注: // 在hrtimers_init中,open_softirq(HRTIMER_SOFTIRQ, run_hrtimer_softirq); 1.1 static void run_hrtimer_softirq(struct softirq_action *h) { //遍曆運行所有到期的hrtimer hrtimer_peek_ahead_timers(); } // 遍曆運行hrtimer // 函數任務: // 1.關中斷 // 2.運行hrtimer // 調用路徑:run_hrtimer_softirq->hrtimer_peek_ahead_timers 1.2 void hrtimer_peek_ahead_timers(void) { unsigned long flags; //關中斷 local_irq_save(flags); hrtimer_interrupt(&__get_cpu_var(tick_cpu_device)->evtdev); local_irq_restore(flags); } // 高分辨率tick device事件處理函數 // 遍曆執行本cpu上的hrtimer // 調用路徑: // 1.run_hrtimer_softirq->....->hrtimer_interrupt 軟中斷路徑。 // 2.當激活高分辨率模式時,安裝此函數作為tick device的事件處理函數。 // 函數任務: // 1.遍曆時鍾基礎 // 1.1 運行到期的hrtimer // 2.如果處理完所有hrtimer,關閉時鍾事件設備,退出 // 3.重複步驟1,最多遍曆3次 // 4.更新統計信息 // 4.1 cpu_base->nr_hangs統計一次hrtimer未能處理完所有hrtimer的次數 // 4.2 cpu_base->hang_detected指示有hrtimer待處理 // 4.3 cpu_base->max_hang_time記錄hrtimer_interrupt花費的最大時間,即hrtimer可能被延遲的最大時間 // 5.根據花費的時間計算時鍾事件設備下一次到期的時間 // 5.1 如果處理hrtimer花費時間超過1ms,推遲下一次到期時間為1ms後 // 5.2 否則下一次到期時間為花費的時間 1.3 void hrtimer_interrupt(struct clock_event_device *dev) { struct hrtimer_cpu_base *cpu_base = &__get_cpu_var(hrtimer_bases); struct hrtimer_clock_base *base; ktime_t expires_next, now, entry_time, delta; int i, retries = 0; cpu_base->nr_events++; dev->next_event.tv64 = KTIME_MAX; entry_time = now = ktime_get(); retry: expires_next.tv64 = KTIME_MAX; //防止此段時間內其他cpu的hrtimer遷移到本cpu時 raw_spin_lock(&cpu_base->lock); cpu_base->expires_next.tv64 = KTIME_MAX; base = cpu_base->clock_base; //遍曆所有時鍾基礎的hrtime for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++) { ktime_t basenow; struct rb_node *node; //時鍾基礎的時間與實際時間可能有偏移,hrtimer的到期時間為實際時間的絕對值 basenow = ktime_add(now, base->offset); while ((node = base->first)) { struct hrtimer *timer; timer = rb_entry(node, struct hrtimer, node); //如果當前hrtimer還沒有到期 if (basenow.tv64 < hrtimer_get_softexpires_tv64(timer)) { ktime_t expires; //更新時鍾事件下一次到期時間 expires = ktime_sub(hrtimer_get_expires(timer), base->offset); if (expires.tv64 < expires_next.tv64) expires_next = expires; break; } //否則立即執行定時器 __run_hrtimer(timer, &basenow); } base++; } //更新時鍾基礎下一次到期時間 cpu_base->expires_next = expires_next; raw_spin_unlock(&cpu_base->lock); //沒有要到期的hrtimer,關閉時間事件設備 if (expires_next.tv64 == KTIME_MAX || !tick_program_event(expires_next, 0)) { cpu_base->hang_detected = 0; return; } //防止一直處理hrtimer,最大遍曆次數3 now = ktime_get(); cpu_base->nr_retries++; if (++retries < 3) goto retry; //有掛起的hrtimer需要處理 cpu_base->nr_hangs++; cpu_base->hang_detected = 1; //計算hrtimer_interrupt處理hrtimer花費的時間 delta = ktime_sub(now, entry_time); if (delta.tv64 > cpu_base->max_hang_time.tv64) cpu_base->max_hang_time = delta; //根據花費的時間計算時鍾事件設備下一次到期的時間 // 如果處理hrtimer花費時間超過1ms,推遲下一次到期時間為1ms後 // 否則下一次到期時間為花費的時間 if (delta.tv64 > 100 * NSEC_PER_MSEC) expires_next = ktime_add_ns(now, 100 * NSEC_PER_MSEC); else expires_next = ktime_add(now, delta); tick_program_event(expires_next, 1); } // 運行hrtimer // 調用路徑:hrtimer_interrupt->__run_hrtimer // 函數任務: // 1.從紅黑樹中刪除hrtimer // 2.設置其為執行狀態 // 3.執行hrtimer回調函數 // 3.1 如果hrtimer需要繼續執行,重新建hrtimer加入到紅黑樹中 // 4.清除其正在執行標誌 1.4 static void __run_hrtimer(struct hrtimer *timer, ktime_t *now) { struct hrtimer_clock_base *base = timer->base; struct hrtimer_cpu_base *cpu_base = base->cpu_base; enum hrtimer_restart (*fn)(struct hrtimer *); int restart; //從紅黑樹中刪除hrtimer,設置其為執行狀態 __remove_hrtimer(timer, base, HRTIMER_STATE_CALLBACK, 0); fn = timer->function; raw_spin_unlock(&cpu_base->lock); //執行hrtimer回調函數 restart = fn(timer); raw_spin_lock(&cpu_base->lock); //將hrtimer重新入隊 if (restart != HRTIMER_NORESTART) { enqueue_hrtimer(timer, base); } //清除其正在執行標誌 timer->state &= ~HRTIMER_STATE_CALLBACK; } // 運行高分辨率定時器 // 調用路徑: // update_process_times->run_local_timers->hrtimer_run_queues // 當沒有開啟高分辨率模式時,高分辨率定時器由低分辨率時鍾軟中斷調用,此函數在低分辨率中銜接高分辨率 // 函數任務: // 1.檢查高分辨率率定時器框架是否已經被激活 // 1.1 當高分辨率定時器框架被激活時,hrtimer已經通過hrtimer_interrupt被運行 // 2.獲取當前時間 // 3.遍曆時鍾基礎,如果hrtimer到期,運行其回調函數 // 注: // 當高分辨率率定時器框架為激活時,高分辨率定時器通過時鍾中斷運行,頻率為jiffiy。 2.1 void hrtimer_run_queues(void) { struct timerqueue_node *node; struct hrtimer_cpu_base *cpu_base = &__get_cpu_var(hrtimer_bases); struct hrtimer_clock_base *base; int index, gettime = 1; //如果高分辨率定時器框架已經激活,則hrtimer已經通過hrtimer_interrupt被運行,直接返回 if (hrtimer_hres_active()) return; //遍曆cpu的時鍾基礎,運行到期的hrtimer for (index = 0; index < HRTIMER_MAX_CLOCK_BASES; index++) { base = &cpu_base->clock_base[index]; //當前時鍾基礎已經沒有active的hrtimer,則遍曆下一個 if (!timerqueue_getnext(&base->active)) continue; //獲取當前時間 if (gettime) { hrtimer_get_softirq_time(cpu_base); gettime = 0; } raw_spin_lock(&cpu_base->lock); //獲取下一個active的hrtimer while ((node = timerqueue_getnext(&base->active))) { struct hrtimer *timer; timer = container_of(node, struct hrtimer, node); //如果hrtimer到期,則運行其回調函數 if (base->softirq_time.tv64 <= hrtimer_get_expires_tv64(timer)) break; __run_hrtimer(timer, &base->softirq_time); } raw_spin_unlock(&cpu_base->lock); } }
最後更新:2017-04-03 14:54:27