diff options
| author | Frans Kaashoek <kaashoek@mit.edu> | 2019-09-10 12:30:10 -0400 | 
|---|---|---|
| committer | Frans Kaashoek <kaashoek@mit.edu> | 2019-09-10 12:30:10 -0400 | 
| commit | 7e6c37e67e6da62e02089fc3292569103b7e94b3 (patch) | |
| tree | 8b3f2e762f1f0a32a4641d240d30b155af6ab34a /kernel | |
| parent | 035cca95fe87c67ee1e33b9edfb2d87e24476fa8 (diff) | |
| download | xv6-labs-7e6c37e67e6da62e02089fc3292569103b7e94b3.tar.gz xv6-labs-7e6c37e67e6da62e02089fc3292569103b7e94b3.tar.bz2 xv6-labs-7e6c37e67e6da62e02089fc3292569103b7e94b3.zip | |
Support exit status for exit/wait
One test case for returning a exit status
Passes usertests, but haven't used it to simplify tests
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/defs.h | 4 | ||||
| -rw-r--r-- | kernel/proc.c | 12 | ||||
| -rw-r--r-- | kernel/proc.h | 1 | ||||
| -rw-r--r-- | kernel/sysfile.c | 4 | ||||
| -rw-r--r-- | kernel/sysproc.c | 10 | ||||
| -rw-r--r-- | kernel/trap.c | 4 | 
6 files changed, 26 insertions, 9 deletions
| diff --git a/kernel/defs.h b/kernel/defs.h index 23dcd41..f893d28 100644 --- a/kernel/defs.h +++ b/kernel/defs.h @@ -82,7 +82,7 @@ void            printfinit(void);  // proc.c  int             cpuid(void); -void            exit(void); +void            exit(int);  int             fork(void);  int             growproc(int);  pagetable_t     proc_pagetable(struct proc *); @@ -97,7 +97,7 @@ void            sched(void);  void            setproc(struct proc*);  void            sleep(void*, struct spinlock*);  void            userinit(void); -int             wait(void); +int             wait(uint64);  void            wakeup(void*);  void            yield(void);  int             either_copyout(int user_dst, uint64 dst, void *src, uint64 len); diff --git a/kernel/proc.c b/kernel/proc.c index 428fdb0..786e5c3 100644 --- a/kernel/proc.c +++ b/kernel/proc.c @@ -141,6 +141,7 @@ freeproc(struct proc *p)    p->name[0] = 0;    p->chan = 0;    p->killed = 0; +  p->xstate = 0;    p->state = UNUSED;  } @@ -319,7 +320,7 @@ reparent(struct proc *p, struct proc *parent) {  // An exited process remains in the zombie state  // until its parent calls wait().  void -exit(void) +exit(int status)  {    struct proc *p = myproc(); @@ -350,6 +351,7 @@ exit(void)    // Parent might be sleeping in wait().    wakeup1(p->parent); +  p->xstate = status;    p->state = ZOMBIE;    release(&p->parent->lock); @@ -362,7 +364,7 @@ exit(void)  // Wait for a child process to exit and return its pid.  // Return -1 if this process has no children.  int -wait(void) +wait(uint64 addr)  {    struct proc *np;    int havekids, pid; @@ -387,6 +389,12 @@ wait(void)          if(np->state == ZOMBIE){            // Found one.            pid = np->pid; +          if(addr != 0 && copyout(p->pagetable, addr, (char *)&np->xstate, +                                  sizeof(np->xstate)) < 0) { +            release(&np->lock); +            release(&p->lock); +            return -1; +          }            freeproc(np);            release(&np->lock);            release(&p->lock); diff --git a/kernel/proc.h b/kernel/proc.h index 655d79f..538b48a 100644 --- a/kernel/proc.h +++ b/kernel/proc.h @@ -91,6 +91,7 @@ struct proc {    struct proc *parent;         // Parent process    void *chan;                  // If non-zero, sleeping on chan    int killed;                  // If non-zero, have been killed +  int xstate;                  // Exit status to be returned to parent's wait    int pid;                     // Process ID    // these are private to the process, so p->lock need not be held. diff --git a/kernel/sysfile.c b/kernel/sysfile.c index 23a9540..5b09d93 100644 --- a/kernel/sysfile.c +++ b/kernel/sysfile.c @@ -246,6 +246,7 @@ create(char *path, short type, short major, short minor)    if((dp = nameiparent(path, name)) == 0)      return 0; +    ilock(dp);    if((ip = dirlookup(dp, name, 0)) != 0){ @@ -289,8 +290,9 @@ sys_open(void)    int fd, omode;    struct file *f;    struct inode *ip; +  int n; -  if(argstr(0, path, MAXPATH) < 0 || argint(1, &omode) < 0) +  if((n = argstr(0, path, MAXPATH)) < 0 || argint(1, &omode) < 0)      return -1;    begin_op(); diff --git a/kernel/sysproc.c b/kernel/sysproc.c index face81a..e8bcda9 100644 --- a/kernel/sysproc.c +++ b/kernel/sysproc.c @@ -10,7 +10,10 @@  uint64  sys_exit(void)  { -  exit(); +  int n; +  if(argint(0, &n) < 0) +    return -1; +  exit(n);    return 0;  // not reached  } @@ -29,7 +32,10 @@ sys_fork(void)  uint64  sys_wait(void)  { -  return wait(); +  uint64 p; +  if(argaddr(0, &p) < 0) +    return -1; +  return wait(p);  }  uint64 diff --git a/kernel/trap.c b/kernel/trap.c index ec57bed..e96a542 100644 --- a/kernel/trap.c +++ b/kernel/trap.c @@ -54,7 +54,7 @@ usertrap(void)      // system call      if(p->killed) -      exit(); +      exit(-1);      // sepc points to the ecall instruction,      // but we want to return to the next instruction. @@ -74,7 +74,7 @@ usertrap(void)    }    if(p->killed) -    exit(); +    exit(-1);    // give up the CPU if this is a timer interrupt.    if(which_dev == 2) | 
