diff options
| author | Frans Kaashoek <kaashoek@mit.edu> | 2019-07-06 16:38:41 -0400 | 
|---|---|---|
| committer | Frans Kaashoek <kaashoek@mit.edu> | 2019-07-06 16:38:41 -0400 | 
| commit | dabbc348bc4edab522901d8473acaabe276cdc45 (patch) | |
| tree | a46c2e0a275ad9ca48898b23026f131fac85c086 /kernel | |
| parent | be88befed702f7bcbf65212a9dcf9456a7bd2ae1 (diff) | |
| download | xv6-labs-dabbc348bc4edab522901d8473acaabe276cdc45.tar.gz xv6-labs-dabbc348bc4edab522901d8473acaabe276cdc45.tar.bz2 xv6-labs-dabbc348bc4edab522901d8473acaabe276cdc45.zip | |
Maybe fix two races identified by rtm (thx!):
- during exit(), hold p's parent lock and p's lock across all changes
to p and its parent (e.g., reparenting and wakeup1).  the lock
ordering between concurrent exits of children, parent, and great
parent might work out because processes form a tree.
- in wakeup1() test and set p->state atomically by asking caller to
have p locked.
a correctness proof would be desirable.
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/proc.c | 32 | 
1 files changed, 20 insertions, 12 deletions
| diff --git a/kernel/proc.c b/kernel/proc.c index 9c64c4a..2266ca6 100644 --- a/kernel/proc.c +++ b/kernel/proc.c @@ -288,22 +288,28 @@ fork(void)    return pid;  } -// Pass p's abandoned children to init. -void reparent(struct proc *p) { +// Pass p's abandoned children to init. p and p's parent +// are locked. +void reparent(struct proc *p, struct proc *parent) {    struct proc *pp;    for(pp = ptable.proc; pp < &ptable.proc[NPROC]; pp++){ -    acquire(&pp->lock); -    if(pp->parent == p){ -      pp->parent = initproc; -      if(pp->state == ZOMBIE) { +    if (pp != p && pp != parent) { +      acquire(&pp->lock); +      if(pp->parent == p){ +        pp->parent = initproc; +        if(pp->state == ZOMBIE) { +          acquire(&initproc->lock);            wakeup1(initproc); +          release(&initproc->lock); +        }        } +      release(&pp->lock);      } -    release(&pp->lock);    }  } +  // Exit the current process.  Does not return.  // An exited process remains in the zombie state  // until its parent calls wait(). @@ -331,19 +337,20 @@ exit(void)    iput(cwd);    end_op(); -  reparent(p); -      acquire(&p->parent->lock);    acquire(&p->lock); + +  reparent(p, p->parent); +    p->cwd = 0;    p->state = ZOMBIE; -  release(&p->parent->lock); -    // Parent might be sleeping in wait().    wakeup1(p->parent); +  release(&p->parent->lock); +    // Jump into the scheduler, never to return.    sched();    panic("zombie exit"); @@ -529,7 +536,8 @@ sleep(void *chan, struct spinlock *lk)  }  //PAGEBREAK! -// Wake up locked parent, used by exit() +// Wake up p, used by exit() +// Caller should lock p.  static void  wakeup1(struct proc *p)  { | 
