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

inn6fuwd  于 2023-06-05  发布在  其他
关注(0)|答案(2)|浏览(198)

如下所示,我有一个结构体,它有几个位域。我还有一个包含volatile 64位值和此结构的联合。通过联合访问的结构的更改是否也是易失性的?
也就是说,由于结构体和volatile int共享相同的内存位置,对结构体的访问是否也会导致每次访问都访问内存,或者编译器会将它们存储在寄存器中?

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);

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

nom7f22z

nom7f22z1#

好吧,正如我所看到的,您最初的问题可以改为“volatile是线程安全的等价物吗”。可悲的答案是“不”。
对于多线程代码,有两个主要的敌人:
1.编译器级优化。这一个可以被“易失性”分类器击败。(是的,它肯定只是损坏的编译器,优化volatile变量作为寄存器-然后,用正确的编译器(如GCC或CLang)更改编译器)

  1. CPU级优化。是的,当你的代码通过内部传送器移动时,CPU可以做一些技巧和陷阱来加速整个过程。如果没有特别的预防措施,你的代码可能会以非常不同的步骤顺序执行,如果CPU认为执行的总结果不会被给定的优化改变。可悲的是,“volatile”对建议CPU可以做什么没有多大帮助,更重要的是,在传送带优化期间,什么不可以做。
    毕竟,一旦你不能使用锁和互斥锁,似乎你正在寻找所谓的“无锁编程”。看看Andrei Alexandrescu的Lock-Free Data Structures或这个Introduction to Lock-Free Programming
p4tfgftt

p4tfgftt2#

我不知道官方标准是怎么说的,但让我们从逻辑上思考一下:

联合

volatile 64位类型只是联合的一个选项。如果“每个人都同意”将工会解释为非易失性类型,那么就好像这个选项不存在一样--除了在规模方面。所以我想说你们的结合并不是天生的不稳定。
不过,我建议你:**永远不要将volatile和nonvolatile成员放在同一个联盟中。**这样做只会带来麻烦、混乱和bug。

结构体

如果成员是易失性的,即如果它的内容可以在当前执行线程的读取之间被修改,则根据定义,对于包含它的任何结构都是如此,它的内容(尽管可能只是其中的一些)也可以因此被修改。所以有volatile成员的结构体本身也是volatile的

相关问题