[英]Can I use cmpxchg16b to atomically copy a pointer to a pointer and an int, while simultaneously incrementing the int (atomic reference counting)?
我的目標是復制一個指針並原子地增加一個引用計數器, 而不是鎖定 。 我可以使用cmpxchg16b,或者可能有更簡單的方法嗎? 我對匯編程序很無能為力,所以請原諒任何明顯的錯誤。
編輯 :一些類似這樣 ,但對於這個英特爾架構。 (我仍然試圖看看我是否可以調整dr.dobbs文章中的內容到我的平台。原子操作似乎有點不同)
示例內存
struct MyThing {
void * pSomeObj;
uint64_t counter;
__attribute__((aligned(16)));
};
我想做的是這樣的事情。
MyThing* globalSource = ...;
...
MyThing* dest;
//copy the pointer while incrementing counter all in one shot. (to prevent data race where a copy is done and some other thread deletes the pointer before the the counter gets a chance to be updated)
AtomicCopyAndIncrement(dest, globalSource);
從邏輯上講,這就是我想要實現的目標:
bool AtomicCopyAndIncrement(MyThing *dest, MyThing *src) {
//begin atomic
dest = src;
dest->counter++;
//end atomic
return true;
}
此功能只是按原樣交換所有內容。 我認為這是對的。
bool AtomicSwap(MyThing *dest, MyThing *src)
{
bool swap_result;
__asm__ __volatile__
(
"lock cmpxchg16b %0;"
"setz %3;"
: "+m" (*dest), "+a" (dest->pSomeObj), "+d" (dest->counter), "=q" (swap_result)
: "b" (src->pSomeObj), "c" (src->counter)
: "cc", "memory"
);
return swap_result;
}
此函數應該使用src並將其設置為dest,同時遞增在dest中分配的計數器。
bool AtomicCopyAndIncrement(MyThing *dest, MyThing *src)
{
bool swap_result;
__asm__ __volatile__
(
"lock cmpxchg16b %0;"
"setz %3;"
//all wrong
: "+m" (*dest), "+a" (dest->pSomeObj), "+d" (dest->counter), "=q" (swap_result)
: "b" (src->pSomeObj), "c" (src->counter +1)
: "cc", "memory"
);
return swap_result;
}
這會減少計數器,但會將點復制回自身。 我不知道這是否必要,
但我認為這是對的。
編輯我很確定這是錯的。
bool AtomicDecrement(MyThing *dest)
{
bool swap_result;
__asm__ __volatile__
(
"lock cmpxchg16b %0;"
"setz %3;"
: "+m" (*dest), "+a" (dest->pSomeObj), "+d" (dest->counter), "=q" (swap_result)
: "b" (dest->pSomeObj), "c" (dest->counter -1)
: "cc", "memory"
);
return swap_result;
}
使用場景如下:
線程0:
MyThing* newThing;
do {
if (newThing) delete newThing;
newThing = new MyThing;
newThing->pSomeObj->SomeUpdate();
}
while (AtomicSwap(newThing, globalThing));
//then deal with the memory in newThing
線程1-N:
MyThing *currentThing = new MyThing;
//make currentThing->pSomeObj the same as globalThing->pSomeObj, and increment the counter
AtomicCopyAndIncrement(currentThing, globalThing);
考慮使用std::atomic
。 如果目標體系結構提供它,它將編譯為128位CAS,並且比內聯匯編程序更清晰,更易於使用,並且更加獨立於平台。
下面是一個示例,您可以使用它來更新指針並以原子方式遞增計數器:
std::atomic<MyThing>* target = ...;
MyThing oldValue = target->load();
MyThing newValue { newPointer, 0 };
do{
newValue.counter = oldValue.counter+1;
while(target->compare_exchange_strong(oldValue,newValue))
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.