gcc中的线程安全原子操作

nafvub8i  于 2023-10-19  发布在  其他
关注(0)|答案(5)|浏览(100)

在我工作的一个程序中,我有很多代码如下:

pthread_mutex_lock( &frame->mutex );
frame->variable = variable;
pthread_mutex_unlock( &frame->mutex );

如果中间指令可以用原子存储替换,这显然是对CPU周期的浪费。我知道gcc在这方面很有能力,但是我还没有找到太多关于这种简单的线程安全原子操作的文档。如何用原子操作替换这组代码?
(我知道简单的存储在理论上应该是原子的,但我不希望优化器在过程中的某个时候没有破坏它们的原子性。
说明:我不需要它们是严格的原子;这些变量仅用于线程同步。也就是说,线程B读取该值,检查其是否正确,如果不正确,则休眠。因此,即使线程A更新了值,而线程B没有意识到它被更新了,这也不是问题,因为这只是意味着线程B在不需要的时候休眠了,当它醒来时,值将是正确的。

xhv8bpkk

xhv8bpkk1#

你可以查看gcc文档。对于当前的gcc版本(4.3.2),它将是第5.47章Built-in functions for atomic memory access-对于其他gcc版本,请检查您的文档。它应该在第5章-C语言家族的扩展。
顺便说一下,C编译器绝对不能保证简单的存储操作是原子的。你不能依赖这个假设。为了使机器操作码能够原子地执行,它需要前缀"“。

taor4pac

taor4pac2#

在某种程度上,C中的原子操作是通过atomic. h头文件直接从内核源代码提供的。
但是,在用户空间代码中直接使用内核头文件是一种非常糟糕的做法,因此atomic. h头文件在一段时间前就被删除了。相反,我们现在可以使用“GCC Atomic Builtins”,这是一种更好、更可靠的方法。
very good explanation provided by Tudor Golubenco on his blog。他甚至为初始atomic. h文件提供了一个临时替代品,以防您有一些代码需要它。
不幸的是,我是stackoverflow的新手,所以我只能在我的评论中使用一个链接,所以检查Tudor的帖子并获得启发。

px9o7tmv

px9o7tmv3#

在x86和大多数其他架构上,对齐的4字节读写始终是原子的。但是,优化器可以跳过/重新排序单个线程内的读取和写入。
你要做的是通知编译器其他线程可能已经触及了这个内存位置。(pthread_mutex_lock的一个副作用是告诉编译器其他线程可能已经触及了内存的任何部分。)您可能会看到推荐使用volatile,但这不在C规范中,GCC也不会以这种方式解释volatile

asm("" : "=m" (variable));
frame->variable = variable;

是GCC特有的机制,表示“variable已被写入,请重新加载它”。

9jyewag0

9jyewag04#

AFAIK,你不能在MOV指令前加上前缀“”;这仅允许用于RMW操作。但是如果他 * 确实 * 使用了一个简单的存储,他可能还需要一个内存屏障,这在互斥体和允许重复的指令中是隐式的。

w7t8yxp5

w7t8yxp55#

正如我所看到的,您正在使用gnu平台进行开发,因此可以肯定地说,glic提供了一个具有原子能力的数据类型int,'sig_atomic_t'。因此,这种方法可以确保在内核级别进行原子操作。而不是GCC水平。

相关问题