sleep, wakeup, wait, exit
This commit is contained in:
parent
a4c03dea09
commit
be0a7eacda
7 changed files with 93 additions and 6 deletions
6
Makefile
6
Makefile
|
@ -5,7 +5,7 @@ CC = i386-jos-elf-gcc
|
||||||
LD = i386-jos-elf-ld
|
LD = i386-jos-elf-ld
|
||||||
OBJCOPY = i386-jos-elf-objcopy
|
OBJCOPY = i386-jos-elf-objcopy
|
||||||
OBJDUMP = i386-jos-elf-objdump
|
OBJDUMP = i386-jos-elf-objdump
|
||||||
CFLAGS = -nostdinc -I. -O -Wall
|
CFLAGS = -nostdinc -I. -O -Wall -MD
|
||||||
|
|
||||||
xv6.img : bootblock kernel
|
xv6.img : bootblock kernel
|
||||||
dd if=/dev/zero of=xv6.img count=10000
|
dd if=/dev/zero of=xv6.img count=10000
|
||||||
|
@ -27,5 +27,7 @@ kernel : $(OBJS)
|
||||||
vectors.S : vectors.pl
|
vectors.S : vectors.pl
|
||||||
perl vectors.pl > vectors.S
|
perl vectors.pl > vectors.S
|
||||||
|
|
||||||
|
-include *.d
|
||||||
|
|
||||||
clean :
|
clean :
|
||||||
rm -f *.o bootblock kernel kernel.asm xv6.img
|
rm -f *.o bootblock kernel kernel.asm xv6.img *.d
|
||||||
|
|
2
defs.h
2
defs.h
|
@ -12,6 +12,8 @@ struct proc;
|
||||||
void setupsegs(struct proc *);
|
void setupsegs(struct proc *);
|
||||||
struct proc * newproc(void);
|
struct proc * newproc(void);
|
||||||
void swtch(void);
|
void swtch(void);
|
||||||
|
void sleep(void *);
|
||||||
|
void wakeup(void *);
|
||||||
|
|
||||||
// trap.c
|
// trap.c
|
||||||
void tinit(void);
|
void tinit(void);
|
||||||
|
|
9
main.c
9
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_es = p->tf->tf_ds = p->tf->tf_ss = (SEG_UDATA << 3) | 3;
|
||||||
p->tf->tf_cs = (SEG_UCODE << 3) | 3;
|
p->tf->tf_cs = (SEG_UCODE << 3) | 3;
|
||||||
p->tf->tf_eflags = FL_IF;
|
p->tf->tf_eflags = FL_IF;
|
||||||
|
p->pid = 0;
|
||||||
|
p->ppid = 0;
|
||||||
setupsegs(p);
|
setupsegs(p);
|
||||||
|
|
||||||
p = newproc();
|
p = newproc();
|
||||||
|
@ -56,6 +58,13 @@ main()
|
||||||
p->mem[i++] = 0xcd; // int
|
p->mem[i++] = 0xcd; // int
|
||||||
p->mem[i++] = T_SYSCALL;
|
p->mem[i++] = T_SYSCALL;
|
||||||
p->mem[i++] = 0xb8; // mov ..., %eax
|
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++] = SYS_exit;
|
||||||
p->mem[i++] = 0;
|
p->mem[i++] = 0;
|
||||||
p->mem[i++] = 0;
|
p->mem[i++] = 0;
|
||||||
|
|
28
proc.c
28
proc.c
|
@ -7,6 +7,7 @@
|
||||||
|
|
||||||
struct proc proc[NPROC];
|
struct proc proc[NPROC];
|
||||||
struct proc *curproc;
|
struct proc *curproc;
|
||||||
|
int next_pid = 1;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* set up a process's task state and segment descriptors
|
* set up a process's task state and segment descriptors
|
||||||
|
@ -54,6 +55,8 @@ newproc()
|
||||||
if(np >= &proc[NPROC])
|
if(np >= &proc[NPROC])
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
np->pid = next_pid++;
|
||||||
|
np->ppid = curproc->pid;
|
||||||
np->sz = curproc->sz;
|
np->sz = curproc->sz;
|
||||||
np->mem = kalloc(curproc->sz);
|
np->mem = kalloc(curproc->sz);
|
||||||
if(np->mem == 0)
|
if(np->mem == 0)
|
||||||
|
@ -111,7 +114,12 @@ swtch()
|
||||||
|
|
||||||
// XXX callee-saved registers?
|
// 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));
|
asm volatile("lgdt %0" : : "g" (np->gdt_pd.pd_lim));
|
||||||
ltr(SEG_TSS << 3);
|
ltr(SEG_TSS << 3);
|
||||||
|
@ -122,3 +130,21 @@ swtch()
|
||||||
asm volatile("movl %0, %%esp" : : "g" (np->esp));
|
asm volatile("movl %0, %%esp" : : "g" (np->esp));
|
||||||
asm volatile("movl %0, %%ebp" : : "g" (np->ebp));
|
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;
|
||||||
|
}
|
||||||
|
|
5
proc.h
5
proc.h
|
@ -20,7 +20,10 @@ struct proc{
|
||||||
char *mem; // start of process's physical memory
|
char *mem; // start of process's physical memory
|
||||||
unsigned sz; // total size of mem, including kernel stack
|
unsigned sz; // total size of mem, including kernel stack
|
||||||
char *kstack; // kernel stack, separate from mem so it doesn't move
|
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 Taskstate ts; // only to give cpu address of kernel stack
|
||||||
struct Segdesc gdt[NSEGS];
|
struct Segdesc gdt[NSEGS];
|
||||||
|
|
48
syscall.c
48
syscall.c
|
@ -24,11 +24,52 @@ sys_fork()
|
||||||
void
|
void
|
||||||
sys_exit()
|
sys_exit()
|
||||||
{
|
{
|
||||||
curproc->state = UNUSED;
|
struct proc *p;
|
||||||
// XXX free resources. notify parent. abandon children.
|
|
||||||
|
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();
|
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
|
void
|
||||||
syscall()
|
syscall()
|
||||||
{
|
{
|
||||||
|
@ -42,6 +83,9 @@ syscall()
|
||||||
case SYS_exit:
|
case SYS_exit:
|
||||||
sys_exit();
|
sys_exit();
|
||||||
break;
|
break;
|
||||||
|
case SYS_wait:
|
||||||
|
sys_wait();
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
cprintf("unknown sys call %d\n", num);
|
cprintf("unknown sys call %d\n", num);
|
||||||
// XXX fault
|
// XXX fault
|
||||||
|
|
|
@ -1,2 +1,3 @@
|
||||||
#define SYS_fork 1
|
#define SYS_fork 1
|
||||||
#define SYS_exit 2
|
#define SYS_exit 2
|
||||||
|
#define SYS_wait 3
|
||||||
|
|
Loading…
Reference in a new issue