//代码复制自<操作系统导论>一书
//Peterson算法
int flag[2];
int turn;
void init()
{
flag[0] = flag[1] = 0;//1->thread wants to grab lock
turn = 0;//whose turn? (thread 0 or 1?)
}
void lock()
{
flag[self] = 1; //self: thread ID of caller
turn = 1 - self;//make it other thread's turn
while((flag[1-self] == 1) && (turn == 1 - self))
//(flag[1-self] == 1)这是检查另一个thread是否想获取锁。
//假设self=0,则turn=1,那么就表明让thread 1 运行
//如果self还是=0,而turn却=0,那么就表明该让thread 0运行了,就退出这个循环。
// 两个判断语句都为真,则等待。
; //spin-wait
}
void unlock()
{
flag[self] = 0;
}
//c伪代码实现 测试并设置(test-and-set)
int TestAndSet(int *old_ptr, int new)
{
int old = *old_ptr;//note that sete sets 'byte' not the word
*old_ptr = new; //store 'new' into old_ptr
return old;//return the old value
}
//使用testAndSet实现自旋锁
typedef struct _lock_t
{
int flag;
} lock_t;
void init(lock_t *lock)
{
lock->flag = 0;
}
void lock(lock_t *lock)
{
//线程1首先获取锁,TestAndSet设置flag=1,并返回flag的旧值,也就是0,退出循环
//线程2尝试获取锁, TestAndSet这时返回flag的旧值,也就是1,一直循环,直到线程1释放锁。
while(TestAndSet(&lock->flag, 1) == 1)
; //spin-wait
}
void unlock(lock_t *lock)
{
lock->flag = 0;
}
//c伪代码实现 比较并交换
int CompareAndSwap(int *ptr, int expected, int new)
{
int actual = *ptr;
if(actual == expected)
*ptr = new;
return actual;
}
//x86 c实现 比较并交换
char CompareAndSwap(int *ptr, int old, int new)
{
unsigned char ret;
//note that sete sets 'byte' not the word
__asm__ __volatile__ (
" lock\n"
" cmpxchgl %2, %1\n"
" sete %0\n"
: "=q" (ret),
"=m" (*ptr)
: "r" (new),
"m" (*ptr), "a" (old)
: "memory"
);
return ret;
}