![](/img/trans.png)
[英]Can rcu_assign_pointer() be used between rcu_read_lock() and rcu_read_unlock()?
[英]rcu_read_lock and x86-64 memory ordering
在可搶占式SMP內核上, rcu_read_lock
編譯以下內容:
current->rcu_read_lock_nesting++;
barrier();
barrier
是一個編譯器指令,可編譯為空。
因此,根據英特爾的X86-64內存訂購白皮書:
可能會將舊商店的貨物重新排序到其他位置
為什么實施實際上可以?
請考慮以下情況:
rcu_read_lock();
read_non_atomic_stuff();
rcu_read_unlock();
是什么阻止read_non_atomic_stuff
從“ rcu_read_lock
”向前“泄漏”,導致它與在另一個線程中運行的回收代碼同時運行?
對於其他CPU上的觀察者,沒有什么可以阻止這一點。 沒錯, ++
商店部分的StoreLoad重新排序可以使它在某些加載后在全局可見。
因此,我們可以得出結論,只有當前在此內核上運行的代碼才會觀察到current->rcu_read_lock_nesting
,或者通過在此處調度而遠程觸發了該內核上的內存屏障,或者使用了一種專用機制來使所有內核在該內核中執行屏障。處理器間中斷(IPI)的處理程序。 例如,類似於membarrier()
用戶空間系統調用。
如果此核心開始運行另一個任務,則可以確保該任務按程序順序查看此任務的操作。 (因為它在同一個內核上,並且一個內核總是按順序查看其自身的操作。)而且,上下文切換可能涉及完整的內存屏障,因此可以在不破壞單線程邏輯的情況下在另一個內核上恢復任務。 (這可以使任何內核在此任務/線程不在任何地方運行時安全地查看rcu_read_lock_nesting
。)
請注意,內核在您的計算機的每個內核上啟動一個RCU任務 ; 例如, ps
輸出在我的4c8t四核上顯示[rcuc/0]
, [rcuc/1]
,..., [rcu/7]
。 大概它們是該設計的重要組成部分,它使讀者可以毫無障礙地等待。
我還沒有研究RCU的全部細節,但是https://www.kernel.org/doc/Documentation/RCU/whatisRCU.txt中的“玩具”示例之一是實現了synchronize_rcu()
“經典RCU” for_each_possible_cpu(cpu) run_on(cpu);
,以使回收器在可能已執行RCU操作的每個內核(即每個內核)上執行。 完成此操作后,我們知道在切換過程中某個地方一定已經發生了內存不足的情況。
因此,是的,RCU並沒有遵循經典的方法,在這種方法中,您需要一個完整的內存屏障(包括StoreLoad)來使核心等待直到第一個存儲區可見之后才能進行任何讀取。 RCU避免了讀取路徑中完整內存屏障的開銷。 除了避免爭用外,這是它的主要吸引力之一。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.