diff --git a/main.c b/main.c index b489231..275aa80 100644 --- a/main.c +++ b/main.c @@ -12,19 +12,13 @@ static void mpmain(void) __attribute__((noreturn)); int main(void) { - int bcpu, i; extern char edata[], end[]; // clear BSS memset(edata, 0, end - edata); - // pushcli() every processor during bootstrap. - for(i=0; i<NCPU; i++) - cpus[i].ncli = 1; // no interrupts during bootstrap - mp_init(); // collect info about this machine - bcpu = mp_bcpu(); - lapic_init(bcpu); + lapic_init(mp_bcpu()); cprintf("\ncpu%d: starting xv6\n\n", cpu()); pinit(); // process table @@ -38,19 +32,15 @@ main(void) console_init(); // I/O devices & their interrupts ide_init(); // disk if(!ismp) - timer_init(); // uniprocessor timer + timer_init(); // uniprocessor timer userinit(); // first user process + bootothers(); // start other processors - // Allocate scheduler stacks and boot the other CPUs. - for(i=0; i<ncpu; i++) - cpus[i].stack = kalloc(KSTACKSIZE); - bootothers(); - - // Switch to our scheduler stack and continue with mpmain. - asm volatile("movl %0, %%esp" : : "r" (cpus[bcpu].stack+KSTACKSIZE)); + // Finish setting up this processor in mpmain. mpmain(); } +// Bootstrap processor gets here after setting up the hardware. // Additional processors start here. static void mpmain(void) @@ -62,7 +52,6 @@ mpmain(void) setupsegs(0); cpuid(0, 0, 0, 0, 0); // memory barrier cpus[cpu()].booted = 1; - popcli(); scheduler(); } @@ -73,6 +62,7 @@ bootothers(void) extern uchar _binary_bootother_start[], _binary_bootother_size[]; uchar *code; struct cpu *c; + char *stack; // Write bootstrap code to unused memory at 0x7000. code = (uchar*)0x7000; @@ -83,7 +73,8 @@ bootothers(void) continue; // Fill in %esp, %eip and start code on cpu. - *(void**)(code-4) = c->stack + KSTACKSIZE; + stack = kalloc(KSTACKSIZE); + *(void**)(code-4) = stack + KSTACKSIZE; *(void**)(code-8) = mpmain; lapic_startap(c->apicid, (uint)code); diff --git a/proc.c b/proc.c index b009892..808a15e 100644 --- a/proc.c +++ b/proc.c @@ -179,7 +179,6 @@ userinit(void) } // Return currently running process. -// XXX comment better struct proc* curproc(void) { @@ -206,11 +205,13 @@ scheduler(void) struct cpu *c; int i; + c = &cpus[cpu()]; for(;;){ + // Enable interrupts on this processor. + sti(); + // Loop over process table looking for process to run. acquire(&proc_table_lock); - - c = &cpus[cpu()]; for(i = 0; i < NPROC; i++){ p = &proc[i]; if(p->state != RUNNABLE) @@ -229,8 +230,8 @@ scheduler(void) c->curproc = 0; setupsegs(0); } - release(&proc_table_lock); + } } diff --git a/proc.h b/proc.h index 36913c4..fa60452 100644 --- a/proc.h +++ b/proc.h @@ -56,9 +56,9 @@ struct cpu { struct context context; // Switch here to enter scheduler struct taskstate ts; // Used by x86 to find stack for interrupt struct segdesc gdt[NSEGS]; // x86 global descriptor table - char *stack; volatile int booted; // Has the CPU started? - int ncli; // Depth of pushcli nesting. + int ncli; // Depth of pushcli nesting. + int intena; // Were interrupts enabled before pushcli? }; extern struct cpu cpus[NCPU]; diff --git a/spinlock.c b/spinlock.c index bf02292..a1aa37d 100644 --- a/spinlock.c +++ b/spinlock.c @@ -88,15 +88,19 @@ holding(struct spinlock *lock) } - -// XXX! -// Better names? Better functions? +// Pushcli/popcli are like cli/sti except that they are matched: +// it takes two popcli to undo two pushcli. Also, if interrupts +// are off, then pushcli, popcli leaves them off. void pushcli(void) { + int eflags; + + eflags = read_eflags(); cli(); - cpus[cpu()].ncli++; + if(cpus[cpu()].ncli++ == 0) + cpus[cpu()].intena = eflags & FL_IF; } void @@ -106,7 +110,7 @@ popcli(void) panic("popcli - interruptible"); if(--cpus[cpu()].ncli < 0) panic("popcli"); - if(cpus[cpu()].ncli == 0) + if(cpus[cpu()].ncli == 0 && cpus[cpu()].intena) sti(); } diff --git a/trap.c b/trap.c index 0acc94b..e38cd00 100644 --- a/trap.c +++ b/trap.c @@ -44,9 +44,6 @@ trap(struct trapframe *tf) return; } - // No interrupts during interrupt handling. - pushcli(); - switch(tf->trapno){ case IRQ_OFFSET + IRQ_TIMER: if(cpu() == 0){ @@ -84,8 +81,6 @@ trap(struct trapframe *tf) cp->killed = 1; } - popcli(); - // 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.)