进程切换是否会影响arm9处理器中的std :: atomic比较和交换?

时间:2018-09-26 08:27:57

标签: c++11 arm context-switch stdatomic

我是c ++中std :: atomic的新手,试图了解ARM处理器下比较和交换操作的实现。我在Linux上使用gcc。

当我查看汇编代码时

    mcr p15, 0, r0, c7, c10, 5
.L41:
    ldrexb  r3, [r2]
    cmp r3, r1
    bne .L42
    strexb  ip, r0, [r2]
    cmp ip, #0
    bne .L41
.L42:
    mcr p15, 0, r0, c7, c10, 5

我的理解是

  1. 它需要多条指令来进行比较和交换。
  2. ldrex将内存位置标记为互斥并读取数据。
  3. strex存储数据并清除该标志的独占标志 位置。

我的问题是

  1. ldrex标记虚拟地址。作为专有地址还是实际地址?

  2. 如果进程P1将虚拟地址标记为互斥,并且进程切换到P2,则该虚拟地址将被转换为P2。在P2中可以访问?如果P2还对同一地址执行ldrex,将会发生什么情况。

  3. 如果进程P1将物理地址标记为互斥,并且发生进程切换,则当P1恢复时,由于现在数据没有可能驻留在物理内存中的其他位置,分页。

我试图理解这一点,因为,我想对多个进程访问的共享内存位置进行比较和交换。

我的c ++函数看起来像

std::atomic<bool> *flag;  
flag = (std::atomic<bool> *) (shm_ptr);  
bool temp = false ;  
while(!std::atomic_compare_exchange_strong((flag),&temp,true))  
{  
std::this_thread::yield();  
}  
// update shared memory  
std::atomic_store((flag), false);

1 个答案:

答案 0 :(得分:1)

是的,在ARM的所有主流C ++实现中,在不同进程映射的共享内存上使用无锁std::atomic<T>是安全的。

但是非无锁原子将不起作用,因为不同的进程不会共享同一张锁表。


strex完成之前的中断将导致失败。您不必担心内核代码会在ldrex和strex之间更改页表。

在同一个或另一个CPU上发生中断后,在中间恢复此代码将意味着strex完全失败,因为它不是作为由ldrex启动的“事务”的一部分而执行的。


原子性在ARM上以及在所有实现C ++ 11无锁原子的普通主流系统上都是无地址的。

如果不同内核上的两个线程/进程将相同的物理页面映射到不同的虚拟地址,则一切仍然有效。 C ++ 11标准明确建议,对于无锁std::atomic<T>,实现应以这种方式工作。 (它并没有要求它,因为那样的话,它就必须定义一个进程是什么,并具有重新映射虚拟内存的功能。)

这几乎是Are lock-free atomics address-free in practice?的副本。有关标准和更多详细信息的引用,请参见。


现代计算机系统确保其缓存不存在别名同名/同义词问题,因为这通常会导致一致性问题,而不仅仅是原子RMW。有时,这需要OS内核的配合(例如,如果一个缓存索引位来自页码而不是地址的一页内偏移量,则页面着色),但是通常,缓存的行为是物理的。

(某些早期的CPU,例如早期的MIPS,有时确实使用了虚拟寻址的L1数据高速缓存,但是在支持多个CPU的系统AFAIK上并没有做到这一点。)