用于从中提到的两个32位计时器计数器读取64位计时器值的序列

在读取之间插入ARM64内存屏障的正确方法是什么?

下面这样的东西合适吗?有人能解释一下在这种情况下如何使用数据存储屏障吗?

do {
  high1 = read(base+4);
  asm volatile("dmb sy");
  low = read(base);
  asm volatile("dmb sy");
  high2 = read(base+4);
  asm volatile("dmb sy");
} while (high2 != high1);

我知道关于如何读取64位定时器的问题已经存在,但并没有关于内存屏障使用的详细信息,我需要这个用于ARM机器-How to read two 32bit counters as a 64bit integer without race condition

推荐答案

内存映射有不同的类型.每种类型都定义了如何进行内存访问以及读/写的可能重新排序.

在这种情况下,例如当指令序列high1 = read(base+4); low = read(base);由CPU(如low = read(base); high1 = read(base+4);)执行时,重新排序.从性能的Angular 来看,这是完全合理的.在CPUtry 执行while (high2 != high1);的阶段,通常情况下,分配给哪个寄存器的第一个"低"或"高1"并不重要.CPU基本上不知道两个单词之间的相互依赖关系.

对于这种64位值的情况,我们应该采取额外的步骤来防止CPU删除这个寄存器依赖项.

第一种也是"最正确的"方法是将计时器映射为"设备"内存.通常,所有硬件映射内存都是"设备"内存设备的内存映射保证了严格的内存顺序.所以CPU不会对内存读取(或写入,或两者)进行任何重新排序,它总是high1lowhigh2.设备内存也是不可缓存的.在这种情况下,这并不重要,但对于使用DMA的东西来说,它可以从维护缓存一致性中节省内存.作为结论,在这种情况下,任何sync barriers for 'device' memory are redundant.

如果你想找麻烦,硬件可能会被映射为"通用"/"通用"内存.

  • high1 = read(base+4); low = read(base);被重新排序并作为low = read(base); high1 = read(base+4);执行
  • 低读数为9999,读数完成后,定时器递增.
  • 现在计时器是0001-0000
  • 高的读数为0001
  • 我们有0001-9999

所以,正如我所看到的,有必要防止读数high1low,以及lowhigh2的重新排序,因为在这两种情况下,我们都可以得到0001-9999种情况(对于第二种情况,高1=0000,高2=0000,低=0000,在high中缺少0001).

我得说

do {
  high1 = read(base+4);
  asm volatile("dmb sy");
  low = read(base);
  asm volatile("dmb sy");
  high2 = read(base+4);
  // asm volatile("dmb sy"); This looks like excessive
} while (high2 != high1);

PS:看起来你不需要像sy这样严格的订单,非常小的一个,保证在特定CPU上的订单应该足够了.

C++相关问答推荐

如何启用ss(另一个调查套接字的实用程序)来查看Linux主机上加入的多播组IP地址?

字符数组,字符指针,在一种情况下工作,但在另一种情况下不工作?

当main函数调用被重构时,C函数给出错误的结果

va_copy的使用是未定义的行为吗?

将 typewriter LF打印到Windows终端,而不是隐含的CR+LF

如何在Visual Studio代码中关闭此函数名称显示功能?

为什么GCC可以调用未定义的函数?

ZED for SDL上的C语言服务器

在传统操作系统上可以在虚拟0x0写入吗?

如何将字符串传递给函数并返回在C中更改的相同字符串?

LibpCap禁用监视器模式(C、MacOS)

在C++中使用函数指针的正确语法

为什么指针运算会产生错误的结果?

在编写代码时,Clion比vscode有更多的问题指示器

类型定义 struct 与简单的类型定义 struct

仅从限制指针参数声明推断非混叠

C代码可以在在线编译器上运行,但不能在Leetcode上运行

Makefile无法将代码刷新到ATmega328p

在列表中查找素数

无法将字符串文字分配给 C 中的字符数组