diff options
author | Frans Kaashoek <[email protected]> | 2019-09-10 12:30:10 -0400 |
---|---|---|
committer | Frans Kaashoek <[email protected]> | 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) |