【问题标题】:C- union of struct and volatile int- are updates to struct also volatile?C- struct 和 volatile int 的联合- 对 struct 的更新也是 volatile 吗?
【发布时间】:2018-03-15 18:45:22
【问题描述】:

如下所示,我有一个包含几个位域的结构。我还有一个包含 volatile 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);

由于某些实时限制,我无法使用锁/互斥锁来实现此目的。

【问题讨论】:

  • stackoverflow.com/questions/4306186/… 你需要考虑填充。确保 sizeof(my_info_s) 为 64。
  • 我不会想到将存储类放在结构或联合的单个成员上甚至是合法的,但我想它在语法上是有效的,因为在 or 中没有两个单独的声明语法结构之外。我认为它没有意义,但现在你问了,我不知道有什么反对它的规则。 (gcc,至少我尝试过的版本,似乎毫无怨言地接受了它们。)
  • 易失位域是什么意思?在不影响结构的其他位的情况下,您无法真正读取或写入 12 位或 36 位。所以看起来像没有。
  • 考虑结构的地址可以被获取并传递给另一个对联合一无所知的模块中的例程。此例程将仅看到非易失性struct 类型的定义,并且编译器在编译此例程时不会将其视为易失性。因此,对与 volatile 对象共享联合的结构的访问不能被认为是 volatile。
  • 鉴于您的“我不能使用锁/互斥锁来实现这个......”,我希望您不要尝试使用 volatile 来使您的代码线程安全,因为那不会工作。请参阅 Volatile: Almost Useless for Multi-Threaded ProgrammingShould volatile Acquire Atomicity and Thread Visibility Semantics? 请注意,第二作者正是 Hans Boehm。

标签: c struct volatile unions


【解决方案1】:

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

联合

volatile 64 位类型只是联合的一种选择。如果“每个人都同意”将联合解释为非易失性类型,那么就好像该选项不存在一样——除了大小方面。所以我想说你的工会本质上不是易变的。

但是,我建议您:永远不要将易失性和非易失性成员放在同一个联合中。这样做只是自找麻烦、混淆和错误。

结构

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

【讨论】:

    【解决方案2】:

    好吧,正如我所见,您最初的问题可以改写为“易失性是否等同于线程安全”。可悲的答案是“不”。

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

    1. 编译器级优化。这可能会被“易失性”分类器打败。 (是的,它肯定只是将 volatile 变量优化为寄存器的损坏的编译器 - 然后,用正确的编译器更改你的编译器,如 GCC 或 CLang)
    2. CPU 级优化。是的,在通过内部传送带移动代码时,CPU 可以做一些技巧和陷阱来加速整个过程。如果 CPU 认为执行的总结果不会因给定的优化而改变,那么如果没有特殊的预防措施,您的代码可能会以非常不同的步骤顺序执行。遗憾的是,“volatile”对于建议 CPU 可以做什么,更重要的是,在传送带优化期间不能做什么并没有多大帮助。

    毕竟,一旦您不能使用锁和互斥锁,您似乎正在寻找所谓的“无锁编程”。看看 Andrei Alexandrescu 的 Lock-Free Data Structures 或这个 Introduction to Lock-Free Programming

    【讨论】:

      猜你喜欢
      • 2011-05-27
      • 2014-10-20
      • 2011-12-09
      • 1970-01-01
      • 1970-01-01
      • 2013-12-19
      • 2021-06-03
      • 1970-01-01
      相关资源
      最近更新 更多