[英]Partial reordering of C++11 atomics on Aarch64
我在查看gcc的rmw原子的編譯器輸出時 ,發現有些奇怪的東西-在Aarch64上,諸如fetch_add之類的rmw操作可以通過輕松的加載進行部分重新排序。
在Aarch64上,可能會為value.fetch_add(1, seq_cst)
生成以下代碼
.L1:
ldaxr x1, [x0]
add x1, x1, 1
stlxr w2, x1, [x0]
cbnz L1
但是,有可能對ldaxr之前發生的裝入和存儲進行重新排序,使其超出stlxr之后發生的裝入和存儲/存儲(請參見此處 )。 GCC不會添加圍欄來防止這種情況-以下是一小段代碼演示了這一點:
void partial_reorder(std::atomic<uint64_t> loader, std::atomic<uint64_t> adder) {
loader.load(std::memory_order_relaxed); // can be reordered past the ldaxr
adder.fetch_add(1, std::memory_order_seq_cst);
loader.load(std::memory_order_relaxed); // can be reordered past the stlxr
}
發電
partial_reorder(std::atomic<int>, std::atomic<int>):
ldr w2, [x0] @ reordered down
.L2:
ldaxr w2, [x1]
add w2, w2, 1
stlxr w3, w2, [x1]
cbnz w3, .L2
ldr w0, [x0] @ reordered up
ret
實際上,可以通過RMW操作對負載進行部分重新排序-它們出現在中間。
那么,有什么大不了的? 我在問什么
原子操作本身是可以整除的,這似乎很奇怪。 我無法在標准中找到任何阻止這種情況的方法,但是我曾經相信,有一系列規則暗示着操作是不可分割的。
似乎這不符合獲取順序。 如果我在此操作之后直接執行加載,則可能會在fetch_add和后續操作之間看到存儲加載或存儲-存儲重新排序,這意味着稍后的內存訪問在獲取操作之后至少部分重新排序。 同樣,我在標准中找不到任何明確表明不允許和獲取的內容,即負載排序,但是我的理解是獲取操作適用於整個操作,而不僅僅是部分操作。 類似的情況也適用於通過ldaxr重新排序某些東西的版本。
這可能是在進一步擴展排序定義,但似乎無法將seq_cst操作前后的兩個操作重新排序。 如果邊界操作各自重新排序到操作的中間,然后彼此越過,則可能會發生這種情況。
我在這里沒有發現任何問題。 第二個示例與第一個示例幾乎相同,只是在其中預先添加了一個負載並附加了一個負載。 因此,它完全遵循您在C代碼中編寫的內容。 我在這里看不到任何重新排序。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.