使用OpenMP实现无锁堆栈:比较和交换

时间:2016-10-08 22:45:52

标签: openmp atomic c11 compare-and-swap

我正在编写一个C库,我想通过使用OpenMP来选择性地支持并发(如果编译器不支持OpenMP,可以串行编译它)。我想使用无锁堆栈实现。

我考虑过使用C的stdatomic.h作为堆栈,但似乎是until a few weeks ago, GCC couldn't use _Atomic with OpenMP,所以这会使可移植性变得复杂。 Clang 3.8似乎正确地使用OpenMP处理原子,但是这仍然不是最好的选择,因为在没有OpenMP(因此是连续的)编译时没有必要保持原子性。

我似乎需要在从堆栈弹出时使用比较和交换操作,而我在OpenMP上找不到任何有关比较和交换的信息。有没有办法只使用OpenMP实现无锁堆栈?

到目前为止我的代码(与clang合作):

struct lfstack_node {
  void *value;
  struct lfstack_node *next;
};

typedef struct lfstack {
  _Atomic(size_t) size;
  _Atomic(struct lfstack_node *) head;
  _Atomic int aba;
} *lfstack_t;

// ...

void *lfstack_pop(lfstack_t stack) {
  if(stack) {
    atomic_fetch_add(&stack->aba, 1);
    struct lfstack_node *node, *next;
    do {
      node = atomic_load(&stack->head);
      if(!node) {
        break;
      }
      // ABA problem here if not handled correctly
      next = node->next;
    } while(!atomic_compare_exchange_weak(&stack->head, &node, next));

    atomic_fetch_sub(&stack->aba, 1);
    if(node) {
      int zero = 0;
      while(!atomic_compare_exchange_weak(&stack->aba, &zero, zero)) {
        continue;
      }
      void *value = node->value;
      free(node);
      return value;
    }
  }
  return NULL;
}

0 个答案:

没有答案