[英]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.