|
如果CPU可以響應(yīng)中斷,但是在長時間內(nèi)不能調(diào)度(比如禁止搶占時間太長),此時就需要一種機(jī)制(softlockup)來檢測這種情形。 本文基于3.14.25 記錄下第二種比較嚴(yán)重的“死鎖”:禁止搶占的時間太長,此時依舊可以相應(yīng)中斷,但是本CPU上在長時間內(nèi)沒有發(fā)生調(diào)度。 reset_init
|-->kernel_thread(kernel_init, NULL, CLONE_FS | CLONE_SIGHAND);
kernel_init
|-->kernel_init_freeable();
|-->lockup_detector_init();
|-->watchdog_enable_all_cpus(false);
|-->smpboot_register_percpu_thread(&watchdog_threads);
static struct smp_hotplug_thread watchdog_threads = {
.store = &softlockup_watchdog,
.thread_should_run = watchdog_should_run,
.thread_fn = watchdog,
.thread_comm = "watchdog/%u",
.setup = watchdog_enable,
};
smpboot_register_percpu_thread(&watchdog_threads)
|-->__smpboot_create_thread(&watchdog_threads, cpu);
創(chuàng)建了一個線程A task,該線程的主函數(shù)為 smpboot_thread_fun,該線程存儲于watchdog_threads.store中 過程(閱讀smpboot_thread_fn): 1、調(diào)用setup:watchdog_enable; 2、調(diào)用thread_should_run:watchdog_should_run判定是否需要運行線程主函數(shù) 3、線程主函數(shù)thread_fn:watchdog watchdog_enable |-->struct hrtimer *hrtimer = &__raw_get_cpu_var(watchdog_hrtimer); |-->hrtimer->function = watchdog_timer_fn; |-->hrtimer_start(hrtimer, ns_to_ktime(sample_period), HRTIMER_MODE_REL_PINNED); |-->watchdog_set_prio(SCHED_FIFO, MAX_RT_PRIO - 1);//實時優(yōu)先級 這個函數(shù)比較重要,因為: A task中主函數(shù)為smpboot_thread_fun,其中將會檢測是否運行thread_fn:watchdog watchdog_should_run |-->return __this_cpu_read(hrtimer_interrupts) != __this_cpu_read(soft_lockup_hrtimer_cnt); 因此如果hrtimer_interrupts == soft_lockup_hrtimer_cnt成立則運行調(diào)度器(放棄CPU使用權(quán)),否則運行thread_fn:watchdog 我們看下thread_fn的職責(zé): watchdog: |-->__this_cpu_write(soft_lockup_hrtimer_cnt, __this_cpu_read(hrtimer_interrupts)); |--> __this_cpu_write(watchdog_touch_ts, get_timestamp()); 再看下hrtimer定時的職責(zé): static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer) |-->unsigned long touch_ts = __this_cpu_read(watchdog_touch_ts); |-->__this_cpu_inc(hrtimer_interrupts); 記錄hrtimer中斷次數(shù) |-->wake_up_process(__this_cpu_read(softlockup_watchdog));//喚醒創(chuàng)建的 A task,雖然被喚醒,但并不意味著就能得到調(diào)度 |-->hrtimer_forward_now(hrtimer, ns_to_ktime(sample_period)); |-->duration = is_softlockup(touch_ts);//判定當(dāng)前時間與touch_ts的時間差是否超過20s, | 如果超過,說明發(fā)生了softlockup,否則說明沒有發(fā)生。
總結(jié):更新watchdog_touch_ts的是一個具有實時優(yōu)先級的線程A task,既然是線程就存在是否得到調(diào)度的問題。如果在20s內(nèi),該線程沒有得到調(diào)度,則說
|
|
|