我正在尝试验证我是否可以在gcc编译器中使用“__atomic_exchange_n”(版本4.3.2),如果它支持原子,我找不到任何地方,如果它不能使用“__sync_lock_test_and_set” ?
我在哪里可以看到我的编译器是否支持这个函数,或者它们在gcc中引入的位置?谢谢!
伪码:
#if defined HAVE_GCC_SYNC_BUILTINS
#define AtomicExchange(vP, v) (void)__sync_lock_test_and_set(vP, v)
#elif defined HAVE_GCC_ATOMIC_BUILTINS
#define AtomicExchange(vP, v) (void)__atomic_exchange_n(vP,v, o)
#endif
修改
我有gcc 4.3.2,我无法更新它。 (平台限制) 有没有办法实现64位变量的原子存储?
我尝试使用“__sync_lock_test_and_set(vP,v)”,如上所述,对于int,short和char,它可以工作,但对于int64(long long),我可以执行商店,因为它给出了“未定义的引用”到__sync_lock_test_and_set_8“。 “_8”是8字节(64位)。
我能做些什么来实现64位原子商店吗? 谢谢
答案 0 :(得分:3)
原子操作CAS(或比较和交换)和LL/SC(或加载链接/存储条件)有两种基本方法。它们的低级差异使得它们无法直接暴露给用户空间。旧式__sync内置程序基于采用CAS方法的Intel Itanium架构;毫无疑问,它不是LL / SC风格架构原子的非常好的匹配。实际结果是不同的C方法(如果必须使用同步内置函数)在不同的体系结构上工作得最好;新型原子内置函数倾向于在所有体系结构上产生更好的代码,基于并且更多地接触不同类型的体系结构。
GCC 4.3.2仅支持旧式__sync_内置插件。替换__atomic_exchange_n()
操作有两种常规方法:
static inline TYPE atomic_exchange(TYPE *const ptr, const TYPE newval)
{
TYPE oldval;
do {
oldval = *ptr;
} while (!__sync_bool_compare_and_swap(ptr, oldval, newval));
return oldval;
}
static inline TYPE atomic_exchange(TYPE *const ptr, const TYPE newval)
{
TYPE oldval, tmpval;
oldval = *ptr;
do {
tmpval = oldval;
oldval = __sync_val_compare_and_swap(ptr, tmpval, newval);
} while (oldval != tmpval);
return oldval;
}
如果newval
为零或全部,我们也可以使用
static inline TYPE atomic_clear(TYPE *const ptr)
{
return __sync_fetch_and_and(ptr, (TYPE)0);
}
static inline TYPE atomic_setall(TYPE *const ptr)
{
return __sync_fetch_and_or(ptr, ~(TYPE)0);
}
如果只有少数处理器/缓存架构目标,您可以始终编写一个有效的内联汇编函数,假设硬件实际上支持64位原子操作。如果您可以编译一个简单的新式原子交换函数,那么这将非常简单,比如说
TYPE atomic_exchange_prototype(TYPE *const ptr, const TYPE newval)
{
return __atomic_exchange_n(ptr, newval, __ATOMIC_SEQ_CST);
}
对于每个目标体系结构到汇编代码(例如,使用-O2 -S
gcc标志,以及特定于体系结构的选项;或-O2 --static -c
如果使用GCC提供的函数,在这种情况下{{1} }可以提供反汇编)。在某些情况下,体系结构手册实际上描述了如何最好地构建原子操作。
如果硬件架构不支持64位原子操作(尽管如果32位架构根本不支持64位原子操作,即使通过仿真也会有点惊讶),可能仍有解决方法。例如,使用生成计数器。 (基本上,两个或多个原子递增(小)计数器字段用于确定数据何时有效。确切的实现取决于需求,特别是在(从哪个上下文)数据被修改时。)
答案 1 :(得分:1)
您可以谷歌获取GCC 4.3.2规范
https://gcc.gnu.org/onlinedocs/gcc-4.3.2/gcc/Atomic-Builtins.html
我认为你可以使用
type __sync_val_compare_and_swap (type *ptr, type oldval type newval, ...)
这些内置函数执行原子比较和交换。也就是说,如果 * ptr的当前值是oldval,然后将newval写入* ptr。
如果比较成功并且newval,则“bool”版本返回true 写的。 “val”版本在返回之前返回* ptr的内容 操作
type __sync_lock_test_and_set (type *ptr, type value, ...)
英特尔所描述的这种内置设备并不是传统的测试套装 操作,而是原子交换操作。它 将值写入* ptr,并返回* ptr。
的先前内容许多目标对此类锁只有最小的支持,并且不支持完整的交换操作。在这种情况下,目标可能会支持 这里减少了存储唯一有效值的功能 立即数1.实际存储在* ptr中的确切值是 实施定义。
这种内置不是一个完整的障碍,而是一个获取障碍。这意味着内置后的引用不能移动到(或者是 推测到内置之前,但以前的内存存储可能不会 是全局可见的,以前的内存负载可能还没有 满意。