原子集的内置 GCC 是啥?

Posted

技术标签:

【中文标题】原子集的内置 GCC 是啥?【英文标题】:What is the GCC builtin for an atomic set?原子集的内置 GCC 是什么? 【发布时间】:2018-04-20 01:56:24 【问题描述】:

我在https://gcc.gnu.org/onlinedocs/gcc-4.1.0/gcc/Atomic-Builtins.html 看到了内置列表。但是对于原子集,您是否需要使用 __sync_lock_test_and_set 和 __sync_lock_release 对?

我在https://attractivechaos.wordpress.com/2011/10/06/multi-threaded-programming-efficiency-of-locking/ 上看到过这个例子。

volatile int lock = 0;
void *worker(void*)

    while (__sync_lock_test_and_set(&lock, 1));
    // critical section
    __sync_lock_release(&lock);

但是如果我使用这个例子,并且在临界区中做我的原子集,那么不同变量的原子集将被不必要地序列化。

感谢任何关于如何在我有多个原子变量的情况下进行原子集的输入。

【问题讨论】:

你真的必须使用那些遗留的内置函数吗? gcc.gnu.org/onlinedocs/gcc-7.3.0/gcc/… 建议在新代码中避免使用它们。 好主意。我在“c 中的原子操作”中找到的大多数链接都是关于这些遗留内置函数的。 __atomic_store 内置函数可以实现我的 atomic64_set 函数。 【参考方案1】:

根据定义需要同时使用两者

__sync_synchronize (...)

这个内置函数发出一个完整的内存屏障。输入

__sync_lock_test_and_set (type *ptr, type value, ...)

正如英特尔所描述的,这个内置不是传统的测试和设置 操作,而是原子交换操作。它写入值 进入 *ptr,并返回 *ptr 之前的内容。许多目标 对这种锁只有最低限度的支持,不支持完整的 交换操作。在这种情况下,目标可能支持减少 此处唯一要存储的有效值是 立即常数 1. 实际存储在 *ptr 中的确切值是 实现定义。

这个内置不是一个完整的屏障,而是一个获取屏障。 这意味着内置函数之后的引用不能移动到(或 推测)在内置之前,但以前的内存存储可能不会 仍然是全局可见的,并且以前的内存负载可能还不是 使满意。

void __sync_lock_release (type *ptr, ...)

这个内置释放 由 __sync_lock_test_and_set 获取的锁。通常这意味着写 常数 0 到 *ptr。这个内置不是一个完整的障碍,而是 释放屏障。这意味着所有以前的内存存储都是 全局可见,并且所有先前的内存负载都已得到满足, 但不会阻止以下内存读取被推测为 在障碍之前。

【讨论】:

你知道是否有一个单独的调用来设置一个值吗?由于 GCC 提供了 __sync_fetch_and_or() 之类的操作,因此似乎应该有一个 __sync_set 操作。如果没有,你能否提供一个如何做的例子。使用 __sync_synchronize()。它有相应的发布调用吗?在我能找到的几个例子中没有看到一个。谢谢!【参考方案2】:

我想出了这个解决方案。如果您知道更好的请回复:

typedef struct 
    volatile int lock;  // must be initialized to 0 before 1st call to atomic64_set
    volatile long long counter;
 atomic64_t;

static inline void atomic64_set(atomic64_t *v, long long i)

    // see https://attractivechaos.wordpress.com/2011/10/06/multi-threaded-programming-efficiency-of-locking/
    // for an explanation of __sync_lock_test_and_set
    while (__sync_lock_test_and_set(&v->lock, 1))  // we don't have the lock, so busy wait until
        while (v->lock);                            // it is released (i.e. lock is set to 0)
                                                   // by the holder via __sync_lock_release()
    // critical section
    v->counter = i;
    __sync_lock_release(&v->lock);

【讨论】:

以上是关于原子集的内置 GCC 是啥?的主要内容,如果未能解决你的问题,请参考以下文章

gcc __sync 内置函数和 x86

内置数组大小的类型是啥?

获取 pytorch 数据集的子集

“子集”和“$ 运算符对原子向量无效”

核心数据 - 如何跟踪实体集的子集

从另一个获取 NSDictionary 的 NSArray,其中包含原始键集的子集