[英]Is calling spin_lock_irqsave, instead of local_irq_disable followed by spin_lock, the same for a per-prorcessor struct?
考慮以下 kernel 代碼
local_irq_disable();
__update_rq_clock(rq);
spin_lock(&rq->lock);
rq
是指向每個處理器struct
的指針(即;不受 SMP 並發的影響)。 由於在調用local_irq_disable
后rq
將永遠不會在另一個地方被訪問(因為rq
僅由單個處理器使用並且禁用本地中斷意味着該 CPU 上不會運行任何中斷處理程序),那么在前面的函數之間嵌入__update_rq_clock
的意義何在? 換句話說,鑒於rq
在__update_rq_clock
內的兩種情況下都是安全的,無論是否被鎖定,它與以下內容有何不同?
spin_lock_irqsave(&rq->lock, flags);
__update_rq_clock(rq);
首先也是最重要的:您展示的兩個示例具有不同的語義: local_irq_disable
不保存舊的 state 的 IRQ。 換句話說,當相應的local_irq_enable
function被調用時,它將強制重新啟用IRQ(無論它們是否已經被禁用)。 另一方面, spin_lock_irqsave
確實保存了舊的 IRQ state,因此以后可以通過spin_unlock_irqrestore
恢復它。 出於這個原因,您展示的兩段代碼非常不同,比較它們沒有多大意義。
現在,進入真正的問題:
由於在調用
local_irq_disable
后rq
將永遠不會在另一個地方被訪問(因為rq
僅由單個處理器使用,並且禁用本地中斷意味着不會在該 CPU 上運行中斷處理程序)
這並非總是如此。 沒有“魔法屏障”可以阻止 CPU 訪問另一個 CPU 的每個 CPU 數據。 這仍然是可能的,在這種情況下,必須通過適當的鎖定機構格外小心。
雖然 per-CPU 變量通常旨在為單個 CPU 提供對 object 的快速訪問,因此可以具有不需要鎖定的優勢,但沒有什么比約定可以阻止處理器挖掘其他處理器的 per-CPU數據(報價)。
運行隊列就是一個很好的例子:由於調度程序經常需要將任務從一個運行隊列遷移到另一個運行隊列,它肯定需要在某個時候同時訪問兩個運行隊列。 事實上,這可能是struct rq
有一個.lock
字段的原因之一。
事實上,在最近的 kernel 代碼中,在不持有rq->lock
的情況下進行 rq 時鍾更新似乎被認為是一個錯誤,正如您可以從update_rq_clock()
中的lockdep 斷言中看到的那樣:
void update_rq_clock(struct rq *rq)
{
s64 delta;
lockdep_assert_held(&rq->lock);
// ...
感覺您在第一個代碼片段中顯示的語句應該重新排序以先鎖定然后更新,但是代碼很舊(v2.6.25),並且對__update_rq_clock()
的調用似乎是在獲取之前故意進行的鎖。 很難說為什么,但也許舊的運行隊列語義不需要鎖定來更新.lock
/ .prev_clock_raw
,因此鎖定是在之后完成的,只是為了最小化臨界區的大小。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.