diff --git a/defs.h b/defs.h index af22433..7af5421 100644 --- a/defs.h +++ b/defs.h @@ -139,7 +139,9 @@ void syscall(void); // trap.c void idtinit(void); +extern int ticks; void tvinit(void); +extern struct spinlock tickslock; // number of elements in fixed-size array #define NELEM(x) (sizeof(x)/sizeof((x)[0])) diff --git a/syscall.c b/syscall.c index d7cf123..9fed725 100644 --- a/syscall.c +++ b/syscall.c @@ -102,10 +102,10 @@ extern int sys_open(void); extern int sys_pipe(void); extern int sys_read(void); extern int sys_sbrk(void); +extern int sys_sleep(void); extern int sys_unlink(void); extern int sys_wait(void); extern int sys_write(void); -extern int sys_yield(void); static int (*syscalls[])(void) = { [SYS_chdir] sys_chdir, @@ -124,10 +124,10 @@ static int (*syscalls[])(void) = { [SYS_pipe] sys_pipe, [SYS_read] sys_read, [SYS_sbrk] sys_sbrk, +[SYS_sleep] sys_sleep, [SYS_unlink] sys_unlink, [SYS_wait] sys_wait, [SYS_write] sys_write, -[SYS_yield] sys_yield, }; void diff --git a/syscall.h b/syscall.h index 85ea220..f4b7807 100644 --- a/syscall.h +++ b/syscall.h @@ -18,4 +18,4 @@ #define SYS_dup 17 #define SYS_getpid 18 #define SYS_sbrk 19 -#define SYS_yield 20 +#define SYS_sleep 20 diff --git a/sysproc.c b/sysproc.c index 8cf3291..48fbe37 100644 --- a/sysproc.c +++ b/sysproc.c @@ -70,8 +70,21 @@ sys_sbrk(void) } int -sys_yield(void) +sys_sleep(void) { - yield(); + int n, ticks0; + + if(argint(0, &n) < 0) + return -1; + acquire(&tickslock); + ticks0 = ticks; + while(ticks - ticks0 < n){ + if(cp->killed){ + release(&tickslock); + return -1; + } + sleep(&ticks, &tickslock); + } + release(&tickslock); return 0; } diff --git a/trap.c b/trap.c index 217e79d..e045aed 100644 --- a/trap.c +++ b/trap.c @@ -6,10 +6,13 @@ #include "x86.h" #include "traps.h" #include "syscall.h" +#include "spinlock.h" // Interrupt descriptor table (shared by all CPUs). struct gatedesc idt[256]; extern uint vectors[]; // in vectors.S: array of 256 entry pointers +struct spinlock tickslock; +int ticks; void tvinit(void) @@ -19,6 +22,8 @@ tvinit(void) for(i = 0; i < 256; i++) SETGATE(idt[i], 0, SEG_KCODE<<3, vectors[i], 0); SETGATE(idt[T_SYSCALL], 0, SEG_KCODE<<3, vectors[T_SYSCALL], DPL_USER); + + initlock(&tickslock, "time"); } void @@ -47,21 +52,14 @@ trap(struct trapframe *tf) // PAGEBREAK: 10 switch(tf->trapno){ case IRQ_OFFSET + IRQ_TIMER: - lapic_timerintr(); - cpus[cpu()].nlock--; - if(cp){ - // Force process exit if it has been killed and is in user space. - // (If it is still executing in the kernel, let it keep running - // until it gets to the regular system call return.) - if((tf->cs&3) == DPL_USER && cp->killed) - proc_exit(); - - // Force process to give up CPU and let others run. - // If locks were held with interrupts on, would need to check nlock. - if(cp->state == RUNNING) - yield(); + if(cpu() == 0){ + acquire(&tickslock); + ticks++; + wakeup(&ticks); + release(&tickslock); } - return; + lapic_eoi(); + break; case IRQ_OFFSET + IRQ_IDE: ide_intr(); @@ -75,6 +73,7 @@ trap(struct trapframe *tf) case IRQ_OFFSET + IRQ_SPURIOUS: cprintf("spurious interrupt from cpu %d eip %x\n", cpu(), tf->eip); + lapic_eoi(); break; default: @@ -84,12 +83,23 @@ trap(struct trapframe *tf) cp->pid, cp->name, tf->trapno, tf->err, cpu(), tf->eip); proc_exit(); } - // Otherwise it's our mistake. cprintf("unexpected trap %d from cpu %d eip %x\n", tf->trapno, cpu(), tf->eip); panic("trap"); } - cpus[cpu()].nlock--; + + if(tf->trapno == IRQ_OFFSET + IRQ_TIMER && cp != 0){ + // Force process exit if it has been killed and is in user space. + // (If it is still executing in the kernel, let it keep running + // until it gets to the regular system call return.) + if((tf->cs&3) == DPL_USER && cp->killed) + proc_exit(); + + // Force process to give up CPU and let others run. + // If locks were held with interrupts on, would need to check nlock. + if(cp->state == RUNNING) + yield(); + } } diff --git a/trapasm.S b/trapasm.S index ac96413..87a832a 100644 --- a/trapasm.S +++ b/trapasm.S @@ -3,7 +3,7 @@ .globl trapret1 .globl alltraps -.set SEG_KDATA_SEL 0x10 # selector for SEG_KDATA +.set SEG_KDATA_SEL, 0x10 # selector for SEG_KDATA # vectors.S sends all traps here. alltraps: diff --git a/user.h b/user.h index 1bbe2fd..c3ee675 100644 --- a/user.h +++ b/user.h @@ -18,6 +18,7 @@ int chdir(char*); int dup(int); int getpid(); char* sbrk(int); +int sleep(int); // ulib.c int stat(char*, struct stat*); diff --git a/usys.S b/usys.S index 210774d..380cb91 100644 --- a/usys.S +++ b/usys.S @@ -27,4 +27,4 @@ STUB(chdir) STUB(dup) STUB(getpid) STUB(sbrk) -STUB(yield) +STUB(sleep) diff --git a/zombie.c b/zombie.c index 883ea75..07ad798 100644 --- a/zombie.c +++ b/zombie.c @@ -1,4 +1,5 @@ -// Create a zombie process. +// Create a zombie process that +// must be reparented at exit. #include "types.h" #include "stat.h" @@ -10,7 +11,6 @@ main(void) int i; if(fork() > 0) - for(i=0; i<10; i++) - yield(); + sleep(5); // Let child exit before parent. exit(); }