【问题标题】:What does assignment mean to a C11 atomic?赋值对 C11 原子意味着什么?
【发布时间】:2016-07-04 15:58:01
【问题描述】:

例如,

atomic_int test(void)
{
  atomic_int tmp = ATOMIC_VAR_INIT(14);
  tmp = 47;                    // Looks like atomic_store
  atomic_int mc;               // Probably just uninitialised data
  memcpy(&mc,&tmp,sizeof(mc)); // Probably equivalent to a copy
  tmp = mc + 4;                // Arithmetic
  return tmp;                  // A copy - perhaps load then store
}

Clang 对这一切都很满意。我已经阅读了标准的第 7.17 节,它说了很多关于内存模型和定义的函数(init、store、load 等),但没有说任何关于通常的操作(+、= 等)。

同样令人感兴趣的是将struct wot { atomic_int value; } 传递给函数的行为。

我想相信分配的行为与原子加载相同,然后使用 memory_order_seq_cst 存储。

更乐观的是,我愿意相信结构赋值、传递给函数、从函数返回甚至 memcpy 的行为与在 memory_order_seq_cst 下小心复制位模式的行为相同。

不过,我找不到任何支持证据来支持这两种信念的标准。原子原语的赋值和 memcpy 肯定有可能是未定义的行为。

对原子原语的原语操作应该如何表现?

谢谢!

【问题讨论】:

    标签: atomic c11


    【解决方案1】:

    _Atomic 限定的对象的操作(atomic_int 只是对此的不同写法)保证具有顺序一致性。您会发现在每个操作数的语义部分末尾都提到了这一点。 (也许没有提到分配。)

    您的代码在两个地方不正确:初始化必须使用 ATOMIC_VAR_INIT 宏 (7.17.2.1),以及 memcpy 未定义(大小可能不一致),尽管它可能适用于大多数架构.

    也行

    tmp = mc + 4;                // Arithmetic
    

    没有按照您的评论声称的那样做。这不是对原子对象的算术运算,而是一个加载,然后是一个普通的加法。更有趣的是

    mc += 4;                // Arithmetic
    

    这是一个具有顺序一致性的原子操作。

    【讨论】:

    • 谢谢!如果满足通常的大小和对齐约束,是否在 _Atomic 类型上定义了 memcpy?上面的示例是两个 _Atomic int 之间的 memcpy,它们的大小彼此相同,但我也倾向于使用 memcpy 往返对齐的 char 数组作为一种封装技术,我很遗憾放弃了 _Atomic 字段在一个结构中。
    • 不,对_Atomic 的访问只有通过运算符或函数才有效。显然,如果你在做memcpy,就不能保证原子性。
    • 抱歉,我找到了我的答案。唯一让我困惑的是,如果一个简单的赋值是原子的,为什么要有 ATOMIC_VAR_INIT() 和 atomic_init(),而 atomic_load 也可以这样做?
    • @JensGustedt 是的,我同意。我删除了 cmets,因为我在您回复之前找到了答案,但请阅读上述评论。
    • @2501,你的意思可能是atomic_store_Atomic 对象的初始化比 atomic_store 更“便宜”,因为不能保证初始化是原子操作。这个想法是在初始化的那一刻不能有竞争条件,因为没有其他人知道这个对象。
    猜你喜欢
    • 2015-04-05
    • 2020-09-08
    • 1970-01-01
    • 1970-01-01
    • 2020-03-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多