From 2c5f7aba38f8e7207a81fdef36d7720bda9dc4e5 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Sat, 11 Jul 2009 19:28:29 -0700 Subject: [PATCH] initproc, usegment, swtch tweaks --- defs.h | 5 ++-- proc.c | 83 +++++++++++++++++++++++++------------------------------ swtch.S | 8 ++++-- trapasm.S | 8 ------ 4 files changed, 45 insertions(+), 59 deletions(-) diff --git a/defs.h b/defs.h index cb47716..09fa467 100644 --- a/defs.h +++ b/defs.h @@ -52,7 +52,7 @@ int writei(struct inode*, char*, uint, uint); // ide.c void ideinit(void); void ideintr(void); -void iderw(struct buf *); +void iderw(struct buf*); // ioapic.c void ioapicenable(int irq, int cpu); @@ -109,7 +109,7 @@ void wakeup(void*); void yield(void); // swtch.S -void swtch(struct context**, struct context**); +void swtch(struct context**, struct context*); // spinlock.c void acquire(struct spinlock*); @@ -151,7 +151,6 @@ void uartinit(void); void uartintr(void); void uartputc(int); - // number of elements in fixed-size array #define NELEM(x) (sizeof(x)/sizeof((x)[0])) diff --git a/proc.c b/proc.c index 554ad28..aa6c4ec 100644 --- a/proc.c +++ b/proc.c @@ -15,7 +15,7 @@ static struct proc *initproc; int nextpid = 1; extern void forkret(void); -extern void forkret1(struct trapframe*); +extern void trapret(void); void pinit(void) @@ -30,19 +30,18 @@ static struct proc* allocproc(void) { struct proc *p; + char *sp; acquire(&ptable.lock); - for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){ - if(p->state == UNUSED){ - p->state = EMBRYO; - p->pid = nextpid++; + for(p = ptable.proc; p < &ptable.proc[NPROC]; p++) + if(p->state == UNUSED) goto found; - } - } release(&ptable.lock); return 0; found: + p->state = EMBRYO; + p->pid = nextpid++; release(&ptable.lock); // Allocate kernel stack if necessary. @@ -50,11 +49,20 @@ found: p->state = UNUSED; return 0; } - p->tf = (struct trapframe*)(p->kstack + KSTACKSIZE) - 1; + sp = p->kstack + KSTACKSIZE; + + // Leave room for trap frame. + sp -= sizeof *p->tf; + p->tf = (struct trapframe*)sp; + + // Set up new context to start executing at forkret, + // which returns to trapret (see below). + sp -= 4; + *(uint*)sp = (uint)trapret; - // Set up new context to start executing at forkret (see below). - p->context = (struct context *)p->tf - 1; - memset(p->context, 0, sizeof(*p->context)); + sp -= sizeof *p->context; + p->context = (struct context*)sp; + memset(p->context, 0, sizeof *p->context); p->context->eip = (uint)forkret; return p; } @@ -79,19 +87,16 @@ growproc(int n) } // Set up CPU's kernel segment descriptors. +// Run once at boot time on each CPU. void ksegment(void) { struct cpu *c1; c1 = &cpus[cpu()]; - c1->gdt[0] = SEG_NULL; c1->gdt[SEG_KCODE] = SEG(STA_X|STA_R, 0, 0x100000 + 64*1024-1, 0); c1->gdt[SEG_KDATA] = SEG(STA_W, 0, 0xffffffff, 0); - c1->gdt[SEG_KCPU] = SEG(STA_W, (uint)&c1->tls+sizeof(c1->tls), 0xffffffff, 0); - c1->gdt[SEG_UCODE] = SEG_NULL; - c1->gdt[SEG_UDATA] = SEG_NULL; - c1->gdt[SEG_TSS] = SEG_NULL; + c1->gdt[SEG_KCPU] = SEG(STA_W, (uint)(&c1->tls+1), 0xffffffff, 0); lgdt(c1->gdt, sizeof(c1->gdt)); loadfsgs(SEG_KCPU << 3); @@ -106,23 +111,12 @@ void usegment(void) { pushcli(); - c->ts.ss0 = SEG_KDATA << 3; - if(cp) - c->ts.esp0 = (uint)(cp->kstack + KSTACKSIZE); - else - c->ts.esp0 = 0xffffffff; - - if(cp){ - c->gdt[SEG_UCODE] = SEG(STA_X|STA_R, (uint)cp->mem, cp->sz-1, DPL_USER); - c->gdt[SEG_UDATA] = SEG(STA_W, (uint)cp->mem, cp->sz-1, DPL_USER); - } else { - c->gdt[SEG_UCODE] = SEG_NULL; - c->gdt[SEG_UDATA] = SEG_NULL; - } + c->gdt[SEG_UCODE] = SEG(STA_X|STA_R, (uint)cp->mem, cp->sz-1, DPL_USER); + c->gdt[SEG_UDATA] = SEG(STA_W, (uint)cp->mem, cp->sz-1, DPL_USER); c->gdt[SEG_TSS] = SEG16(STS_T32A, (uint)&c->ts, sizeof(c->ts)-1, 0); c->gdt[SEG_TSS].s = 0; - - lgdt(c->gdt, sizeof(c->gdt)); + c->ts.ss0 = SEG_KDATA << 3; + c->ts.esp0 = (uint)cp->kstack + KSTACKSIZE; ltr(SEG_TSS << 3); popcli(); } @@ -171,7 +165,7 @@ void userinit(void) { struct proc *p; - extern uchar _binary_initcode_start[], _binary_initcode_size[]; + extern char _binary_initcode_start[], _binary_initcode_size[]; p = allocproc(); initproc = p; @@ -179,6 +173,7 @@ userinit(void) // Initialize memory from initcode.S p->sz = PAGE; p->mem = kalloc(p->sz); + memset(p->mem, 0, p->sz); memmove(p->mem, _binary_initcode_start, (int)_binary_initcode_size); memset(p->tf, 0, sizeof(*p->tf)); @@ -210,7 +205,7 @@ scheduler(void) struct proc *p; for(;;){ - // Enable interrupts on this processor, in lieu of saving intena. + // Enable interrupts on this processor. sti(); // Loop over process table looking for process to run. @@ -225,36 +220,35 @@ scheduler(void) cp = p; usegment(); p->state = RUNNING; - swtch(&c->context, &p->context); + swtch(&c->context, p->context); // Process is done running for now. // It should have changed its p->state before coming back. cp = 0; - usegment(); } release(&ptable.lock); } } -// Enter scheduler. Must already hold ptable.lock +// Enter scheduler. Must hold only ptable.lock // and have changed cp->state. void sched(void) { int intena; - if(readeflags()&FL_IF) - panic("sched interruptible"); - if(cp->state == RUNNING) - panic("sched running"); if(!holding(&ptable.lock)) panic("sched ptable.lock"); if(c->ncli != 1) panic("sched locks"); + if(cp->state == RUNNING) + panic("sched running"); + if(readeflags()&FL_IF) + panic("sched interruptible"); intena = c->intena; - swtch(&cp->context, &c->context); + swtch(&cp->context, c->context); c->intena = intena; } @@ -262,7 +256,7 @@ sched(void) void yield(void) { - acquire(&ptable.lock); + acquire(&ptable.lock); //DOC: yieldlock cp->state = RUNNABLE; sched(); release(&ptable.lock); @@ -275,9 +269,8 @@ forkret(void) { // Still holding ptable.lock from scheduler. release(&ptable.lock); - - // Jump into assembly, never to return. - forkret1(cp->tf); + + // Return to "caller", actually trapret (see allocproc). } // Atomically release lock and sleep on chan. diff --git a/swtch.S b/swtch.S index ada98f3..8751317 100644 --- a/swtch.S +++ b/swtch.S @@ -1,5 +1,7 @@ -# void swtch(struct context **old, struct context **new); -# +# Context switch +# +# void swtch(struct context **old, struct context *new); +# # Save current register context in old # and then load register context from new. @@ -16,7 +18,7 @@ swtch: # Switch stacks movl %esp, (%eax) - movl (%edx), %esp + movl %edx, %esp # Load new callee-save registers popl %edi diff --git a/trapasm.S b/trapasm.S index 983163d..1cb2ce6 100644 --- a/trapasm.S +++ b/trapasm.S @@ -35,11 +35,3 @@ trapret: popl %ds addl $0x8, %esp # trapno and errcode iret - - # A forked process switches to user mode by calling - # forkret1(tf), where tf is the trap frame to use. -.globl forkret1 -forkret1: - movl 4(%esp), %esp - jmp trapret -