JOS大内核锁

来源:互联网 发布:linux程序设计 微盘 编辑:程序博客网 时间:2024/03/29 19:41

JOSlab4里面,采用了SMT的操作系统,所以可能存在两个CPU同时进入内核态,虽然CPU之间的内核栈,但是多核同步可能还是会出现问题,所以JOS采用大内核锁来锁住整个内核,使得每次只有一个CPU会进入内核,另外的CPU如果申请进入内核态,是进不去的。
    首先,看一下内核锁的实现方法:
  

struct spinlock {    unsigned locked;       };/***************************************/spin_lock(struct spinlock *lk){    while (xchg(&lk->locked, 1) != 0)        asm volatile ("pause");}/************************************************/voidspin_unlock(struct spinlock *lk){    xchg(&lk->locked, 0);}

  总共只有三个不同的内容,一个变量,还有就是上锁和解锁。
  首先看xchg操作,xchg操作是一个原子操作,它的作用就是交换两个参数,并且返回第一个参数原来的值。
  现在看下上锁过程,假设CPU0进入内核,首先要进行上锁操作,
  xchg(&lk->locked, 1)
  
  CPU0会执行上面的原子操作,并且返回lk->locked的原来的值,如果原来的值是0,则进入内核,并且内核也被上锁,即lk->locked被赋值为1,当其他CPU要进入的时候,lk->locked一直是1,此时,会执行:
   asm volatile (“pause”);
   pause指令:
  

Improves the performance of spin-wait loops. When executing a “spin-wait loop,” a Pentium 4 or Intel Xeon processor suffers a severe performance penalty when exiting the loop because it detects a possible memory order violation. The PAUSE instruction provides a hint to the processor that the code sequence is a spin-wait loop. The processor uses this hint to avoid the memory order violation in most situations, which greatly improves processor performance. For this reason, it is recommended that a PAUSE instruction be placed in all spin-wait loops.
An additional fucntion of the PAUSE instruction is to reduce the power consumed by a Pentium 4 processor while executing a spin loop.

所以,用pause可以让CPU知道接下来的指令是用来自旋等待,就不用做memory reorder了,cache也不用废除了(cache是很宝贵的资源,进程切换的一个重要资源房费就是会导致cache失效,从而导致缓存不命中的问题)。而且附加的功能——减少能耗。
所以用pause就是提醒CPU接下来的指令是自旋等待,什么都不用干,然后CPU一直查询lk->locked的值,直到它的值变为了0,。
2.解锁
解锁就比较简单了,直接把lk->locked变成0就可以了。

  所以,总的来说,JOS用了一个简单的自旋锁来当成一个大的内核锁,这里的内核锁实现是用xchg原子操作了实现的。总体来说,这个方法的优点就是实现简单,而且绝对不会出错。缺点也很明显,效率太低了,估计CPU会有很多时间浪费在等待上面。
  所以后来的内核的方法,主要采用的是在关键资源上面加锁,而不是在整个内核加锁,这样效率就可以大大的提高,但是相对的实现的难度也加大了。

0 0
原创粉丝点击