C语言 32位系统中16位操作的原子性

rqcrx0a6  于 2023-01-29  发布在  其他
关注(0)|答案(2)|浏览(210)

考虑一个32位系统(例如ARM RISC MCU),如何确保16位变量以原子方式写入/读取?基于this doc,如果我理解正确,16位和8位操作都是原子操作,但仅假设内存对齐。问题是,编译器是否总是将内存与32位字对齐(不包括压缩结构等情况)?
这里的基本原理是尽可能使用uint16_t而不是uint32_t,以便在32位和16位平台之间实现更好的代码可移植性,这与在两个平台(16位或32位)上定义不同类型无关。

5anewei6

5anewei61#

编译器可以根据自己的意愿对齐任何(标量)对象,除非它是数组或类似对象的一部分,C语言对此没有任何限制或保证。数组可以保证连续分配,没有填充。并且结构体/联合体的第一个成员可以通过be aligned来保证(因为结构体/联合体的地址可以转换为指向第一个成员类型的指针)。
要获得原子操作,如果编译器支持的话,你必须使用类似atomic_uint_fast16_t(stdatomic. h)的东西,否则C中的任何操作都不能被认为是原子的,不管是类型、句点。
一个常见的错误是认为“8位拷贝在我的CPU上是原子的,所以如果我使用8位类型,我的代码是可重入的”。这不是,因为uint8_t x = y;不保证在单个指令中完成,也不保证导致原子机器代码指令。
即使选择了一条原子指令,你仍然可以从这样的代码中获得实时错误。

  • y的内容存储在寄存器A中。
  • 一个在满月时才发生一次的中断触发,改变y
  • y的旧值存储在x中-耶,这是一条原子指令!
  • 现在x具有旧的、过时的值。

正确的实时行为应该是在中断命中之前完全更新x,或者在中断命中之后更新它。

67up9zun

67up9zun2#

我工作的地方与所有相关编译器供应商有一个特殊协议,他们负责通知我们的工具链Maven假设不适用的情况。
事实证明这是必要的,因为否则就不能可靠地确定。文档没有说明,标准更没有说明。
或者说,这是模具制造人员告诉我的。
所以对你来说答案似乎是:问供应商。

相关问题