時間子係統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