ARM V6 和V6+架构中的原子指令

ARM V6

ARM V6中原子指令是:

SWP 指令

该指令可以实现寄存器和内存之间的原子交换, 但是由于该指令要lock住BUS, 所以会影响系统性能.
例子:
sem_wati:MOV R1,#0
LDR R0,=SEM
SWP R1,R1,[R0] ;取出信号量,并设置其为0
CMP R1,#0 ;判断是否有信号
BEQ sem_wait ;若没有信号,则等待
所以在内核中, V6以前的架构, atomic_add/sub 之类的指令都是用
raw_local_irq_save(flags)
val = v->counter;
v->counter = val += 1;
raw_local_irq_restore(flags)
来实现的.

ARM V6 以后, V7, V8中

提供LDREX和STREX来替换SWP指令, 实现对原子的内存操作.
LDREX <Rt>,[Rn]STREX <Rd>,<Rt>,[Rn] ;STREX成功,Rd置0
所以Linux内核就可以利用这个指令来做原子操作, 内核中的atomic_add 实现就是
 static inline void atomic_add(int i, atomic_t *v)
static inline void atomic_add(int i, atomic_t *v)
{
     unsigned long tmp;
     int result;

     __asm__ __volatile__("@ atomic_addn"
"1:     ldrex     %0, [%3]n"    // 先读入counter
"     add     %0, %0, %4n"     // 再把counter+i
"     strex     %1, %0, [%3]n"  // 把counter再写到result的地址, 并且放返回值到tmp里面.
"     teq     %1, #0n"                // 检查tmp和0相等否
"     bne     1b"                          // 如果不相等, 再重新来一次. 防止被其他的CPU或者其他的竞争条件.
     : "=&r" (result), "=&r" (tmp), "+Qo" (v->counter)
     : "r" (&v->counter), "Ir" (i)
     : "cc");
}
下面是一些ARM V6+架构对该指令的内部实现,(参考:http://www.keil.com/support/man/docs/armasmref/armasmref_Cihbghef.htm)

LDREX loads data from memory.If the physical address has the Shared TLB attribute, LDREX tags the physical address as exclusive access for the current processor, and clears any exclusive access tag for this processor for any other physical address.

Otherwise, it tags the fact that the executing processor has an outstanding tagged physical address.

(如果物理地址在TLB中, 那么LDREX就标识该地址为当前CORE的排他使用(exclusive access), 而且清楚掉该Core对其他的地址的exclusive access.
如果不在TLB中, 那么就标志当前CPU有一个outstanding tagged 物理地址, 我想应该是一个特殊的物理地址访问的意思.)

STREX performs a conditional store to memory. The conditions are as follows:If the physical address does not have the Shared TLB attribute, and the executing processor has an outstanding tagged physical address, the store takes place, the tag is cleared, and the value 0 is returned in Rd.

(如果该物理地址没有share TBL 属性, 也就是没有load到TLB中, 当前执行的CPU有一个"outstanding tagged physical address", 那么存储会直接存进去, 清除tag, 然后再Rd里面返回0)

    If the physical address does not have the Shared TLB attribute, and the executing processor does not have an outstanding tagged physical address, the store does not take place, and the value 1 is returned in Rd. (如果物理地址没有在TBL中, 而且当前执行CPU没有一个outstanding tagged physical address, 那么这次store不发生, 并且返回1在Rd中).If the physical address has the Shared TLB attribute, and the physical address is tagged as exclusive access for the executing processor, the store takes place, the tag is cleared, and the value 0 is returned in Rd.

(如果物理地址已经有一个TLB的属性, 而且该物理地址已经被标识为exclusive access, 那么存储发生, 并且清掉TAG, 在Rd中返回0)

If the physical address has the Shared TLB attribute, and the physical address is not tagged as exclusive access for the executing processor, the store does not take place, and the value 1 is returned in Rd.
(如果该地址已经有TLB的属性, 但是物理地址没有tag成exclusive access, 存储不发生, 并且在Rd中返回0.