在xv6中swtch.s返回到哪里?

问题描述 投票:0回答:1

问题很困惑 Swtch.ssched()

中被调用后返回到哪里
.globl swtch
swtch:
        sd ra, 0(a0)
        sd sp, 8(a0)
        sd s0, 16(a0)
        sd s1, 24(a0)
        sd s2, 32(a0)
        sd s3, 40(a0)
        sd s4, 48(a0)
        sd s5, 56(a0)
        sd s6, 64(a0)
        sd s7, 72(a0)
        sd s8, 80(a0)
        sd s9, 88(a0)
        sd s10, 96(a0)
        sd s11, 104(a0)

        ld ra, 0(a1)
        ld sp, 8(a1)
        ld s0, 16(a1)
        ld s1, 24(a1)
        ld s2, 32(a1)
        ld s3, 40(a1)
        ld s4, 48(a1)
        ld s5, 56(a1)
        ld s6, 64(a1)
        ld s7, 72(a1)
        ld s8, 80(a1)
        ld s9, 88(a1)
        ld s10, 96(a1)
        ld s11, 104(a1)
        
        ret

还有进入sched后进程的锁在哪里释放。 如果有人能在这方面帮助我,那就太好了

c assembly operating-system riscv xv6
1个回答
0
投票

原谅我糟糕的英语:)

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;
  swtch(&p->context, &mycpu()->context);
  mycpu()->intena = intena;
}

以上代码由MIT 6.s081提供。 sched 首先检查进程锁,因此每次进程调用 sched 函数时,它的锁都必须被锁定。然后,sched调用swtch函数。根据 risc v 调用约定,

&p->context
将存储在 a0 寄存器中,
&mycpu()->context
将存储在 a1 寄存器中。

毫无疑问,swtch 函数只是将一些寄存器(ra 存储返回地址,sp 指向当前堆栈和一些通用被调用者保存的寄存器)存储到当前进程的上下文中,加载新的上下文,然后跳转到ra寄存器中存储的地址,如果您熟悉sd、ld、ret指令的用法。

一个自然的问题是,哪个上下文存储在 mycpu()->context 上?让我们快速回顾一下调度程序功能。

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) {
        // Switch to chosen process.  It is the process's job
        // to release its lock and then reacquire it
        // before jumping back to us.
        p->state = RUNNING;
        c->proc = p;
        swtch(&c->context, &p->context);

        // Process is done running for now.
        // It should have changed its p->state before coming back.
        c->proc = 0;
      }
      release(&p->lock);
    }
    if(nproc <= 2) {   // only init and sh exist
      intr_on();
      asm volatile("wfi");
    }
  }
}

调度程序函数找到第一个RUNNABLE进程,然后调用swtch,将当前上下文存储到c->context。

因此,ret指令会让程序跳转到调度程序函数,这有助于释放锁并找到新的RUNNABLE进程。

© www.soinside.com 2019 - 2024. All rights reserved.