summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile6
-rw-r--r--defs.h2
-rw-r--r--main.c9
-rw-r--r--proc.c28
-rw-r--r--proc.h5
-rw-r--r--syscall.c48
-rw-r--r--syscall.h1
7 files changed, 93 insertions, 6 deletions
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,12 +24,53 @@ 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()
{
int num = curproc->tf->tf_regs.reg_eax;
@@ -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