您的位置:首页 > 其它

JOS中 "spinlock" 的实现

2015-02-19 15:42 295 查看
JOS中  "spinlock" 的实现

In software engineering, a spinlock is
a lock which causes a thread trying to acquire it to simply wait in a loop ("spin") while repeatedly checking if the lock is available. Since the thread remains active but is not performing a useful task,the use of such a lock is a kind of busy waiting.

                                                                                   
                                                                   -- from wikipedia

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);
}

原理还是很简单的,只是基于汇编层次的全局变量的busy waiting.

          春节, 快乐

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: