[英]xv6: reading ticks directly without taking the ticks lock?
我正在從事Xv6操作系統課程的作業。 我需要為進程的創建時間、終止時間、睡眠時間等實現數據狀態結構......
到目前為止,我決定直接使用ticks
變量而不使用tickslock
因為使用鎖並減慢系統速度來實現如此低優先級的目標似乎不是一個好主意。
由於 ticks 變量僅像這樣使用: ticks++
,有沒有辦法嘗試檢索當前的刻度數並得到錯誤的數字?
我不介意在 +-10 滴答時得到錯誤的數字,但有沒有辦法讓它真正關閉。 就像當數字 01111111111111111 遞增時,它需要改變 2 個字節。 所以我的問題是,在存儲操作開始和完成之間,CPU 是否有可能分階段存儲數據,而另一個 CPU 將能夠獲取該內存位置中的數據?
所以在我看來,如果編譯器將創建一條mov
指令或一條inc
指令,我想知道的是,是否可以在它的開始和結束之間看到存儲操作。
asm 沒有問題:在 x86 上使用單個指令完成的對齊加載/存儲在 qword(8 字節)寬度內是原子的。 為什么在 x86 上自然對齊的變量原子上的整數賦值是原子的?
(在 486 上,保證僅適用於 4 字節對齊的值,甚至可能不適用於 386,所以這可能就是 Xv6 使用鎖定的原因?我不確定它是否應該在 386 上是多核安全的;我的理解是罕見的 386 SMP 機器並沒有完全實現現代 x86 內存模型(內存排序等)。)
但 C 不是 asm。 一次使用來自多個“線程”的普通非atomic
變量是未定義的行為,除非所有線程都只是在讀取。 這意味着編譯器可以假設其他線程不會異步更改普通 C 變量。
在 C 中的循環中使用ticks
將使編譯器讀取一次並重復使用相同的值。 您需要像 Linux 內核使用的READ_ONCE
宏,例如*(volatile int*)&ticks
。 或者簡單地將其聲明為volatile unsigned ticks;
對於一個足夠窄以適合一個整數寄存器的變量,假設一個健全的編譯器將使用單個 dword 存儲來編寫它可能是安全的,無論是mov
還是 memory-destination inc
或add dword [mem], 1
。 (不過,您不能假設編譯器將使用內存目標 inc/add,因此您不能依賴於中斷方面的單核原子增量。)
對於一個作者和多個讀者,是的,讀者可以簡單地閱讀它,而無需任何類型的鎖定,只要他們使用volatile
。
即使在可移植的ISO C 中,當由信號處理程序寫入並由運行信號處理程序的線程讀取時, volatile sig_atomic_t
對安全工作的保證也非常有限。 (雖然不一定由其他線程執行:在 ISO C volatile
並不能避免數據競爭 UB。但實際上在 x86 上使用非敵對編譯器很好。)
(POSIX 信號是用戶空間的中斷等價物。)
對於一個線程以兩半發布更寬的計數器,您通常會使用 SeqLock。 使用 1 個寫入器和多個讀取器時,沒有實際鎖定,如果寫入與讀取重疊,則由讀取器重試。 請參閱使用 32 位原子實現 64 位原子計數器
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.