繁体   English   中英

我可以使用cmpxchg16b以原子方式将指针复制到指针和int,同时增加int(原子引用计数)吗?

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM