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:
Frans Kaashoek 2019-09-10 12:30:10 -04:00
parent 035cca95fe
commit 7e6c37e67e
22 changed files with 319 additions and 297 deletions

View file

@ -82,7 +82,7 @@ void printfinit(void);
// proc.c // proc.c
int cpuid(void); int cpuid(void);
void exit(void); void exit(int);
int fork(void); int fork(void);
int growproc(int); int growproc(int);
pagetable_t proc_pagetable(struct proc *); pagetable_t proc_pagetable(struct proc *);
@ -97,7 +97,7 @@ void sched(void);
void setproc(struct proc*); void setproc(struct proc*);
void sleep(void*, struct spinlock*); void sleep(void*, struct spinlock*);
void userinit(void); void userinit(void);
int wait(void); int wait(uint64);
void wakeup(void*); void wakeup(void*);
void yield(void); void yield(void);
int either_copyout(int user_dst, uint64 dst, void *src, uint64 len); int either_copyout(int user_dst, uint64 dst, void *src, uint64 len);

View file

@ -141,6 +141,7 @@ freeproc(struct proc *p)
p->name[0] = 0; p->name[0] = 0;
p->chan = 0; p->chan = 0;
p->killed = 0; p->killed = 0;
p->xstate = 0;
p->state = UNUSED; p->state = UNUSED;
} }
@ -319,7 +320,7 @@ reparent(struct proc *p, struct proc *parent) {
// An exited process remains in the zombie state // An exited process remains in the zombie state
// until its parent calls wait(). // until its parent calls wait().
void void
exit(void) exit(int status)
{ {
struct proc *p = myproc(); struct proc *p = myproc();
@ -350,6 +351,7 @@ exit(void)
// Parent might be sleeping in wait(). // Parent might be sleeping in wait().
wakeup1(p->parent); wakeup1(p->parent);
p->xstate = status;
p->state = ZOMBIE; p->state = ZOMBIE;
release(&p->parent->lock); release(&p->parent->lock);
@ -362,7 +364,7 @@ exit(void)
// Wait for a child process to exit and return its pid. // Wait for a child process to exit and return its pid.
// Return -1 if this process has no children. // Return -1 if this process has no children.
int int
wait(void) wait(uint64 addr)
{ {
struct proc *np; struct proc *np;
int havekids, pid; int havekids, pid;
@ -387,6 +389,12 @@ wait(void)
if(np->state == ZOMBIE){ if(np->state == ZOMBIE){
// Found one. // Found one.
pid = np->pid; 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); freeproc(np);
release(&np->lock); release(&np->lock);
release(&p->lock); release(&p->lock);

View file

@ -91,6 +91,7 @@ struct proc {
struct proc *parent; // Parent process struct proc *parent; // Parent process
void *chan; // If non-zero, sleeping on chan void *chan; // If non-zero, sleeping on chan
int killed; // If non-zero, have been killed int killed; // If non-zero, have been killed
int xstate; // Exit status to be returned to parent's wait
int pid; // Process ID int pid; // Process ID
// these are private to the process, so p->lock need not be held. // these are private to the process, so p->lock need not be held.

View file

@ -246,6 +246,7 @@ create(char *path, short type, short major, short minor)
if((dp = nameiparent(path, name)) == 0) if((dp = nameiparent(path, name)) == 0)
return 0; return 0;
ilock(dp); ilock(dp);
if((ip = dirlookup(dp, name, 0)) != 0){ if((ip = dirlookup(dp, name, 0)) != 0){
@ -289,8 +290,9 @@ sys_open(void)
int fd, omode; int fd, omode;
struct file *f; struct file *f;
struct inode *ip; 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; return -1;
begin_op(); begin_op();

View file

@ -10,7 +10,10 @@
uint64 uint64
sys_exit(void) sys_exit(void)
{ {
exit(); int n;
if(argint(0, &n) < 0)
return -1;
exit(n);
return 0; // not reached return 0; // not reached
} }
@ -29,7 +32,10 @@ sys_fork(void)
uint64 uint64
sys_wait(void) sys_wait(void)
{ {
return wait(); uint64 p;
if(argaddr(0, &p) < 0)
return -1;
return wait(p);
} }
uint64 uint64

View file

@ -54,7 +54,7 @@ usertrap(void)
// system call // system call
if(p->killed) if(p->killed)
exit(); exit(-1);
// sepc points to the ecall instruction, // sepc points to the ecall instruction,
// but we want to return to the next instruction. // but we want to return to the next instruction.
@ -74,7 +74,7 @@ usertrap(void)
} }
if(p->killed) if(p->killed)
exit(); exit(-1);
// give up the CPU if this is a timer interrupt. // give up the CPU if this is a timer interrupt.
if(which_dev == 2) if(which_dev == 2)

View file

@ -12,12 +12,12 @@ cat(int fd)
while((n = read(fd, buf, sizeof(buf))) > 0) { while((n = read(fd, buf, sizeof(buf))) > 0) {
if (write(1, buf, n) != n) { if (write(1, buf, n) != n) {
printf("cat: write error\n"); printf("cat: write error\n");
exit(); exit(-1);
} }
} }
if(n < 0){ if(n < 0){
printf("cat: read error\n"); printf("cat: read error\n");
exit(); exit(-1);
} }
} }
@ -28,16 +28,16 @@ main(int argc, char *argv[])
if(argc <= 1){ if(argc <= 1){
cat(0); cat(0);
exit(); exit(-1);
} }
for(i = 1; i < argc; i++){ for(i = 1; i < argc; i++){
if((fd = open(argv[i], 0)) < 0){ if((fd = open(argv[i], 0)) < 0){
printf("cat: cannot open %s\n", argv[i]); printf("cat: cannot open %s\n", argv[i]);
exit(); exit(-1);
} }
cat(fd); cat(fd);
close(fd); close(fd);
} }
exit(); exit(0);
} }

View file

@ -15,5 +15,5 @@ main(int argc, char *argv[])
write(1, "\n", 1); write(1, "\n", 1);
} }
} }
exit(); exit(0);
} }

View file

@ -25,24 +25,24 @@ forktest(void)
if(pid < 0) if(pid < 0)
break; break;
if(pid == 0) if(pid == 0)
exit(); exit(0);
} }
if(n == N){ if(n == N){
print("fork claimed to work N times!\n"); print("fork claimed to work N times!\n");
exit(); exit(-1);
} }
for(; n > 0; n--){ for(; n > 0; n--){
if(wait() < 0){ if(wait(0) < 0){
print("wait stopped early\n"); print("wait stopped early\n");
exit(); exit(-1);
} }
} }
if(wait() != -1){ if(wait(0) != -1){
print("wait got too many\n"); print("wait got too many\n");
exit(); exit(-1);
} }
print("fork test OK\n"); print("fork test OK\n");
@ -52,5 +52,5 @@ int
main(void) main(void)
{ {
forktest(); forktest();
exit(); exit(0);
} }

View file

@ -41,24 +41,24 @@ main(int argc, char *argv[])
if(argc <= 1){ if(argc <= 1){
fprintf(2, "usage: grep pattern [file ...]\n"); fprintf(2, "usage: grep pattern [file ...]\n");
exit(); exit(-1);
} }
pattern = argv[1]; pattern = argv[1];
if(argc <= 2){ if(argc <= 2){
grep(pattern, 0); grep(pattern, 0);
exit(); exit(0);
} }
for(i = 2; i < argc; i++){ for(i = 2; i < argc; i++){
if((fd = open(argv[i], 0)) < 0){ if((fd = open(argv[i], 0)) < 0){
printf("grep: cannot open %s\n", argv[i]); printf("grep: cannot open %s\n", argv[i]);
exit(); exit(-1);
} }
grep(pattern, fd); grep(pattern, fd);
close(fd); close(fd);
} }
exit(); exit(0);
} }
// Regexp matcher from Kernighan & Pike, // Regexp matcher from Kernighan & Pike,

View file

@ -24,14 +24,14 @@ main(void)
pid = fork(); pid = fork();
if(pid < 0){ if(pid < 0){
printf("init: fork failed\n"); printf("init: fork failed\n");
exit(); exit(-1);
} }
if(pid == 0){ if(pid == 0){
exec("sh", argv); exec("sh", argv);
printf("init: exec sh failed\n"); printf("init: exec sh failed\n");
exit(); exit(-1);
} }
while((wpid=wait()) >= 0 && wpid != pid){ while((wpid=wait(0)) >= 0 && wpid != pid){
//printf("zombie!\n"); //printf("zombie!\n");
} }
} }

View file

@ -9,9 +9,9 @@ main(int argc, char **argv)
if(argc < 2){ if(argc < 2){
fprintf(2, "usage: kill pid...\n"); fprintf(2, "usage: kill pid...\n");
exit(); exit(-1);
} }
for(i=1; i<argc; i++) for(i=1; i<argc; i++)
kill(atoi(argv[i])); kill(atoi(argv[i]));
exit(); exit(0);
} }

View file

@ -7,9 +7,9 @@ main(int argc, char *argv[])
{ {
if(argc != 3){ if(argc != 3){
fprintf(2, "Usage: ln old new\n"); fprintf(2, "Usage: ln old new\n");
exit(); exit(-1);
} }
if(link(argv[1], argv[2]) < 0) if(link(argv[1], argv[2]) < 0)
fprintf(2, "link %s %s: failed\n", argv[1], argv[2]); fprintf(2, "link %s %s: failed\n", argv[1], argv[2]);
exit(); exit(0);
} }

View file

@ -77,9 +77,9 @@ main(int argc, char *argv[])
if(argc < 2){ if(argc < 2){
ls("."); ls(".");
exit(); exit(0);
} }
for(i=1; i<argc; i++) for(i=1; i<argc; i++)
ls(argv[i]); ls(argv[i]);
exit(); exit(0);
} }

View file

@ -9,7 +9,7 @@ main(int argc, char *argv[])
if(argc < 2){ if(argc < 2){
fprintf(2, "Usage: mkdir files...\n"); fprintf(2, "Usage: mkdir files...\n");
exit(); exit(-1);
} }
for(i = 1; i < argc; i++){ for(i = 1; i < argc; i++){
@ -19,5 +19,5 @@ main(int argc, char *argv[])
} }
} }
exit(); exit(0);
} }

View file

@ -9,7 +9,7 @@ main(int argc, char *argv[])
if(argc < 2){ if(argc < 2){
fprintf(2, "Usage: rm files...\n"); fprintf(2, "Usage: rm files...\n");
exit(); exit(-1);
} }
for(i = 1; i < argc; i++){ for(i = 1; i < argc; i++){
@ -19,5 +19,5 @@ main(int argc, char *argv[])
} }
} }
exit(); exit(0);
} }

View file

@ -65,7 +65,7 @@ runcmd(struct cmd *cmd)
struct redircmd *rcmd; struct redircmd *rcmd;
if(cmd == 0) if(cmd == 0)
exit(); exit(-1);
switch(cmd->type){ switch(cmd->type){
default: default:
@ -74,7 +74,7 @@ runcmd(struct cmd *cmd)
case EXEC: case EXEC:
ecmd = (struct execcmd*)cmd; ecmd = (struct execcmd*)cmd;
if(ecmd->argv[0] == 0) if(ecmd->argv[0] == 0)
exit(); exit(-1);
exec(ecmd->argv[0], ecmd->argv); exec(ecmd->argv[0], ecmd->argv);
fprintf(2, "exec %s failed\n", ecmd->argv[0]); fprintf(2, "exec %s failed\n", ecmd->argv[0]);
break; break;
@ -84,7 +84,7 @@ runcmd(struct cmd *cmd)
close(rcmd->fd); close(rcmd->fd);
if(open(rcmd->file, rcmd->mode) < 0){ if(open(rcmd->file, rcmd->mode) < 0){
fprintf(2, "open %s failed\n", rcmd->file); fprintf(2, "open %s failed\n", rcmd->file);
exit(); exit(-1);
} }
runcmd(rcmd->cmd); runcmd(rcmd->cmd);
break; break;
@ -93,7 +93,7 @@ runcmd(struct cmd *cmd)
lcmd = (struct listcmd*)cmd; lcmd = (struct listcmd*)cmd;
if(fork1() == 0) if(fork1() == 0)
runcmd(lcmd->left); runcmd(lcmd->left);
wait(); wait(0);
runcmd(lcmd->right); runcmd(lcmd->right);
break; break;
@ -117,8 +117,8 @@ runcmd(struct cmd *cmd)
} }
close(p[0]); close(p[0]);
close(p[1]); close(p[1]);
wait(); wait(0);
wait(); wait(0);
break; break;
case BACK: case BACK:
@ -127,7 +127,7 @@ runcmd(struct cmd *cmd)
runcmd(bcmd->cmd); runcmd(bcmd->cmd);
break; break;
} }
exit(); exit(0);
} }
int int
@ -166,16 +166,16 @@ main(void)
} }
if(fork1() == 0) if(fork1() == 0)
runcmd(parsecmd(buf)); runcmd(parsecmd(buf));
wait(); wait(0);
} }
exit(); exit(0);
} }
void void
panic(char *s) panic(char *s)
{ {
fprintf(2, "%s\n", s); fprintf(2, "%s\n", s);
exit(); exit(-1);
} }
int int

View file

@ -43,7 +43,7 @@ main(int argc, char *argv[])
read(fd, data, sizeof(data)); read(fd, data, sizeof(data));
close(fd); close(fd);
wait(); wait(0);
exit(); exit(0);
} }

View file

@ -3,8 +3,8 @@ struct rtcdate;
// system calls // system calls
int fork(void); int fork(void);
int exit(void) __attribute__((noreturn)); int exit(int) __attribute__((noreturn));
int wait(void); int wait(int*);
int pipe(int*); int pipe(int*);
int write(int, const void*, int); int write(int, const void*, int);
int read(int, void*, int); int read(int, void*, int);

File diff suppressed because it is too large Load diff

View file

@ -27,7 +27,7 @@ wc(int fd, char *name)
} }
if(n < 0){ if(n < 0){
printf("wc: read error\n"); printf("wc: read error\n");
exit(); exit(-1);
} }
printf("%d %d %d %s\n", l, w, c, name); printf("%d %d %d %s\n", l, w, c, name);
} }
@ -39,16 +39,16 @@ main(int argc, char *argv[])
if(argc <= 1){ if(argc <= 1){
wc(0, ""); wc(0, "");
exit(); exit(0);
} }
for(i = 1; i < argc; i++){ for(i = 1; i < argc; i++){
if((fd = open(argv[i], 0)) < 0){ if((fd = open(argv[i], 0)) < 0){
printf("wc: cannot open %s\n", argv[i]); printf("wc: cannot open %s\n", argv[i]);
exit(); exit(-1);
} }
wc(fd, argv[i]); wc(fd, argv[i]);
close(fd); close(fd);
} }
exit(); exit(0);
} }

View file

@ -10,5 +10,5 @@ main(void)
{ {
if(fork() > 0) if(fork() > 0)
sleep(5); // Let child exit before parent. sleep(5); // Let child exit before parent.
exit(); exit(0);
} }