xv6 chapter6: Locks
前面两小节的内容主要归纳起来就是锁保证并发结果的正确性,本质是通过对一些操作进行线性化,下面看一下代码中的两种锁spinlock与sleeplock
首先是spinlock,它主要包含一个locked属性,为0时表示该锁可用,非0则需要等待,逻辑上对它的acquire如下:
void
acquire(struct spinlock *lk) // does not work!
{
for(;;) {
if(lk->locked == 0) {
lk->locked = 1;
break;
}
}
}
但是如果两个CPU同时执行到if处则都会获得锁,导致两个CPU进入临界区,本质上需要把对locked的判断以及设置为1做成一个硬件级别的原子操作,这样总有一个来自CPU的访问是最先的并且将其置为1,以后同样的命令则会返回不同的结果,xv6使用了C包装好的函数调用__sync_lock_test_and_set函数,可以在kernel/spinlock.c中看到该函数的使用,另外对锁的release逻辑上只要将locked赋值为0即可,但是如果直接使用C语言的赋值,实际可能会对应多条原子指令,所以release中又实用了__sync__lock_release来进行原子性的操作。
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 2128099421@qq.com