2014-01-22 55 views
0

我正在使用一個64位x86系統,限制爲最多8字節的比較和交換操作。由於指針是8字節,我需要一個計數器來避免ABA問題,是否可以修改指針的高16位,這些指針不用於存儲計數器?只有8字節CAS鎖定? C++

pointer_as_dec = reinterpret_cast<uintptr_t>(&node); // Node address 
pointer_as_dec+(1LLU<<48); // Initialize the counter in one of the upper bits 

是否可以使用__sync_bool_compare_and_swap函數存儲修改的指針地址?

回答

2

好了,這是不保證按照你真的允許用指針轉換成int做的是將它轉換回不變的指針任何標準,唯一的工作。但實際上,它可以在任何x86_64平臺以及其他幾乎任何其他平臺上運行。顯然你並不期待特定於gcc的x86_64專用代碼是可移植的。所以,這裏沒有問題。

此外,uintptr_t不是用於gcc原子功能的supported types--但它完全兼容unsigned long long int,它是。 (如果你擔心這一點,你可以隨時添加第二個演員...)所以,這裏也沒有問題。

同時,__sync_bool_compare_and_swap不關心你是走私在uintptr_t指針;就它而言,它只是一個無符號的64位整數。所以,這裏沒有問題。

你真的能肯定的是,前16位總是空的?在x86_64 linux中,它們是爲了您的普通用戶內存。他們可能不是指向核心內存或者內存映射的硬件,他們可能無法在其他x86_64系統,但如果沒有,他們會全1代替。正如布倫丹指出的那樣,這可以保證在沒有128位CAS的x86_64硬件上運行任何東西。*因此,如果您需要將這些內存或端口指向這些系統,只需使用15位而不是16位。假設你指向的是64位對齊的對象,那麼你在指針的另一端也有6個空閒位,你可以使用它來替代/另外使用)。問題也在這裏。


*除了在高度萬一AMD或英特爾或其他人決定改變虛擬地址的大小,也決定要帶走128位CAS ...

+0

感謝您的答覆,這是有益的。由於_sync_bool_cas需要一個指向內存位置的第一個參數,我怎麼會通過(寧uint64_t中我已經投之後)的指針uintptr_t的變量本身存儲在uintptr_t的數量,而不是? – user3217789

+0

@ user3217789:你不能使用被改寫的行動僞裝指針在'uintptr_t'爲*指針*,你只能把它作爲一個_value_。無論你有哪些結構引用了一些需要CAS'd的對象,你都會存儲指針_there_,而不是實際的指針。然後你通過使用結構中的地址來CAS他們。而且你必須去掉這些部分才能去掉它們。 – abarnert

+0

@ user3217789:想一想,在指針本身上有一個計數器會有什麼好處呢? CAS的全部重點是驗證自上次檢查以來指向的64位內存沒有改變。沒有人關心你是否有一個指向64位內存的新指針,就是那裏。請記住,您首先需要CAS的全部原因是其他對象將具有指向同一地址的其他對象。 – abarnert