diff options
| author | Frans Kaashoek <kaashoek@mit.edu> | 2017-01-31 20:21:14 -0500 | 
|---|---|---|
| committer | Frans Kaashoek <kaashoek@mit.edu> | 2017-01-31 20:21:14 -0500 | 
| commit | fbb4c0944422f860484142010bb9f366f3e87bf8 (patch) | |
| tree | 5e339842d43d09a4d23f1a2165391f00af30e308 | |
| parent | abf847a083888bbed4260ecacf849ea19f23e810 (diff) | |
| download | xv6-labs-fbb4c0944422f860484142010bb9f366f3e87bf8.tar.gz xv6-labs-fbb4c0944422f860484142010bb9f366f3e87bf8.tar.bz2 xv6-labs-fbb4c0944422f860484142010bb9f366f3e87bf8.zip | |
Read curproc from cpu structure, but be careful because after a schedule event
myproc() points to a different thread.
   myproc();
   sched();
   myproc();  // this proc maybe different than the one before sched
Thus, in a function that operates on one thread better to retrieve the
current process once at the start of the function.
| -rw-r--r-- | defs.h | 1 | ||||
| -rw-r--r-- | exec.c | 15 | ||||
| -rw-r--r-- | proc.c | 101 | ||||
| -rw-r--r-- | proc.h | 3 | ||||
| -rw-r--r-- | syscall.c | 23 | ||||
| -rw-r--r-- | sysfile.c | 12 | ||||
| -rw-r--r-- | vm.c | 4 | 
7 files changed, 97 insertions, 62 deletions
| @@ -108,6 +108,7 @@ void            exit(void);  int             fork(void);  int             growproc(int);  int             kill(int); +struct proc*    myproc();  void            pinit(void);  void            procdump(void);  void            scheduler(void) __attribute__((noreturn)); @@ -17,6 +17,7 @@ exec(char *path, char **argv)    struct inode *ip;    struct proghdr ph;    pde_t *pgdir, *oldpgdir; +  struct proc *curproc = myproc();    begin_op(); @@ -90,15 +91,15 @@ exec(char *path, char **argv)    for(last=s=path; *s; s++)      if(*s == '/')        last = s+1; -  safestrcpy(myproc()->name, last, sizeof(myproc()->name)); +  safestrcpy(curproc->name, last, sizeof(curproc->name));    // Commit to the user image. -  oldpgdir = myproc()->pgdir; -  myproc()->pgdir = pgdir; -  myproc()->sz = sz; -  myproc()->tf->eip = elf.entry;  // main -  myproc()->tf->esp = sp; -  switchuvm(myproc()); +  oldpgdir = curproc->pgdir; +  curproc->pgdir = pgdir; +  curproc->sz = sz; +  curproc->tf->eip = elf.entry;  // main +  curproc->tf->esp = sp; +  switchuvm(curproc);    freevm(oldpgdir);    return 0; @@ -26,14 +26,23 @@ pinit(void)    initlock(&ptable.lock, "ptable");  } +// XXX get rid off?  int  cpuid() {    return mycpu()-cpus;  } -void -setproc(struct proc* p) { -  mycpu()->proc = p; +// Disable interrupts so that we are not rescheduled +// while reading proc from the cpu structure +struct proc* +myproc(void) { +  struct cpu *c; +  struct proc *p; +  pushcli(); +  c = mycpu(); +  p = c->proc; +  popcli(); +  return p;  }  //PAGEBREAK: 32 @@ -130,17 +139,18 @@ int  growproc(int n)  {    uint sz; +  struct proc *curproc = myproc(); -  sz = myproc()->sz; +  sz = curproc->sz;    if(n > 0){ -    if((sz = allocuvm(myproc()->pgdir, sz, sz + n)) == 0) +    if((sz = allocuvm(curproc->pgdir, sz, sz + n)) == 0)        return -1;    } else if(n < 0){ -    if((sz = deallocuvm(myproc()->pgdir, sz, sz + n)) == 0) +    if((sz = deallocuvm(curproc->pgdir, sz, sz + n)) == 0)        return -1;    } -  myproc()->sz = sz; -  switchuvm(myproc()); +  curproc->sz = sz; +  switchuvm(curproc);    return 0;  } @@ -152,6 +162,7 @@ fork(void)  {    int i, pid;    struct proc *np; +  struct proc *curproc = myproc();    // Allocate process.    if((np = allocproc()) == 0){ @@ -159,25 +170,25 @@ fork(void)    }    // Copy process state from proc. -  if((np->pgdir = copyuvm(myproc()->pgdir, myproc()->sz)) == 0){ +  if((np->pgdir = copyuvm(curproc->pgdir, curproc->sz)) == 0){      kfree(np->kstack);      np->kstack = 0;      np->state = UNUSED;      return -1;    } -  np->sz = myproc()->sz; -  np->parent = myproc(); -  *np->tf = *myproc()->tf; +  np->sz = curproc->sz; +  np->parent = curproc; +  *np->tf = *curproc->tf;    // Clear %eax so that fork returns 0 in the child.    np->tf->eax = 0;    for(i = 0; i < NOFILE; i++) -    if(myproc()->ofile[i]) -      np->ofile[i] = filedup(myproc()->ofile[i]); -  np->cwd = idup(myproc()->cwd); +    if(curproc->ofile[i]) +      np->ofile[i] = filedup(curproc->ofile[i]); +  np->cwd = idup(curproc->cwd); -  safestrcpy(np->name, myproc()->name, sizeof(myproc()->name)); +  safestrcpy(np->name, curproc->name, sizeof(curproc->name));    pid = np->pid; @@ -196,33 +207,34 @@ fork(void)  void  exit(void)  { +  struct proc *curproc = myproc();    struct proc *p;    int fd; -  if(myproc() == initproc) +  if(curproc == initproc)      panic("init exiting");    // Close all open files.    for(fd = 0; fd < NOFILE; fd++){ -    if(myproc()->ofile[fd]){ -      fileclose(myproc()->ofile[fd]); -      myproc()->ofile[fd] = 0; +    if(curproc->ofile[fd]){ +      fileclose(curproc->ofile[fd]); +      curproc->ofile[fd] = 0;      }    }    begin_op(); -  iput(myproc()->cwd); +  iput(curproc->cwd);    end_op(); -  myproc()->cwd = 0; +  curproc->cwd = 0;    acquire(&ptable.lock);    // Parent might be sleeping in wait(). -  wakeup1(myproc()->parent); +  wakeup1(curproc->parent);    // Pass abandoned children to init.    for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){ -    if(p->parent == myproc()){ +    if(p->parent == curproc){        p->parent = initproc;        if(p->state == ZOMBIE)          wakeup1(initproc); @@ -230,7 +242,7 @@ exit(void)    }    // Jump into the scheduler, never to return. -  myproc()->state = ZOMBIE; +  curproc->state = ZOMBIE;    sched();    panic("zombie exit");  } @@ -242,13 +254,14 @@ wait(void)  {    struct proc *p;    int havekids, pid; - +  struct proc *curproc = myproc(); +      acquire(&ptable.lock);    for(;;){      // Scan through table looking for exited children.      havekids = 0;      for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){ -      if(p->parent != myproc()) +      if(p->parent != curproc)          continue;        havekids = 1;        if(p->state == ZOMBIE){ @@ -268,13 +281,13 @@ wait(void)      }      // No point waiting if we don't have any children. -    if(!havekids || myproc()->killed){ +    if(!havekids || curproc->killed){        release(&ptable.lock);        return -1;      }      // Wait for children to exit.  (See wakeup1 call in proc_exit.) -    sleep(myproc(), &ptable.lock);  //DOC: wait-sleep +    sleep(curproc, &ptable.lock);  //DOC: wait-sleep    }  } @@ -290,6 +303,7 @@ void  scheduler(void)  {    struct proc *p; +  struct cpu *c = mycpu();    for(;;){      // Enable interrupts on this processor. @@ -304,15 +318,18 @@ scheduler(void)        // Switch to chosen process.  It is the process's job        // to release ptable.lock and then reacquire it        // before jumping back to us. -      setproc(p); +      c->proc = p;        switchuvm(p);        p->state = RUNNING; -      swtch(&(mycpu()->scheduler), p->context); +      p->cpu = c; +      // cprintf("%d: switch to %d\n", c-cpus, p->pid); +      swtch(&(p->cpu->scheduler), p->context);        switchkvm();        // Process is done running for now.        // It should have changed its p->state before coming back. -      setproc(0); +      c->proc = 0; +      p->cpu = 0;      }      release(&ptable.lock); @@ -330,17 +347,20 @@ void  sched(void)  {    int intena; +  struct proc *p = myproc();    if(!holding(&ptable.lock))      panic("sched ptable.lock");    if(mycpu()->ncli != 1)      panic("sched locks"); -  if(myproc()->state == RUNNING) +  if(p->state == RUNNING)      panic("sched running");    if(readeflags()&FL_IF)      panic("sched interruptible");    intena = mycpu()->intena; -  swtch(&myproc()->context, mycpu()->scheduler); +  // cprintf("%d: before swtch %d %x\n", p->cpu-cpus, p->pid, * (int *) 0x1d); +  swtch(&p->context, p->cpu->scheduler); +  // cprintf("%d/%d: after swtch %d %x\n", cpuid(), p->cpu-cpus, p->pid, * (int *) 0x1d);    mycpu()->intena = intena;  } @@ -380,7 +400,9 @@ forkret(void)  void  sleep(void *chan, struct spinlock *lk)  { -  if(myproc() == 0) +  struct proc *p = myproc(); +   +  if(p == 0)      panic("sleep");    if(lk == 0) @@ -397,12 +419,15 @@ sleep(void *chan, struct spinlock *lk)      release(lk);    }    // Go to sleep. -  myproc()->chan = chan; -  myproc()->state = SLEEPING; +  p->chan = chan; +  p->state = SLEEPING; + +  // cprintf("sleep %d\n", p->pid); +      sched();    // Tidy up. -  myproc()->chan = 0; +  p->chan = 0;    // Reacquire original lock.    if(lk != &ptable.lock){  //DOC: sleeplock2 @@ -30,12 +30,14 @@ mycpu(void) {    return cpu;  } +#if 0  static inline struct proc*  myproc(void) {    struct proc *proc;    asm("movl %%gs:4, %0" : "=r"(proc));    return proc;  } +#endif  //PAGEBREAK: 17 @@ -74,6 +76,7 @@ struct proc {    struct file *ofile[NOFILE];  // Open files    struct inode *cwd;           // Current directory    char name[16];               // Process name (debugging) +  struct cpu *cpu;             // If running, which cpu.  };  // Process memory is laid out contiguously, low addresses first: @@ -17,7 +17,9 @@  int  fetchint(uint addr, int *ip)  { -  if(addr >= myproc()->sz || addr+4 > myproc()->sz) +  struct proc *curproc = myproc(); + +  if(addr >= curproc->sz || addr+4 > curproc->sz)      return -1;    *ip = *(int*)(addr);    return 0; @@ -30,11 +32,12 @@ int  fetchstr(uint addr, char **pp)  {    char *s, *ep; +  struct proc *curproc = myproc(); -  if(addr >= myproc()->sz) +  if(addr >= curproc->sz)      return -1;    *pp = (char*)addr; -  ep = (char*)myproc()->sz; +  ep = (char*)curproc->sz;    for(s = *pp; s < ep; s++){      if(*s == 0)        return s - *pp; @@ -56,10 +59,11 @@ int  argptr(int n, char **pp, int size)  {    int i; - +  struct proc *curproc = myproc(); +     if(argint(n, &i) < 0)      return -1; -  if(size < 0 || (uint)i >= myproc()->sz || (uint)i+size > myproc()->sz) +  if(size < 0 || (uint)i >= curproc->sz || (uint)i+size > curproc->sz)      return -1;    *pp = (char*)i;    return 0; @@ -128,13 +132,14 @@ void  syscall(void)  {    int num; +  struct proc *curproc = myproc(); -  num = myproc()->tf->eax; +  num = curproc->tf->eax;    if(num > 0 && num < NELEM(syscalls) && syscalls[num]) { -    myproc()->tf->eax = syscalls[num](); +    curproc->tf->eax = syscalls[num]();    } else {      cprintf("%d %s: unknown sys call %d\n", -            myproc()->pid, myproc()->name, num); -    myproc()->tf->eax = -1; +            curproc->pid, curproc->name, num); +    curproc->tf->eax = -1;    }  } @@ -41,10 +41,11 @@ static int  fdalloc(struct file *f)  {    int fd; +  struct proc *curproc = myproc();    for(fd = 0; fd < NOFILE; fd++){ -    if(myproc()->ofile[fd] == 0){ -      myproc()->ofile[fd] = f; +    if(curproc->ofile[fd] == 0){ +      curproc->ofile[fd] = f;        return fd;      }    } @@ -373,7 +374,8 @@ sys_chdir(void)  {    char *path;    struct inode *ip; - +  struct proc *curproc = myproc(); +      begin_op();    if(argstr(0, &path) < 0 || (ip = namei(path)) == 0){      end_op(); @@ -386,9 +388,9 @@ sys_chdir(void)      return -1;    }    iunlock(ip); -  iput(myproc()->cwd); +  iput(curproc->cwd);    end_op(); -  myproc()->cwd = ip; +  curproc->cwd = ip;    return 0;  } @@ -27,13 +27,11 @@ seginit(void)    c->gdt[SEG_UCODE] = SEG(STA_X|STA_R, 0, 0xffffffff, DPL_USER);    c->gdt[SEG_UDATA] = SEG(STA_W, 0, 0xffffffff, DPL_USER);    c->cpu = c; +  c->proc = 0;    // Map cpu and proc -- these are private per cpu.    c->gdt[SEG_KCPU] = SEG(STA_W, &c->cpu, 4, 0);    lgdt(c->gdt, sizeof(c->gdt));    loadgs(SEG_KCPU << 3); -  // Initialize cpu-local storage. -  // setcpu(c); -  setproc(0);  }  // Return the address of the PTE in page table pgdir | 
