pintos (4) --Mesa vs. Hoare style

在阅读pintos/src/threads/synch.c的时候,发现了一个令人疑惑的地方:
/* Down or "P" operation on a semaphore. Waits for SEMA's value
to become positive and then atomically decrements it.
This function may sleep, so it must not be called within an
interrupt handler. This function may be called with
interrupts disabled, but if it sleeps then the next scheduled
thread will probably turn interrupts back on. */
void
sema_down (struct semaphore *sema)
{
    enum intr_level old_level;

    ASSERT (sema != NULL);
    ASSERT (!intr_context ());

    old_level = intr_disable ();
    while (sema->value == 0)
    {
        list_push_back (&sema->waiters, &thread_current ()->elem);
        thread_block ();
    }
    sema->value--;
    intr_set_level (old_level);
}
这个函数是信号量的P操作,完成的功能就是
  1. 关中断
  2. 判断信号量是否为0
    • 如果为0,当前进程加入该sema等待队列
    • 不为0,sema–,继续执行
  3. 还原中断

第16行使用了while而不是if,为什么要在这里循环呢?
sema为0陷入阻塞之后,一定是被V操作唤醒的,既然是V操作,那么sema一定不为0,while的意义在哪里呢?


先来看一下V操作:

/* Up or "V" operation on a semaphore.  Increments SEMA's value
   and wakes up one thread of those waiting for SEMA, if any.
   This function may be called from an interrupt handler. */
void
sema_up (struct semaphore *sema) 
{
  enum intr_level old_level;

  ASSERT (sema != NULL);

  old_level = intr_disable ();
  if (!list_empty (&sema->waiters)) 
    thread_unblock (list_entry (list_pop_front (&sema->waiters),
                                struct thread, elem));
  sema->value++;
  intr_set_level (old_level);
}
V操作做了如下的事情
  1. 关中断
  2. 如果waiters队列有进程,执行thread_unblock()
  3. sema++
  4. 还原中断

好像没什么不对的

再来看一下thread_unblock()的实现:
/* Transitions a blocked thread T to the ready-to-run state.
   This is an error if T is not blocked.  (Use thread_yield() to
   make the running thread ready.)
   This function does not preempt the running thread.  This can
   be important: if the caller had disabled interrupts itself,
   it may expect that it can atomically unblock a thread and
   update other data. */
void
thread_unblock (struct thread *t) 
{
  enum intr_level old_level;

  ASSERT (is_thread (t));

  old_level = intr_disable ();
  ASSERT (t->status == THREAD_BLOCKED);
  list_push_back (&ready_list, &t->elem);
  t->status = THREAD_READY;
  intr_set_level (old_level);
}
thread_unblock()做了如下的事情
  1. 关中断
  2. 将进程添加到ready_list,设置状态为READY
  3. 还原中断

竟然没有进行调度!


OK进入正题:

Mesa vs. Hoare style
  • Hoare style:V操作后立即进行调度。
  • Mesa style:V操作后只将进程unblock,然后继续运行等待系统进行调度。

显然PintOs采用的是Mesa style,所以,被unblock的进程在被调度的时候,sema并不一定可用,比如其他进程又进行了P操作,所以必须再次检查sema,如果不可用则继续block,这就是使用while而不是if的理由。

为什么不立即调度呢?这就是他的优点,不立即调度而是等待系统调度,就减少了调度次数,而每次切换上下文都是繁重的工作,进而降低了系统开销。


相关链接:

http://blog.csdn.net/xiaoguobaf/article/details/52174285
http://blog.chinaunix.net/uid-20545494-id-1929545.html
https://github.com/windr0id/pintos/issues/1

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值