繁体   English   中英

ARM Cortex M3上的Atomic int64_t

[英]Atomic int64_t on ARM Cortex M3

由于我的编译器仍然不支持c ++ 11和std :: atomic,我不得不通过ldrex-strex对手动实现它。

我的问题是:用ldrex和strex“原子地”读取 - 修改 - 写入int64_t的正确方法是什么?

像这样的简单解决方案似乎不起作用(STREXW之一始终返回1):

volatile int64_t value;
int64_t temp;

do
{
    int32_t low = __LDREXW( (uint32_t *)&value );
    int32_t high = __LDREXW( ((uint32_t *)&value)+1 );

    temp = (int64_t)low | ( (int64_t)high<<32);
    temp++;    

} while( __STREXW( temp, (uint32_t *)&value) |  __STREXW( temp>>32, ((uint32_t *)&value)+1) );

我找不到关于指向手册中不同地址的几个连续LDREX或STREX指令的任何内容,但在我看来应该允许它。

否则,在某些情况下,多个线程将无法更改两个不同的原子变量。

这将无法工作,因为您无法以这种方式嵌套。 实现方面,Cortex-M3本地专用监视器甚至不跟踪地址 - 独占预留颗粒是整个地址空间 - 因此单独跟踪每个单词的假设已经无效。 但是,您甚至不需要考虑任何实现细节,因为该体系结构已经明确排除了背对背strex

如果在没有插入LDREX的情况下执行两条STREX指令,则第二个STREX返回状态值1.这意味着:

  • 每个STREX必须在给定的执行线程中具有与之关联的先前LDREX。
  • 每个LDREX都不必具有后续STREX。

由于Cortex-M3(以及一般的ARMv7-M)没有像ARMv7-A那样的ldrexd ,因此您必须使用单独的锁来控制对变量的所有访问,或者只是禁用读取 - 修改周围的中断 -写。 如果可能的话,首先重新设计不需要原子64位类型的东西真的会更好,因为你仍然只能在同一个核心上实现相对于其他线程的原子性 - 你根本就不能做任何64从外部代理(如DMA控制器)的角度来看,位操作原子。

我只看看gcc是如何做到的,并使用相同的指令序列。

gcc 4.8.2 声称实现std::atomic<int64_t>is_lock_free()返回true,即使使用-mcpu=cortex-m3 不幸的是,它并没有真正起作用。 它使得代码不链接或不起作用,因为它没有实现它试图使用的辅助函数 (感谢@Notlikethat试用它。)

这是我试过的测试代码 如果该链接已死,请查看此答案的旧版本。 我将离开这个答案,以防这个想法对gcc 确实有用的代码的相关情况下的任何人都有用。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM