diff --git a/Makefile b/Makefile index 2a8c3ce..fa93f85 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ CC = i386-jos-elf-gcc LD = i386-jos-elf-ld OBJCOPY = i386-jos-elf-objcopy OBJDUMP = i386-jos-elf-objdump -CFLAGS = -nostdinc -I. -O -Wall +CFLAGS = -nostdinc -I. -O -Wall -MD xv6.img : bootblock kernel dd if=/dev/zero of=xv6.img count=10000 @@ -27,5 +27,7 @@ kernel : $(OBJS) vectors.S : vectors.pl perl vectors.pl > vectors.S +-include *.d + clean : - rm -f *.o bootblock kernel kernel.asm xv6.img + rm -f *.o bootblock kernel kernel.asm xv6.img *.d diff --git a/defs.h b/defs.h index ad51167..eea3d0c 100644 --- a/defs.h +++ b/defs.h @@ -12,6 +12,8 @@ struct proc; void setupsegs(struct proc *); struct proc * newproc(void); void swtch(void); +void sleep(void *); +void wakeup(void *); // trap.c void tinit(void); diff --git a/main.c b/main.c index 6b07d83..43c8c02 100644 --- a/main.c +++ b/main.c @@ -42,6 +42,8 @@ main() p->tf->tf_es = p->tf->tf_ds = p->tf->tf_ss = (SEG_UDATA << 3) | 3; p->tf->tf_cs = (SEG_UCODE << 3) | 3; p->tf->tf_eflags = FL_IF; + p->pid = 0; + p->ppid = 0; setupsegs(p); p = newproc(); @@ -56,6 +58,13 @@ main() p->mem[i++] = 0xcd; // int p->mem[i++] = T_SYSCALL; p->mem[i++] = 0xb8; // mov ..., %eax + p->mem[i++] = SYS_wait; + p->mem[i++] = 0; + p->mem[i++] = 0; + p->mem[i++] = 0; + p->mem[i++] = 0xcd; // int + p->mem[i++] = T_SYSCALL; + p->mem[i++] = 0xb8; // mov ..., %eax p->mem[i++] = SYS_exit; p->mem[i++] = 0; p->mem[i++] = 0; diff --git a/proc.c b/proc.c index 1e90e37..8291039 100644 --- a/proc.c +++ b/proc.c @@ -7,6 +7,7 @@ struct proc proc[NPROC]; struct proc *curproc; +int next_pid = 1; /* * set up a process's task state and segment descriptors @@ -54,6 +55,8 @@ newproc() if(np >= &proc[NPROC]) return 0; + np->pid = next_pid++; + np->ppid = curproc->pid; np->sz = curproc->sz; np->mem = kalloc(curproc->sz); if(np->mem == 0) @@ -111,7 +114,12 @@ swtch() // XXX callee-saved registers? - // XXX probably ought to lgdt on trap return too + // h/w sets busy bit in TSS descriptor sometimes, and faults + // if it's set in LTR. so clear tss descriptor busy bit. + curproc->gdt[SEG_TSS].sd_type = STS_T32A; + + // XXX probably ought to lgdt on trap return too, in case + // a system call has moved a program or changed its size. asm volatile("lgdt %0" : : "g" (np->gdt_pd.pd_lim)); ltr(SEG_TSS << 3); @@ -122,3 +130,21 @@ swtch() asm volatile("movl %0, %%esp" : : "g" (np->esp)); asm volatile("movl %0, %%ebp" : : "g" (np->ebp)); } + +void +sleep(void *chan) +{ + curproc->chan = chan; + curproc->state = WAITING; + swtch(); +} + +void +wakeup(void *chan) +{ + struct proc *p; + + for(p = proc; p < &proc[NPROC]; p++) + if(p->state == WAITING && p->chan == chan) + p->state = RUNNABLE; +} diff --git a/proc.h b/proc.h index 39e1c49..6eba566 100644 --- a/proc.h +++ b/proc.h @@ -20,7 +20,10 @@ struct proc{ char *mem; // start of process's physical memory unsigned sz; // total size of mem, including kernel stack char *kstack; // kernel stack, separate from mem so it doesn't move - enum { UNUSED, RUNNABLE, WAITING } state; + enum { UNUSED, RUNNABLE, WAITING, ZOMBIE } state; + int pid; + int ppid; + void *chan; // sleep struct Taskstate ts; // only to give cpu address of kernel stack struct Segdesc gdt[NSEGS]; diff --git a/syscall.c b/syscall.c index 9cb20dc..1968c8a 100644 --- a/syscall.c +++ b/syscall.c @@ -24,11 +24,52 @@ sys_fork() void sys_exit() { - curproc->state = UNUSED; - // XXX free resources. notify parent. abandon children. + struct proc *p; + + curproc->state = ZOMBIE; + + // wake up parent + for(p = proc; p < &proc[NPROC]; p++) + if(p->pid == curproc->ppid) + wakeup(p); + + // abandon children + for(p = proc; p < &proc[NPROC]; p++) + if(p->ppid == curproc->pid) + p->pid = 1; + swtch(); } +void +sys_wait() +{ + struct proc *p; + int any; + + cprintf("waid pid %d ppid %d\n", curproc->pid, curproc->ppid); + + while(1){ + any = 0; + for(p = proc; p < &proc[NPROC]; p++){ + if(p->state == ZOMBIE && p->ppid == curproc->pid){ + kfree(p->mem, p->sz); + kfree(p->kstack, KSTACKSIZE); + p->state = UNUSED; + cprintf("%x collected %x\n", curproc, p); + return; + } + if(p->state != UNUSED && p->ppid == curproc->pid) + any = 1; + } + if(any == 0){ + cprintf("%x nothing to wait for\n", curproc); + return; + } + sleep(curproc); + } +} + void syscall() { @@ -42,6 +83,9 @@ syscall() case SYS_exit: sys_exit(); break; + case SYS_wait: + sys_wait(); + break; default: cprintf("unknown sys call %d\n", num); // XXX fault diff --git a/syscall.h b/syscall.h index 3155dbd..13bb2c7 100644 --- a/syscall.h +++ b/syscall.h @@ -1,2 +1,3 @@ #define SYS_fork 1 #define SYS_exit 2 +#define SYS_wait 3