在xv6 中锁对象是 spinlock,spinlock中的locked为1的时候表示被占用,为0的时候锁空闲。函数
struct spinlock { uint locked; // Is the lock held? ...... };
使用 acquire获取锁ui
void acquire(struct spinlock *lk) { ........ while(xchg(&lk->locked, 1) != 0); ...... }
该函数中经过xchg原子性交换locked和1,并返回locked的原来的值。当返回值为1时,说明其余线程占用了该锁,继续循环等待;当返回值为0时,说明其余地方没有占用该锁,同时locked本设置成1了,因此该锁被此处占用。atom
static inline uint xchg(volatile uint *addr, uint newval) { uint result; // The + in "+m" denotes a read-modify-write operand. asm volatile("lock; xchgl %0, %1" : "+m" (*addr), "=a" (result) : "1" (newval) : "cc"); /* //最终汇编相似于 movq *addr, %rdx movl newval, %eax lock; xchgl (%rdx), %eax movl %eax, result */ return result; }
xchg经过lock xchg实现原子性的交换,把*addr的老值放入eax中,而后在赋值给result。spa
释放锁线程
void release(struct spinlock *lk) { ... // Release the lock, equivalent to lk->locked = 0. // This code can't use a C assignment, since it might // not be atomic. A real OS would use C atomics here. asm volatile("movl $0, %0" : "+m" (lk->locked) : ); ... }