阅读 this question 的答案时,我注意到 register
在 C++17 中不再是有效的存储说明符。一些评论甚至表明编译器已经忽略 register
一段时间了。
我将 GCC 6.x 与 ARM Cortex-M MCU 一起使用,并且有一些带有内联汇编的代码,这些代码绝对需要在寄存器中有一个变量。以前我认为 register
关键字会为我做这件事,但显然它没有。
编辑 :为什么我需要在寄存器中存储一些东西?
我正在使用 ARM
LDREX
/STREX
指令实现无锁环形缓冲区。我需要将 ARM LDREX
指令的结果存储在寄存器中,因为将其存储在内存中会破坏 Cortex-M 上的整个机制。编辑 :示例代码。
这是从环形缓冲区中截取的代码片段,用于说明问题的要点。兴趣点是
__LDREXW
、 __STREXW
和 __CLREX
,它们都在 cmsis_gcc.h
中定义。 They are intrinsic functions of the ARM synchronization primitives. 我用它们来实现无锁机制。template<typename T, uint32_t maxCount>
class RingBuffer final {
__attribute__((aligned(8)))
T buffer[maxCount];
uint32_t start;
uint32_t end;
bool pushBack(const T &item) {
register uint32_t exclusiveEnd;
register uint32_t oldEnd;
do {
// Load current end value exclusively
exclusiveEnd = __LDREXW(&end);
__DMB();
// Remember old end value so that
// we can store the item at that location
oldEnd = exclusiveEnd;
// Check if ring buffer is full
if (isFull()) {
__CLREX();
__DMB();
return false;
}
// Figure out correct new value
if (exclusiveEnd == (maxCount - 1)) {
exclusiveEnd = 0;
}
else {
exclusiveEnd ++;
}
// Attempt to store new end value
} while (0 != __STREXW(exclusiveEnd, &end));
__CLREX();
__DMB();
// Store new item
//memcpy(buffer + oldEnd, &item, sizeof(T));
buffer[oldEnd] = item;
return true;
}
// ... other methods ...
}
为什么
LDREX
结果必须存储在寄存器中:在 Cortex-M4 上,实现的独占保留粒度是整个内存地址范围(引用自 Cortex-M4 TRM),这意味着如果存储
LDREX
结果的变量最终在内存中而不是寄存器中,那么以下 STREX
将始终失败.注意:此代码在“裸机”硬件上运行,没有操作系统等。
最佳答案
你不能这样做(在可移植的标准 C++ 或 C 代码中)。您需要 信任您的编译器 ,因此您甚至不应该这样做。
请注意:
register
关键字 只是 (在上个世纪) 编译器的提示 。 但是,作为 扩展 GCC 编译器使您能够放置 variable in a specified register 。 我不建议在没有充分理由的情况下使用 (至少确保在使用和不使用该功能的情况下对代码进行基准测试)。
您确实需要了解 当前编译器在大多数情况下都是 优化得比 更好。在尝试手动优化之前,请务必对您的代码进行基准测试(例如,使用
g++ -O3
和适当的 -mtune=
参数编译)。对于性能敏感的例程,还要检查生成的汇编代码(例如使用 g++ -O3 -fverbose-asm -S
)。然后我建议使用一个小的 extended assembler 代码(用于 GCC),或者,如果绝对必要,声明一个 variable in a specified register
也许您还需要使用
-ffixed-
reg 选项编译所有代码(包括任何使用过的库,包括标准 C 和 C++ 库!)。但我坚持:你需要比现在更信任你的编译器。您确定找不到(并且可能从源代码配置和构建)最近的 GCC(例如 GCC 7),它可以作为内置或其他东西启用您的低级同步机制?
关于c++ - 告诉编译器我希望变量始终存储在寄存器中的正确方法是什么?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/44721905/