__raw_spin_lock在ARM处理器上的实现
static inline void arch_spin_lock(arch_spinlock_t *lock)
{
unsigned long tmp;
__asm__ __volatile__(
//LDREX Rx, [Ry] 读取寄存器Ry指向的4字节内存值,将其保存到Rx寄存器中,同时标记对Ry指向内存区域的独占访问,这里是读取&lock->lock的值到tmp,并设置&lock>lock为独占访问
"1: ldrex %0, [%1]\n"
//测试tmp是否为0
" teq %0, #0\n"
WFE("ne")
//STREX Rx, Ry, [Rz]如果执行这条指令的时候发现已经被标记为独占访问了,则将寄存器Ry中的值更新到寄存器Rz指向的内存,并将寄存器Rx设置成0。指令执行成功后,会将独占访问标记位清除。
//而如果执行这条指令的时候发现没有设置独占标记,则不会更新内存,且将寄存器Rx的值设置成1
//如果&lock->lock被独占访问,则设置&lock->lock的值为1,加锁,并修改tmp的值为0;否则设置tmp的值为1
" strexeq %0, %2, [%1]\n"
//测试tmp的值是否为0
" teqeq %0, #0\n"
//如果tmp的值不为0,则跳转到1标号处循环
" bne 1b"
: "=&r" (tmp)
: "r" (&lock->lock), "r" (1)
: "cc");
smp_mb();
}
关于LDREX和STREX指令的独占访问介绍可以参考以下链接
ARM平台下独占访问指令LDREX和STREX的原理与使用详解