2014-03-31 46 views
7

Linux的ACCESS_ONCE宏定義如下:爲什麼ACCESS_ONCE如此複雜?

#define ACCESS_ONCE(x) (*(volatile typeof(x) *)&(x)) 

我明白這是什麼做的,但不知道爲什麼它是如此複雜?我的理解是它具有下列功能:

  1. 取地址(創建一個臨時指針)關注的是指針
  2. 變量
  3. 演員這一相同類型的揮發性指針
  4. 去參考

這是爲什麼不以更簡單的方式實現任何想法,說:

#define ACCESS_ONCE(x) ((volatile typeof(x))(x)) 

回答

8

ACCESS_ONCE宏用於從已知(或懷疑)易失性存儲位置檢索值但未按類型輸入的情況。其目的是以這種方式檢索存儲位置的當前值,以便擊敗優化編譯器,否則該編譯器可能會將值緩存在寄存器中,甚至根本不提供存儲位置。

寫入的結構通過聲明適當類型的指針來間接地將「volatile」應用於存儲位置。根據C標準,這要求object be evaluated strictly according to the rules of the abstract machine

您提出的修改不會將volatile應用到存儲位置,因此它不會達到此目的。值檢索可以進行優化。

順便說一下,我認爲這是爲了達到上述目的的簡潔模型。我保留complex比這更糟糕的事情。

+0

謝謝大衛,您的清晰準確的解釋。 – user3480510

+0

更多的上下文:C標準允許將'volatile'限定符分配給* data *,而不是*訪問*數據。有很多人認爲這很愚蠢,其中,萊納斯。此外,'volatile'還有一些問題,在Linux內核,多線程等方面它有點被認爲是有害的。因此,ACCESS_ONCE宏(&friends)中的技術是一種強制使用C只有在需要時纔會產生不穩定的語義,避免了缺點。請注意,這足以引起GCC迴歸! – hmijail

0

強制轉換爲卷atile對「簡單」變量基本沒用 - 它不會改變底層的訪問語義,所以這不是你想要的。

+0

你怎麼知道他/她想要什麼? – jag

+1

如果你把任何東西都轉換爲volatile,你可能會期望把這個東西的存儲類改爲volatile。 但是,它不這樣工作。 想像一個強制轉換創建該想要的類型的臨時對象(如果要將整數轉換爲double,那麼您不希望該基礎變量變爲double)? – mfro

-1

This link解釋了爲什麼強制轉換爲volatile的深層原因沒有影響。

將值轉換爲限定類型不起作用;資格 (易失性,比如說)可能對訪問沒有影響,因爲它在事件發生前已經發生了 。如果需要使用易失性語義訪問非易失性對象 ,則該技術將將 對象的地址轉換爲適當的指針限定類型,然後將該指針取消引用 。

相關問題