summaryrefslogtreecommitdiff
path: root/proc.c
diff options
context:
space:
mode:
Diffstat (limited to 'proc.c')
-rw-r--r--proc.c133
1 files changed, 91 insertions, 42 deletions
diff --git a/proc.c b/proc.c
index 7d03ad7..aac7523 100644
--- a/proc.c
+++ b/proc.c
@@ -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