JOS中 "spinlock" 的实现
XCHG instruction Swaps data between two registers or a register and memory location.
LOCK汇编指令用于封锁总线.
static inline uint32_t xchg(volatile uint32_t *addr, uint32_t newval) { uint32_t result; // The + in "+m" denotes a read-modify-write operand. asm volatile("lock; xchgl %0, %1" : "+m" (*addr), "=a" (result) : "1" (newval) : "cc"); return result; }每次都会返回addr指向地址处原来的值.
于是乎,在JOS中,spinlock的实现如下:
./kern/spinlock.h 这里利用结构体struct spinlock来抽象封装spinlock.
实质上,spinlock是个全局变量.这里具体的就是./kern/spinlock.h 中的全局变量结构体
extern struct spinlock kernel_lock.
// Mutual exclusion lock. struct spinlock { unsigned locked; // Is the lock held? }; void __spin_initlock(struct spinlock *lk, char *name); void spin_lock(struct spinlock *lk); void spin_unlock(struct spinlock *lk); #define spin_initlock(lock) __spin_initlock(lock, #lock) extern struct spinlock kernel_lock; static inline void lock_kernel(void) { spin_lock(&kernel_lock); } static inline void unlock_kernel(void) { spin_unlock(&kernel_lock); // Normally we wouldn't need to do this, but QEMU only runs // one CPU at a time and has a long time-slice. Without the // pause, this CPU is likely to reacquire the lock before // another CPU has even been given a chance to acquire it. asm volatile("pause"); }
// Mutual exclusion spin locks. // The big kernel lock struct spinlock kernel_lock = { #ifdef DEBUG_SPINLOCK .name = "kernel_lock" #endif }; spinlock锁的初始化 void __spin_initlock(struct spinlock *lk, char *name) { lk->locked = 0; } // Acquire the lock. // Loops (spins) until the lock is acquired. // Holding a lock for a long time may cause // other CPUs to waste time spinning to acquire it. void spin_lock(struct spinlock *lk) { // The xchg is atomic. // It also serializes, so that reads after acquire are not // reordered before it. while (xchg(&lk->locked, 1) != 0) asm volatile ("pause"); } // Release the lock. void spin_unlock(struct spinlock *lk) { // The xchg serializes, so that reads before release are // not reordered after it. The 1996 PentiumPro manual (Volume 3, // 7.2) says reads can be carried out speculatively and in // any order, which implies we need to serialize here. // But the 2007 Intel 64 Architecture Memory Ordering White // Paper says that Intel 64 and IA-32 will not move a load // after a store. So lock->locked = 0 would work here. // The xchg being asm volatile ensures gcc emits it after // the above assignments (and after the critical section). xchg(&lk->locked, 0); }
春节, 快乐
原文地址:http://blog.csdn.net/cinmyheart/article/details/43880517