Support exit status for exit/wait
One test case for returning a exit status Passes usertests, but haven't used it to simplify tests
This commit is contained in:
parent
035cca95fe
commit
7e6c37e67e
22 changed files with 319 additions and 297 deletions
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue