我在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);
}
但是如果我使用这个例子,并在临界区内进行原子设置,那么不必要地对不同变量的原子集进行序列化。
感谢关于如何进行原子集的任何输入,其中我有多个原子变量。
答案 0 :(得分:0)
根据定义,需要同时使用
__ sync_synchronize(...)
这种内置会发出完整的内存障碍。输入
__ sync_lock_test_and_set(输入* ptr,类型值,...)
英特尔所描述的这种内置设备并不是传统的测试套装 操作,而是原子交换操作。它写出了价值 进入* ptr,并返回* ptr的先前内容。很多目标 对这种锁只有最小的支持,并且不支持完整 交换操作。在这种情况下,目标可以支持减少 这里存储的唯一有效值的功能是 立即常数1.实际存储在* ptr中的确切值是 实施定义。
这种内置不是一个完整的障碍,而是一个获取障碍。 这意味着内置后的引用不能移动到(或者是 推测到内置之前,但以前的内存存储可能不会 是全局可见的,以前的内存负载可能还没有 满意。
void __sync_lock_release(type * ptr,...)
这个内置发布了 由__sync_lock_test_and_set获取的锁。通常这意味着写作 常数0到* ptr。这种内置不是一个完整的障碍,而是 释放障碍。这意味着以前的所有内存都是 全局可见,并且所有以前的内存负载都已满足, 但不会阻止推测以下内存读取 在障碍之前。
答案 1 :(得分:0)
我提出了这个解决方案。如果你认识一个更好的,请回复:
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);
}