test: store curproc at top of stack

I don't actually think this is worthwhile, but I figured
I would check it in before reverting it, so that it can
be in the revision history.

Pros:
  * curproc doesn't need to turn on/off interrupts
  * scheduler doesn't have to edit curproc anymore

Cons:
  * it's ugly
  * all the stack computation is more complicated.
  * it doesn't actually simplify anything but curproc,
    and even curproc is harder to follow.
This commit is contained in:
rsc 2007-09-27 20:29:50 +00:00
parent aefc13f8ba
commit ce2e751555
3 changed files with 16 additions and 14 deletions

8
main.c
View file

@ -42,12 +42,14 @@ main(void)
userinit(); // first user process userinit(); // first user process
// Allocate scheduler stacks and boot the other CPUs. // Allocate scheduler stacks and boot the other CPUs.
for(i=0; i<ncpu; i++) for(i=0; i<ncpu; i++){
cpus[i].stack = kalloc(KSTACKSIZE); cpus[i].stack = kalloc(KSTACKSIZE);
*(void**)(cpus[i].stack + KSTACKTOP) = 0;
}
bootothers(); bootothers();
// Switch to our scheduler stack and continue with mpmain. // Switch to our scheduler stack and continue with mpmain.
asm volatile("movl %0, %%esp" : : "r" (cpus[bcpu].stack+KSTACKSIZE)); asm volatile("movl %0, %%esp" : : "r" (cpus[bcpu].stack+KSTACKTOP));
mpmain(); mpmain();
} }
@ -84,7 +86,7 @@ bootothers(void)
continue; continue;
// Fill in %esp, %eip and start code on cpu. // Fill in %esp, %eip and start code on cpu.
*(void**)(code-4) = c->stack + KSTACKSIZE; *(void**)(code-4) = c->stack + KSTACKTOP;
*(void**)(code-8) = mpmain; *(void**)(code-8) = mpmain;
lapic_startap(c->apicid, (uint)code); lapic_startap(c->apicid, (uint)code);

17
proc.c
View file

@ -75,7 +75,7 @@ setupsegs(struct proc *p)
c = &cpus[cpu()]; c = &cpus[cpu()];
c->ts.ss0 = SEG_PROCSTACK << 3; c->ts.ss0 = SEG_PROCSTACK << 3;
if(p) if(p)
c->ts.esp0 = (uint)(p->kstack + KSTACKSIZE); c->ts.esp0 = (uint)(p->kstack + KSTACKTOP);
else else
c->ts.esp0 = 0xffffffff; c->ts.esp0 = 0xffffffff;
@ -118,7 +118,8 @@ copyproc(struct proc *p)
np->state = UNUSED; np->state = UNUSED;
return 0; return 0;
} }
np->tf = (struct trapframe*)(np->kstack + KSTACKSIZE) - 1; *(void**)(np->kstack + KSTACKTOP) = np;
np->tf = (struct trapframe*)(np->kstack + KSTACKTOP) - 1;
if(p){ // Copy process state from p. if(p){ // Copy process state from p.
np->parent = p; np->parent = p;
@ -187,12 +188,10 @@ userinit(void)
struct proc* struct proc*
curproc(void) curproc(void)
{ {
struct proc *p; uint esp;
pushcli(); asm volatile("movl %%esp, %0" : "=a" (esp));
p = cpus[cpu()].curproc; return *(struct proc**)((esp & ~(KSTACKSIZE-1)) + KSTACKTOP);
popcli();
return p;
} }
//PAGEBREAK: 42 //PAGEBREAK: 42
@ -223,14 +222,12 @@ scheduler(void)
// Switch to chosen process. It is the process's job // Switch to chosen process. It is the process's job
// to release proc_table_lock and then reacquire it // to release proc_table_lock and then reacquire it
// before jumping back to us. // before jumping back to us.
c->curproc = p;
setupsegs(p); setupsegs(p);
p->state = RUNNING; p->state = RUNNING;
swtch(&c->context, &p->context); swtch(&c->context, &p->context);
// Process is done running for now. // Process is done running for now.
// It should have changed its p->state before coming back. // It should have changed its p->state before coming back.
c->curproc = 0;
setupsegs(0); setupsegs(0);
} }
@ -239,7 +236,7 @@ scheduler(void)
} }
// Enter scheduler. Must already hold proc_table_lock // Enter scheduler. Must already hold proc_table_lock
// and have changed curproc[cpu()]->state. // and have changed cp->state.
void void
sched(void) sched(void)
{ {

5
proc.h
View file

@ -46,6 +46,10 @@ struct proc {
char name[16]; // Process name (debugging) char name[16]; // Process name (debugging)
}; };
// The word at kstack + KSTACKTOP is a pointer to the struct proc.
#define KSTACKTOP (KSTACKSIZE-4)
// Process memory is laid out contiguously, low addresses first: // Process memory is laid out contiguously, low addresses first:
// text // text
// original data and bss // original data and bss
@ -55,7 +59,6 @@ struct proc {
// Per-CPU state // Per-CPU state
struct cpu { struct cpu {
uchar apicid; // Local APIC ID uchar apicid; // Local APIC ID
struct proc *curproc; // Process currently running.
struct context context; // Switch here to enter scheduler struct context context; // Switch here to enter scheduler
struct taskstate ts; // Used by x86 to find stack for interrupt struct taskstate ts; // Used by x86 to find stack for interrupt
struct segdesc gdt[NSEGS]; // x86 global descriptor table struct segdesc gdt[NSEGS]; // x86 global descriptor table