summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorFrans Kaashoek <[email protected]>2019-09-10 12:30:10 -0400
committerFrans Kaashoek <[email protected]>2019-09-10 12:30:10 -0400
commit7e6c37e67e6da62e02089fc3292569103b7e94b3 (patch)
tree8b3f2e762f1f0a32a4641d240d30b155af6ab34a /kernel
parent035cca95fe87c67ee1e33b9edfb2d87e24476fa8 (diff)
downloadxv6-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.h4
-rw-r--r--kernel/proc.c12
-rw-r--r--kernel/proc.h1
-rw-r--r--kernel/sysfile.c4
-rw-r--r--kernel/sysproc.c10
-rw-r--r--kernel/trap.c4
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)