diff options
Diffstat (limited to 'proc.c')
-rw-r--r-- | proc.c | 133 |
1 files changed, 91 insertions, 42 deletions
@@ -26,6 +26,45 @@ pinit(void) initlock(&ptable.lock, "ptable"); } +// Must be called with interrupts disabled +int +cpuid() { + return mycpu()-cpus; +} + +// Must be called with interrupts disabled to avoid the caller being rescheduled +// between reading lapicid and running through the loop. +struct cpu* +mycpu(void) +{ + int apicid, i; + + if(readeflags()&FL_IF) + panic("mycpu called with interrupts enabled\n"); + + apicid = lapicid(); + // APIC IDs are not guaranteed to be contiguous. Maybe we should have + // a reverse map, or reserve a register to store &cpus[i]. + for (i = 0; i < ncpu; ++i) { + if (cpus[i].apicid == apicid) + return &cpus[i]; + } + panic("unknown apicid\n"); +} + +// Disable interrupts so that we are not rescheduled +// while reading proc from the cpu structure +struct proc* +myproc(void) { + struct cpu *c; + struct proc *p; + pushcli(); + c = mycpu(); + p = c->proc; + popcli(); + return p; +} + //PAGEBREAK: 32 // Look in the process table for an UNUSED proc. // If found, change state to EMBRYO and initialize @@ -120,17 +159,18 @@ int growproc(int n) { uint sz; + struct proc *curproc = myproc(); - sz = proc->sz; + sz = curproc->sz; if(n > 0){ - if((sz = allocuvm(proc->pgdir, sz, sz + n)) == 0) + if((sz = allocuvm(curproc->pgdir, sz, sz + n)) == 0) return -1; } else if(n < 0){ - if((sz = deallocuvm(proc->pgdir, sz, sz + n)) == 0) + if((sz = deallocuvm(curproc->pgdir, sz, sz + n)) == 0) return -1; } - proc->sz = sz; - switchuvm(proc); + curproc->sz = sz; + switchuvm(curproc); return 0; } @@ -142,32 +182,33 @@ fork(void) { int i, pid; struct proc *np; + struct proc *curproc = myproc(); // Allocate process. if((np = allocproc()) == 0){ return -1; } - // Copy process state from p. - if((np->pgdir = copyuvm(proc->pgdir, proc->sz)) == 0){ + // Copy process state from proc. + if((np->pgdir = copyuvm(curproc->pgdir, curproc->sz)) == 0){ kfree(np->kstack); np->kstack = 0; np->state = UNUSED; return -1; } - np->sz = proc->sz; - np->parent = proc; - *np->tf = *proc->tf; + np->sz = curproc->sz; + np->parent = curproc; + *np->tf = *curproc->tf; // Clear %eax so that fork returns 0 in the child. np->tf->eax = 0; for(i = 0; i < NOFILE; i++) - if(proc->ofile[i]) - np->ofile[i] = filedup(proc->ofile[i]); - np->cwd = idup(proc->cwd); + if(curproc->ofile[i]) + np->ofile[i] = filedup(curproc->ofile[i]); + np->cwd = idup(curproc->cwd); - safestrcpy(np->name, proc->name, sizeof(proc->name)); + safestrcpy(np->name, curproc->name, sizeof(curproc->name)); pid = np->pid; @@ -186,33 +227,34 @@ fork(void) void exit(void) { + struct proc *curproc = myproc(); struct proc *p; int fd; - if(proc == initproc) + if(curproc == initproc) panic("init exiting"); // Close all open files. for(fd = 0; fd < NOFILE; fd++){ - if(proc->ofile[fd]){ - fileclose(proc->ofile[fd]); - proc->ofile[fd] = 0; + if(curproc->ofile[fd]){ + fileclose(curproc->ofile[fd]); + curproc->ofile[fd] = 0; } } begin_op(); - iput(proc->cwd); + iput(curproc->cwd); end_op(); - proc->cwd = 0; + curproc->cwd = 0; acquire(&ptable.lock); // Parent might be sleeping in wait(). - wakeup1(proc->parent); + wakeup1(curproc->parent); // Pass abandoned children to init. for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){ - if(p->parent == proc){ + if(p->parent == curproc){ p->parent = initproc; if(p->state == ZOMBIE) wakeup1(initproc); @@ -220,7 +262,7 @@ exit(void) } // Jump into the scheduler, never to return. - proc->state = ZOMBIE; + curproc->state = ZOMBIE; sched(); panic("zombie exit"); } @@ -232,13 +274,14 @@ wait(void) { struct proc *p; int havekids, pid; - + struct proc *curproc = myproc(); + acquire(&ptable.lock); for(;;){ // Scan through table looking for exited children. havekids = 0; for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){ - if(p->parent != proc) + if(p->parent != curproc) continue; havekids = 1; if(p->state == ZOMBIE){ @@ -258,13 +301,13 @@ wait(void) } // No point waiting if we don't have any children. - if(!havekids || proc->killed){ + if(!havekids || curproc->killed){ release(&ptable.lock); return -1; } // Wait for children to exit. (See wakeup1 call in proc_exit.) - sleep(proc, &ptable.lock); //DOC: wait-sleep + sleep(curproc, &ptable.lock); //DOC: wait-sleep } } @@ -280,7 +323,9 @@ void scheduler(void) { struct proc *p; - + struct cpu *c = mycpu(); + c->proc = 0; + for(;;){ // Enable interrupts on this processor. sti(); @@ -294,15 +339,16 @@ scheduler(void) // Switch to chosen process. It is the process's job // to release ptable.lock and then reacquire it // before jumping back to us. - proc = p; + c->proc = p; switchuvm(p); p->state = RUNNING; - swtch(&cpu->scheduler, p->context); + + swtch(&(c->scheduler), p->context); switchkvm(); // Process is done running for now. // It should have changed its p->state before coming back. - proc = 0; + c->proc = 0; } release(&ptable.lock); @@ -320,18 +366,19 @@ void sched(void) { int intena; + struct proc *p = myproc(); if(!holding(&ptable.lock)) panic("sched ptable.lock"); - if(cpu->ncli != 1) + if(mycpu()->ncli != 1) panic("sched locks"); - if(proc->state == RUNNING) + if(p->state == RUNNING) panic("sched running"); if(readeflags()&FL_IF) panic("sched interruptible"); - intena = cpu->intena; - swtch(&proc->context, cpu->scheduler); - cpu->intena = intena; + intena = mycpu()->intena; + swtch(&p->context, mycpu()->scheduler); + mycpu()->intena = intena; } // Give up the CPU for one scheduling round. @@ -339,7 +386,7 @@ void yield(void) { acquire(&ptable.lock); //DOC: yieldlock - proc->state = RUNNABLE; + myproc()->state = RUNNABLE; sched(); release(&ptable.lock); } @@ -370,7 +417,9 @@ forkret(void) void sleep(void *chan, struct spinlock *lk) { - if(proc == 0) + struct proc *p = myproc(); + + if(p == 0) panic("sleep"); if(lk == 0) @@ -386,14 +435,14 @@ sleep(void *chan, struct spinlock *lk) acquire(&ptable.lock); //DOC: sleeplock1 release(lk); } - // Go to sleep. - proc->chan = chan; - proc->state = SLEEPING; + p->chan = chan; + p->state = SLEEPING; + sched(); // Tidy up. - proc->chan = 0; + p->chan = 0; // Reacquire original lock. if(lk != &ptable.lock){ //DOC: sleeplock2 |