所以我有一段代码如下:
uint8_t *buffer = <16 MB memory region>
uint32_t count = 1024;
uint32_t position = 0;
uint8_t *get_data() {
uint8_t *region = buffer + position * 16;
position += 1;
position %= count;
do {
__sync_synchronize();
} while (reigon[0] != 1);
return region;
}
有问题的缓冲区正由硬件设备写入。在某些时候(可能在我们开始循环之前,也许在我们开始之后),硬件将写入该位置以及缓冲区的其余部分。
我目前正在使用__sync_synchronize来发出内存屏障,因为我想确保编译器无法在region[0] == 1
之前的任何时间导致其余的内存区域被缓存。
我知道我可以将整个缓冲区标记为volatile。但是,我希望能够从此函数返回非易失性缓冲区。
那么,有没有办法做__sync_synchronize
,但只能让它以我指定的内存范围为目标。在这种情况下,来自[region, region + 1024)
?
顺便说一句,此代码存在于用户空间中。内存缓冲区是一个固定的内存区域,我已经分配了内核模块,映射到用户空间,并告诉FPGA最终DMA到它。这是在试图在FPGA完成DMA传输时实施轮询机制。
答案 0 :(得分:2)
区域限制的内存栅栏将是一个相当不寻常的架构特征。但是,在循环终止后,您只需要栅栏:
while (*(volatile uint8_t *)region != 1)
;
__sync_synchronize();
return region;
答案 1 :(得分:0)
这应该可以解决问题:
uint8_t *get_data() {
uint8_t *region = buffer + position * 16;
volatile uint8_t *volatile_region = region;
position += 1;
position %= count;
do {
} while (volatile_region[0] != 1);
return region;
}