结构和volatile int的C-联合对struct的更新也是volatile吗?

时间:2018-03-15 18:45:23

标签: c struct volatile unions

如下所示,我有一个具有几个位域的结构。我还有一个包含易失性64位值和此结构的联合。通过联合访问的结构的更改是否也是不稳定的?

即。由于struct和volatile int共享相同的内存位置,对struct的访问是否也会导致访问每次访问的内存,或者编译器会将它们存储在寄存器中?

typedef struct {
  uint64 my_info_1:12;
  uint64 my_info_2:16;
  uint64 reserved: 36;
  } my_info_s;

typedef union {
  my_info_s my_info_struct;
  volatile unsigned long long my_info_vol; //64 bit
} my_info_u;

my_info_u my_info;
//Are these volatile accesses?
my_info.my_info_1 = 4;
my_info.my_info_2 = 8;

//This is the motivation- update a bunch of bitfields, but set them in one shot.
atomic_set(atomic_location, my_info.my_info_vol);

由于一些实时约束,我不能使用锁/互斥锁来实现这一点。

2 个答案:

答案 0 :(得分:1)

我不知道官方标准是什么,但让我们从逻辑上思考这个问题:

联盟

volatile 64位类型只是union的一个选项。如果“每个人都同意”将联盟解释为非易失性类型,那么它就好像该选项不存在 - 除了大小。所以我会说你的工会本质上不稳定。

但是,我建议你:不要将易变的和非易变的成员放在同一个联盟中。这样做只是要求麻烦,混乱和错误。

的Structs

如果一个成员是易失性的,即如果其内容可以在当前执行线程的读取之间进行修改,那么对于包含它的任何结构的定义都是如此 - 其内容(尽管可能只是其中的一部分)也可以因此改性。因此,具有易变成员的结构本身就是不稳定的。

答案 1 :(得分:1)

好吧,正如我所看到的,你的原始问题可以改为“易失性是否等同于线程安全”。悲伤的回答是“不”。

对于多线程代码,有两个主要的敌人:

  1. 编译器级优化。这个可以用“易变”分类器来击败。 (是的,它肯定只是破坏了编译器,将volatile变量优化为寄存器 - 然后,用GCC或CLang等正确的编译器更改编译器)
  2. CPU级优化。是的,在通过内部传送带移动代码时,CPU可以做一些技巧和陷阱来加速整个过程。如果CPU认为执行的总结果不会因给定的优化而改变,那么如果没有特殊的预防措施,您的代码可能会以非常不同的步骤顺序执行。遗憾的是,“易变性”并没有太多帮助建议CPU可以做什么,更重要的是,在传送带优化过程中必须做什么。
  3. 毕竟,一旦你不能使用锁和互斥锁,你似乎正在寻找所谓的“无锁编程”。请看Andrei Alexandrescu的Lock-Free Data StructuresIntroduction to Lock-Free Programming