內核如何檢測SOFT LOCKUP與HARD LOCKUP?
所謂lockup,是指某段內核代碼占着CPU不放。Lockup嚴重的情況下會導致整個系統失去響應。Lockup有幾個特點:
-
首先只有內核代碼才能引起lockup,因為用戶代碼是可以被搶占的,不可能形成lockup;
-
其次內核代碼必須處於禁止內核搶占的狀態(preemption disabled),因為Linux是可搶占式的內核,只在某些特定的代碼區才禁止搶占,在這些代碼區才有可能形成lockup。
Lockup分為兩種:soft lockup 和 hard lockup,它們的區別是 hard lockup 發生在CPU屏蔽中斷的情況下。
-
Soft lockup是指CPU被內核代碼占據,以至於無法執行其它進程。檢測soft lockup的原理是給每個CPU分配一個定時執行的內核線程[watchdog/x],如果該線程在設定的期限內沒有得到執行的話就意味着發生了soft lockup。
-
Hard lockup比soft lockup更加嚴重,CPU不僅無法執行其它進程,而且不再響應中斷。檢測hard lockup的原理利用了PMU的NMI perf event,因為NMI中斷是不可屏蔽的,在CPU不再響應中斷的情況下仍然可以得到執行,它再去檢查時鍾中斷的計數器hrtimer_interrupts是否在保持遞增,如果停滯就意味着時鍾中斷未得到響應,也就是發生了hard lockup。
Linux kernel設計了一個檢測lockup的機制,稱為NMI Watchdog,是利用NMI中斷實現的,用NMI是因為lockup有可能發生在中斷被屏蔽的狀態下,這時唯一能把CPU搶下來的方法就是通過NMI,因為NMI中斷是不可屏蔽的。NMI Watchdog 中包含 soft lockup detector 和 hard lockup detector,2.6之后的內核的實現方法如下。
NMI Watchdog 的觸發機制包括兩部分:
一個高精度計時器(hrtimer),對應的中斷處理例程是kernel/watchdog.c
: watchdog_timer_fn()
,在該例程中:
要遞增計數器hrtimer_interrupts
,這個計數器供hard lockup detector用於判斷CPU是否響應中斷;
還要喚醒[watchdog/x]內核線程,該線程的任務是更新一個時間戳;
soft lock detector檢查時間戳,如果超過soft lockup threshold一直未更新,說明[watchdog/x]未得到運行機會,意味着
CPU被霸占,也就是發生了soft lockup。
基於PMU的NMI perf event,當PMU的計數器溢出時會觸發NMI中斷,對應的中斷處理例程是 kernel/watchdog.c
: watchdog_overflow_callback()
,hard lockup detector就在其中,它會檢查上述hrtimer的中斷次數(hrtimer_interrupts)是否在保持遞增,如果停滯則表明hrtimer中斷未得到響應,也就是發生了hard lockup。
hrtimer的周期是:softlockup_thresh/5
。
注:
在2.6內核中:
softlockup_thresh
的值等於內核參數kernel.watchdog_thresh
,默認60秒;
而到3.10內核中:
內核參數kernel.watchdog_thresh
名稱未變,但含義變成了hard lockup threshold,默認10秒;
soft lockup threshold則等於(2*kernel.watchdog_thresh)
,即默認20秒。
NMI perf event是基於PMU的,觸發周期(hard lockup threshold)在2.6內核里是固定的60秒,不可手工調整;在3.10內核里可以手工調整,因為直接對應着內核參數kernel.watchdog_thresh
,默認值10秒。
檢測到 lockup 之后怎么辦?可以自動panic,也可輸出條信息就算完了,這是可以通過內核參數來定義的:
-
kernel.softlockup_panic
: 決定了檢測到soft lockup時是否自動panic,缺省值是0; -
kernel.nmi_watchdog
: 定義是否開啟nmi watchdog、以及hard lockup是否導致panic,該內核參數的格式是”=[panic,][nopanic,][num]”.
(注:最新的kernel引入了新的內核參數kernel.hardlockup_panic
,可以通過檢查是否存在 /proc/sys/kernel/hardlockup_panic
來判斷你的內核是否支持。)
參考資料:
Softlockup detector and hardlockup detector (aka nmi_watchdog)