gcc原子内置和可用性版本

时间:2016-04-07 08:36:16

标签: c gcc

我正在尝试验证我是否可以在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位原子商店吗? 谢谢

2 个答案:

答案 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中的确切值是   实施定义。

     

这种内置不是一个完整的障碍,而是一个获取障碍。这意味着内置后的引用不能移动到(或者是   推测到内置之前,但以前的内存存储可能不会   是全局可见的,以前的内存负载可能还没有   满意。