From 7e6c37e67e6da62e02089fc3292569103b7e94b3 Mon Sep 17 00:00:00 2001
From: Frans Kaashoek <kaashoek@mit.edu>
Date: Tue, 10 Sep 2019 12:30:10 -0400
Subject: Support exit status for exit/wait One test case for returning a exit
 status Passes usertests, but haven't used it to simplify tests

---
 kernel/defs.h    |  4 ++--
 kernel/proc.c    | 12 ++++++++++--
 kernel/proc.h    |  1 +
 kernel/sysfile.c |  4 +++-
 kernel/sysproc.c | 10 ++++++++--
 kernel/trap.c    |  4 ++--
 6 files changed, 26 insertions(+), 9 deletions(-)

(limited to 'kernel')

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)
-- 
cgit v1.2.3