分析Linux中Spinlock在ARM及X86平台上的实现
__raw_spin_lock(raw_spinlock_t *lock) { unsigned long tmp; __asm__ __volatile__( "1: ldrex %0, [%1]n" //取lock->lock放在 tmp里,并且设置&lock->lock这个内存地址为独占访问 " teq %0, #0n" //测试lock_lock是否为0,影响标志位z #ifdef CONFIG_CPU_32v6K " wfenen" #endif " strexeq %0, %2, [%1]n" //如果lock_lock是0,并且是独占访问这个内存,就向lock->lock里写入1,并向tmp返回0,同时清除独占标记 " teqeq %0, #0n" //如果lock_lock是0,并且strexeq返回了0,表示加锁成功,返回 " bne 1b" //如果上面的条件(1:lock->lock里不为0,2:strexeq失败)有一个符合,就在原地打转 : "=&r" (tmp) //%0:输出放在tmp里,可以是任意寄存器 : "r" (&lock->lock), "r" (1) //%1:取&lock->lock放在任意寄存器,%2:任意寄存器放入1 : "cc"); //状态寄存器可能会改变 smp_mb(); } 上述代码关键在于LDREX和STREX指令的应用.DREX和STREX指令是在V6以后才出现的,代替了V6以前的swp指令.可以让bus监控LDREX和STREX指令之间有无其它CPU和DMA来存取过这个地址,若有的话STREX指令的第一个寄存器里设置为1(动作失败),若没有,指令的第一个寄存器里设置为0(动作成功). 不仅是自旋锁用到LDREX和STREX指令,信号量的实现也是利用LDREX和STREX指令来实现的.
4、__raw_spin_lock在X86处理器上的实现 /******include/asm-i386/spinlock_types.h***/ typedef struct { /******include/asm-i386/spinlock.h***/ static inline void __raw_spin_lock(raw_spinlock_t *lock) 在多处理器环境中 LOCK_PREFIX 实际被定义为 “lock”前缀.x86 处理器使用“lock”前缀的方式提供了在指令执行期间对总线加锁的手段.芯片上有一条引线 LOCK,如果在一条汇编指令(ADD, ADC, AND, BTC, BTR, BTS, CMPXCHG, CMPXCH8B, DEC, INC, NEG, NOT, OR, SBB, SUB, XOR, XADD, XCHG)前加上“lock” 前缀,经过汇编后的机器代码就处 |
|
凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢! |