将指针转换为_Atomic指针和_Atomic大小 [英] Casting pointers to _Atomic pointers and _Atomic sizes

查看:259
本文介绍了将指针转换为_Atomic指针和_Atomic大小的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

通过阅读标准,
*(_ Atomic TYPE *)&(TYPE){0} (换句话说,将指针投射到a

By my reading of the standard, *(_Atomic TYPE*)&(TYPE){0} (in words, casting a pointer to a non-atomic to a pointer to a corresponding atomic and dereferencing) isn't supported.

如果 TYPE 是/不是无锁的吗? (问题1)

Do gcc and/or clang recognize it as an extension if TYPE is/isn't lock-free? (Question 1)

第二个相关问题:我的印象是,如果 TYPE 无法实现作为无锁原子,需要将锁嵌入到相应的 _Atomic TYPE 中。但是,如果我将 TYPE 设为比较大的结构,则同时在 clang gcc 具有与 _Atomic TYPE 相同的大小。

Second and related question: I was under the impression that if TYPE couldn't be implemented as a lock free atomic, a lock would need to be embedded in the corresponding _Atomic TYPE. But if I make TYPE a largish struct, then on both clang and gcc it has the same size as _Atomic TYPE.

两个问题的代码:

#include <stdatomic.h>
#include <stdio.h>

#if STRUCT
typedef struct {
    int x;
    char bytes[50];
} TYPE;
#else
typedef int TYPE;
#endif

TYPE x;

void f (_Atomic TYPE *X)
{
    *X = (TYPE){0};
}

void use_f()
{
    f((_Atomic TYPE*)(&x));
}

#include <stdio.h>
int main()
{
    printf("%zu %zu\n", sizeof(TYPE), sizeof(_Atomic TYPE));
}

现在,如果我使用编译以上代码段, DSTRUCT ,gcc和clang都将struct和它的atomic变量都保持在相同的大小,并且它们生成对名为 __ atomic_store 的函数的调用商店中的商品(通过与 -latomic 链接来解决)。

Now, if I compile the above snippet with -DSTRUCT, both gcc and clang keep the both the struct and its atomic variant at the same size, and they generate a call to a function named __atomic_store for the store (resolved by linking with -latomic).

如果未嵌入任何锁,该如何工作 _Atomic 版本的结构? (问题2)

How does this work if no lock is embedded in the _Atomic version of the struct? (Question 2)

推荐答案

_Atomic 会更改某些情况下的对齐方式Clang和GCC将来也可能会得到修复( PR 65146 )。在这些情况下,通过强制转换添加 _Atomic 是行不通的(从C标准的角度来看这很好,因为它是未定义的行为,如您所指出)。

_Atomic changes alignment in some corner cases on Clang, and GCC will likely be fixed in the future as well (PR 65146). In these cases, adding _Atomic through a cast does not work (which is fine from a C standard point of view because it is undefined behavior, as you pointed out).

如果对齐正确,则更适合使用 __ atomic 内置函数,它们是专门为此用途而设计的情况:

If the alignment is correct, it is more appropriate to use the __atomic builtins, which have been designed for exactly this use case:

  • Built-in Functions for Memory Model Aware Atomic Operations

如上所述,这不会如果ABI无法为普通(非原子)类型提供对齐方式,并且 _Atomic 会更改对齐方式(仅适用于Clang),则可以使用该功能。

As described above, this will not work in cases where the ABI provides insufficient alignment for plain (non-atomic) types, and where _Atomic would change alignment (with Clang only for now).

这些内建函数在非原子类型的情况下也可以使用,因为它们使用行外锁。这也是为什么使用相同机制的 _Atomic 类型不需要额外的存储的原因。这意味着由于无意间共享锁,存在一些不必要的争用。这些锁的实现方式是一个实现细节,可以在 libatomic 的未来版本中更改。

These builtins also work in case of non-atomic types because they use out-of-line locks. This is also the reason why no additional storage is required for _Atomic types, which use the same mechanism. This means that there is some unnecessary contention due to unintentional sharing of the locks. How these locks are implemented is an implementation detail which could change in future versions of libatomic.

通常,对于具有涉及锁定的原子内建函数的类型不起作用,无法将它们与共享或别名内存映射一起使用。这些内建函数也不是异步信号安全的。 (无论如何,所有这些功能在技术上都超出了C标准。)

In general, for types with atomic builtins that involve locking, using them with shared or aliased memory mappings does not work. These builtins are not async-signal-safe, either. (All these features are technically outside the C standard anyway.)

这篇关于将指针转换为_Atomic指针和_Atomic大小的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆