MIT 6.s081 XV6线程调度

  1. 用户线程接受到时钟中断,强迫CPU从用户空间进入内核,同时trampoline保存当前寄存器代码到trapframe
  2. usertrap处理中断,调用yield函数
  3. yield先给当前t1线程加锁,将其状态设为RUNNABLE,后转入sched函数
  4. sched先进行警戒判断,再调用swtch,将当前reg保存下来,加载cpu调度线程的reg上去
  5. 进入到了scheduler函数,此时进入的位置是之前cpu中的context保存的ra的位置,即在scheduler调用swtch的下面一行代码。此时先把t1的锁解开,再进行遍历线程,找到下一个可调用的线程,调用swtch调用t2线程,并返回到内核线程所对应进程的系统调用或者中断处理程序中。
  6. 当内核程序执行完成之后,trapframe 中的用户寄存器会被恢复,完成线程调度

看看代码:

// Give up the CPU for one scheduling round.
void
yield(void)
{
  struct proc *p = myproc();
  acquire(&p->lock);// 锁t1
  p->state = RUNNABLE;
  sched();//调度开始
  release(&p->lock);// 释放的t2的锁
}
void
sched(void)
{
  int intena;
  struct proc *p = myproc();

  if(!holding(&p->lock))
    panic("sched p->lock");
  if(mycpu()->noff != 1)
    panic("sched locks");
  if(p->state == RUNNING)
    panic("sched running");
  if(intr_get())
    panic("sched interruptible");

  intena = mycpu()->intena;
  // 转到cpu调度线程,即scheduler中swtch中的下一行
  swtch(&p->context, &mycpu()->context);
  mycpu()->intena = intena;
}

注意此时的cpu的context中的ra,是保存的scheduler上一次调用swtch时保存下来的ra,即接下来scheduler执行的代码应该是scheduler函数中swtch调用位置的下一行

void
scheduler(void)
{
  struct proc *p;
  struct cpu *c = mycpu();
  
  c->proc = 0;
  for(;;){
    // Avoid deadlock by ensuring that devices can interrupt.
    intr_on();
    
    int nproc = 0;
    for(p = proc; p < &proc[NPROC]; p++) {
      acquire(&p->lock);
      if(p->state != UNUSED) {
        nproc++;
      }
      if(p->state == RUNNABLE) {
        
        p->state = RUNNING;
        c->proc = p;
        swtch(&c->context, &p->context);// 再切换t2

 
        
        // 注意,这才是进入scheduler时第一步运行的位置
        //sched经过swtch转到这一步
        c->proc = 0;
      }
      release(&p->lock); // 先释放t1的锁
    }
    if(nproc <= 2) {   // only init and sh exist
      intr_on();
      asm volatile("wfi");
    }
  }
}

我们可以看到在加载了cpu的context之后,第一步执行的时c->proc=0,接着执行release(&p->lock),此时的p还是t1,接下来再进行轮询线程,调用t2

来看看整个调用流程:

图来自知乎老哥,画的太清楚了!

 还少一个在最后的yield中释放t2的锁

总结下来,对线程调度就清晰很多了!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值