diff --git a/defs.h b/defs.h index 67ea9f6..5e049ae 100644 --- a/defs.h +++ b/defs.h @@ -108,6 +108,7 @@ void exit(void); int fork(void); int growproc(int); int kill(int); +struct proc* myproc(); void pinit(void); void procdump(void); void scheduler(void) __attribute__((noreturn)); diff --git a/exec.c b/exec.c index 14d673f..b40134f 100644 --- a/exec.c +++ b/exec.c @@ -17,6 +17,7 @@ exec(char *path, char **argv) struct inode *ip; struct proghdr ph; pde_t *pgdir, *oldpgdir; + struct proc *curproc = myproc(); begin_op(); @@ -90,15 +91,15 @@ exec(char *path, char **argv) for(last=s=path; *s; s++) if(*s == '/') last = s+1; - safestrcpy(myproc()->name, last, sizeof(myproc()->name)); + safestrcpy(curproc->name, last, sizeof(curproc->name)); // Commit to the user image. - oldpgdir = myproc()->pgdir; - myproc()->pgdir = pgdir; - myproc()->sz = sz; - myproc()->tf->eip = elf.entry; // main - myproc()->tf->esp = sp; - switchuvm(myproc()); + oldpgdir = curproc->pgdir; + curproc->pgdir = pgdir; + curproc->sz = sz; + curproc->tf->eip = elf.entry; // main + curproc->tf->esp = sp; + switchuvm(curproc); freevm(oldpgdir); return 0; diff --git a/proc.c b/proc.c index bd62e4b..4e8f461 100644 --- a/proc.c +++ b/proc.c @@ -26,14 +26,23 @@ pinit(void) initlock(&ptable.lock, "ptable"); } +// XXX get rid off? int cpuid() { return mycpu()-cpus; } -void -setproc(struct proc* p) { - mycpu()->proc = p; +// 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 @@ -130,17 +139,18 @@ int growproc(int n) { uint sz; + struct proc *curproc = myproc(); - sz = myproc()->sz; + sz = curproc->sz; if(n > 0){ - if((sz = allocuvm(myproc()->pgdir, sz, sz + n)) == 0) + if((sz = allocuvm(curproc->pgdir, sz, sz + n)) == 0) return -1; } else if(n < 0){ - if((sz = deallocuvm(myproc()->pgdir, sz, sz + n)) == 0) + if((sz = deallocuvm(curproc->pgdir, sz, sz + n)) == 0) return -1; } - myproc()->sz = sz; - switchuvm(myproc()); + curproc->sz = sz; + switchuvm(curproc); return 0; } @@ -152,6 +162,7 @@ fork(void) { int i, pid; struct proc *np; + struct proc *curproc = myproc(); // Allocate process. if((np = allocproc()) == 0){ @@ -159,25 +170,25 @@ fork(void) } // Copy process state from proc. - if((np->pgdir = copyuvm(myproc()->pgdir, myproc()->sz)) == 0){ + if((np->pgdir = copyuvm(curproc->pgdir, curproc->sz)) == 0){ kfree(np->kstack); np->kstack = 0; np->state = UNUSED; return -1; } - np->sz = myproc()->sz; - np->parent = myproc(); - *np->tf = *myproc()->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(myproc()->ofile[i]) - np->ofile[i] = filedup(myproc()->ofile[i]); - np->cwd = idup(myproc()->cwd); + if(curproc->ofile[i]) + np->ofile[i] = filedup(curproc->ofile[i]); + np->cwd = idup(curproc->cwd); - safestrcpy(np->name, myproc()->name, sizeof(myproc()->name)); + safestrcpy(np->name, curproc->name, sizeof(curproc->name)); pid = np->pid; @@ -196,33 +207,34 @@ fork(void) void exit(void) { + struct proc *curproc = myproc(); struct proc *p; int fd; - if(myproc() == initproc) + if(curproc == initproc) panic("init exiting"); // Close all open files. for(fd = 0; fd < NOFILE; fd++){ - if(myproc()->ofile[fd]){ - fileclose(myproc()->ofile[fd]); - myproc()->ofile[fd] = 0; + if(curproc->ofile[fd]){ + fileclose(curproc->ofile[fd]); + curproc->ofile[fd] = 0; } } begin_op(); - iput(myproc()->cwd); + iput(curproc->cwd); end_op(); - myproc()->cwd = 0; + curproc->cwd = 0; acquire(&ptable.lock); // Parent might be sleeping in wait(). - wakeup1(myproc()->parent); + wakeup1(curproc->parent); // Pass abandoned children to init. for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){ - if(p->parent == myproc()){ + if(p->parent == curproc){ p->parent = initproc; if(p->state == ZOMBIE) wakeup1(initproc); @@ -230,7 +242,7 @@ exit(void) } // Jump into the scheduler, never to return. - myproc()->state = ZOMBIE; + curproc->state = ZOMBIE; sched(); panic("zombie exit"); } @@ -242,13 +254,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 != myproc()) + if(p->parent != curproc) continue; havekids = 1; if(p->state == ZOMBIE){ @@ -268,13 +281,13 @@ wait(void) } // No point waiting if we don't have any children. - if(!havekids || myproc()->killed){ + if(!havekids || curproc->killed){ release(&ptable.lock); return -1; } // Wait for children to exit. (See wakeup1 call in proc_exit.) - sleep(myproc(), &ptable.lock); //DOC: wait-sleep + sleep(curproc, &ptable.lock); //DOC: wait-sleep } } @@ -290,6 +303,7 @@ void scheduler(void) { struct proc *p; + struct cpu *c = mycpu(); for(;;){ // Enable interrupts on this processor. @@ -304,15 +318,18 @@ 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. - setproc(p); + c->proc = p; switchuvm(p); p->state = RUNNING; - swtch(&(mycpu()->scheduler), p->context); + p->cpu = c; + // cprintf("%d: switch to %d\n", c-cpus, p->pid); + swtch(&(p->cpu->scheduler), p->context); switchkvm(); // Process is done running for now. // It should have changed its p->state before coming back. - setproc(0); + c->proc = 0; + p->cpu = 0; } release(&ptable.lock); @@ -330,17 +347,20 @@ void sched(void) { int intena; + struct proc *p = myproc(); if(!holding(&ptable.lock)) panic("sched ptable.lock"); if(mycpu()->ncli != 1) panic("sched locks"); - if(myproc()->state == RUNNING) + if(p->state == RUNNING) panic("sched running"); if(readeflags()&FL_IF) panic("sched interruptible"); intena = mycpu()->intena; - swtch(&myproc()->context, mycpu()->scheduler); + // cprintf("%d: before swtch %d %x\n", p->cpu-cpus, p->pid, * (int *) 0x1d); + swtch(&p->context, p->cpu->scheduler); + // cprintf("%d/%d: after swtch %d %x\n", cpuid(), p->cpu-cpus, p->pid, * (int *) 0x1d); mycpu()->intena = intena; } @@ -380,7 +400,9 @@ forkret(void) void sleep(void *chan, struct spinlock *lk) { - if(myproc() == 0) + struct proc *p = myproc(); + + if(p == 0) panic("sleep"); if(lk == 0) @@ -397,12 +419,15 @@ sleep(void *chan, struct spinlock *lk) release(lk); } // Go to sleep. - myproc()->chan = chan; - myproc()->state = SLEEPING; + p->chan = chan; + p->state = SLEEPING; + + // cprintf("sleep %d\n", p->pid); + sched(); // Tidy up. - myproc()->chan = 0; + p->chan = 0; // Reacquire original lock. if(lk != &ptable.lock){ //DOC: sleeplock2 diff --git a/proc.h b/proc.h index 38a2d32..7047d54 100644 --- a/proc.h +++ b/proc.h @@ -30,12 +30,14 @@ mycpu(void) { return cpu; } +#if 0 static inline struct proc* myproc(void) { struct proc *proc; asm("movl %%gs:4, %0" : "=r"(proc)); return proc; } +#endif //PAGEBREAK: 17 @@ -74,6 +76,7 @@ struct proc { struct file *ofile[NOFILE]; // Open files struct inode *cwd; // Current directory char name[16]; // Process name (debugging) + struct cpu *cpu; // If running, which cpu. }; // Process memory is laid out contiguously, low addresses first: diff --git a/syscall.c b/syscall.c index 2d6769e..ee85261 100644 --- a/syscall.c +++ b/syscall.c @@ -17,7 +17,9 @@ int fetchint(uint addr, int *ip) { - if(addr >= myproc()->sz || addr+4 > myproc()->sz) + struct proc *curproc = myproc(); + + if(addr >= curproc->sz || addr+4 > curproc->sz) return -1; *ip = *(int*)(addr); return 0; @@ -30,11 +32,12 @@ int fetchstr(uint addr, char **pp) { char *s, *ep; + struct proc *curproc = myproc(); - if(addr >= myproc()->sz) + if(addr >= curproc->sz) return -1; *pp = (char*)addr; - ep = (char*)myproc()->sz; + ep = (char*)curproc->sz; for(s = *pp; s < ep; s++){ if(*s == 0) return s - *pp; @@ -56,10 +59,11 @@ int argptr(int n, char **pp, int size) { int i; - + struct proc *curproc = myproc(); + if(argint(n, &i) < 0) return -1; - if(size < 0 || (uint)i >= myproc()->sz || (uint)i+size > myproc()->sz) + if(size < 0 || (uint)i >= curproc->sz || (uint)i+size > curproc->sz) return -1; *pp = (char*)i; return 0; @@ -128,13 +132,14 @@ void syscall(void) { int num; + struct proc *curproc = myproc(); - num = myproc()->tf->eax; + num = curproc->tf->eax; if(num > 0 && num < NELEM(syscalls) && syscalls[num]) { - myproc()->tf->eax = syscalls[num](); + curproc->tf->eax = syscalls[num](); } else { cprintf("%d %s: unknown sys call %d\n", - myproc()->pid, myproc()->name, num); - myproc()->tf->eax = -1; + curproc->pid, curproc->name, num); + curproc->tf->eax = -1; } } diff --git a/sysfile.c b/sysfile.c index fae6960..87e508b 100644 --- a/sysfile.c +++ b/sysfile.c @@ -41,10 +41,11 @@ static int fdalloc(struct file *f) { int fd; + struct proc *curproc = myproc(); for(fd = 0; fd < NOFILE; fd++){ - if(myproc()->ofile[fd] == 0){ - myproc()->ofile[fd] = f; + if(curproc->ofile[fd] == 0){ + curproc->ofile[fd] = f; return fd; } } @@ -373,7 +374,8 @@ sys_chdir(void) { char *path; struct inode *ip; - + struct proc *curproc = myproc(); + begin_op(); if(argstr(0, &path) < 0 || (ip = namei(path)) == 0){ end_op(); @@ -386,9 +388,9 @@ sys_chdir(void) return -1; } iunlock(ip); - iput(myproc()->cwd); + iput(curproc->cwd); end_op(); - myproc()->cwd = ip; + curproc->cwd = ip; return 0; } diff --git a/vm.c b/vm.c index cb159ad..d1640e8 100644 --- a/vm.c +++ b/vm.c @@ -27,13 +27,11 @@ seginit(void) c->gdt[SEG_UCODE] = SEG(STA_X|STA_R, 0, 0xffffffff, DPL_USER); c->gdt[SEG_UDATA] = SEG(STA_W, 0, 0xffffffff, DPL_USER); c->cpu = c; + c->proc = 0; // Map cpu and proc -- these are private per cpu. c->gdt[SEG_KCPU] = SEG(STA_W, &c->cpu, 4, 0); lgdt(c->gdt, sizeof(c->gdt)); loadgs(SEG_KCPU << 3); - // Initialize cpu-local storage. - // setcpu(c); - setproc(0); } // Return the address of the PTE in page table pgdir