Amo*_*mum 6 assembly arm atomic
由于我的编译器仍然不支持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) );
Run Code Online (Sandbox Code Playgroud)
我找不到关于指向手册中不同地址的几个连续LDREX或STREX指令的任何内容,但在我看来应该允许它.
否则,在某些情况下,多个线程将无法更改两个不同的原子变量.
这将无法工作,因为您不能以这种方式嵌套独占.实现方面,Cortex-M3本地专用监视器甚至不跟踪地址 - 独占预留颗粒是整个地址空间 - 因此单独跟踪每个单词的假设已经无效.但是,您甚至不需要考虑任何实现细节,因为该体系结构已明确排除背靠背strex:
如果在没有插入LDREX的情况下执行两条STREX指令,则第二个STREX返回状态值1.这意味着:
- 每个STREX必须在给定的执行线程中具有与之关联的先前LDREX.
- 每个LDREX都不必具有后续STREX.
由于Cortex-M3(以及一般的ARMv7-M)没有ldrexd像ARMv7-A那样,你要么必须使用单独的锁来控制对变量的所有访问,要么只是禁用read-modify-write周围的中断.如果可能的话,首先重新设计不需要原子64位类型的东西真的会更好,因为你仍然只能在同一个核心上实现相对于其他线程的原子性 - 你根本就不能做任何64从外部代理(如DMA控制器)的角度来看,位操作原子.