MIT xv6 design from user prespective

Created on Oct 1, 2021

I will use mit 6.s801 lab1 “util” as an entry to the code behind. This article will not talk much about how to do lab1, but reveal some delicate design behind the syscall lab1 use.

ex1- sleep

#easy

This is the easiest lab in the lab1, so I will not talk about this exercise. Let’s go through the syscall sys_sleep in sysproc.c

uint64
sys_sleep(void)
{
  int n;
  uint ticks0;
  if(argint(0, &n) < 0)
    return -1;
  acquire(&tickslock);
  ticks0 = ticks;			// ticks is a golbal var maintained by trap
  while(ticks - ticks0 < n){
    if(myproc()->killed){
      release(&tickslock);
      return -1;
    }
    sleep(&ticks, &tickslock);
  }
  release(&tickslock);
  return 0;
}
  1. ticks is the global variable maintained in trap.c, when a time interrupt occurs(1 ms) , the devintr() in trap.c will add up ticks. ticks is protected by tickslock.

    clockintr()
    {
      acquire(&tickslock);
      ticks++;
      wakeup(&ticks);
      release(&tickslock);
    }
    
  2. sleep() in kernel, take 2 vars, the first one is the condition variable( aka chanvariable ), which is saved in the proc’s PCB, the next one is the lock that will be release before sleep.

    struct proc {
      ...
      void *chan;                  // If non-zero, sleeping on chan
      ...
      ...
    };
    
  3. everytime ticks++ in clockintr(), it will wakeup() all sleeping process holding ticks in its chan

    void
    wakeup(void *chan)
    {
      struct proc *p;
    
      for(p = proc; p < &proc[NPROC]; p++) {
        acquire(&p->lock);
        if(p->state == SLEEPING && p->chan == chan) {
          p->state = RUNNABLE;
        }
        release(&p->lock);
      }
    }
    

ex2- pingpong

#easy

another easy lab, in this section I will dive in the syscall sys_pipe() read(), write(), and try to answer why the pipe need be in one direction while using.

uint64
sys_pipe(void)
{
  uint64 fdarray; // user pointer to array of two integers
  struct file *rf, *wf;
  int fd0, fd1;
  struct proc *p = myproc();
  if(argaddr(0, &fdarray) < 0)
    return -1;
  if(pipealloc(&rf, &wf) < 0)
    return -1;
  fd0 = -1;
  if((fd0 = fdalloc(rf)) < 0 || (fd1 = fdalloc(wf)) < 0){
    if(fd0 >= 0)
      p->ofile[fd0] = 0;
    fileclose(rf);
    fileclose(wf);
    return -1;
  }
  if(copyout(p->pagetable, fdarray, (char*)&fd0, sizeof(fd0)) < 0 ||
    copyout(p->pagetable, fdarray+sizeof(fd0), (char *)&fd1, sizeof(fd1)) < 0){
    p->ofile[fd0] = 0;
    p->ofile[fd1] = 0;
    fileclose(rf);
    fileclose(wf);
    return -1;
  }
  return 0;
}
  1. File system

ex4/5 find and xargs

#mid I will talk about the directory layer and inode layer of the xv6 File system

ex3 primes

#hard Dive in fork(), and the basic design of “ex3 primes”.