Read curproc from cpu structure, but be careful because after a schedule event

myproc() points to a different thread.

   myproc();
   sched();
   myproc();  // this proc maybe different than the one before sched

Thus, in a function that operates on one thread better to retrieve the
current process once at the start of the function.
This commit is contained in:
Frans Kaashoek 2017-01-31 20:21:14 -05:00
parent abf847a083
commit fbb4c09444
7 changed files with 97 additions and 62 deletions

1
defs.h
View file

@ -108,6 +108,7 @@ void exit(void);
int fork(void); int fork(void);
int growproc(int); int growproc(int);
int kill(int); int kill(int);
struct proc* myproc();
void pinit(void); void pinit(void);
void procdump(void); void procdump(void);
void scheduler(void) __attribute__((noreturn)); void scheduler(void) __attribute__((noreturn));

15
exec.c
View file

@ -17,6 +17,7 @@ exec(char *path, char **argv)
struct inode *ip; struct inode *ip;
struct proghdr ph; struct proghdr ph;
pde_t *pgdir, *oldpgdir; pde_t *pgdir, *oldpgdir;
struct proc *curproc = myproc();
begin_op(); begin_op();
@ -90,15 +91,15 @@ exec(char *path, char **argv)
for(last=s=path; *s; s++) for(last=s=path; *s; s++)
if(*s == '/') if(*s == '/')
last = s+1; last = s+1;
safestrcpy(myproc()->name, last, sizeof(myproc()->name)); safestrcpy(curproc->name, last, sizeof(curproc->name));
// Commit to the user image. // Commit to the user image.
oldpgdir = myproc()->pgdir; oldpgdir = curproc->pgdir;
myproc()->pgdir = pgdir; curproc->pgdir = pgdir;
myproc()->sz = sz; curproc->sz = sz;
myproc()->tf->eip = elf.entry; // main curproc->tf->eip = elf.entry; // main
myproc()->tf->esp = sp; curproc->tf->esp = sp;
switchuvm(myproc()); switchuvm(curproc);
freevm(oldpgdir); freevm(oldpgdir);
return 0; return 0;

99
proc.c
View file

@ -26,14 +26,23 @@ pinit(void)
initlock(&ptable.lock, "ptable"); initlock(&ptable.lock, "ptable");
} }
// XXX get rid off?
int int
cpuid() { cpuid() {
return mycpu()-cpus; return mycpu()-cpus;
} }
void // Disable interrupts so that we are not rescheduled
setproc(struct proc* p) { // while reading proc from the cpu structure
mycpu()->proc = p; struct proc*
myproc(void) {
struct cpu *c;
struct proc *p;
pushcli();
c = mycpu();
p = c->proc;
popcli();
return p;
} }
//PAGEBREAK: 32 //PAGEBREAK: 32
@ -130,17 +139,18 @@ int
growproc(int n) growproc(int n)
{ {
uint sz; uint sz;
struct proc *curproc = myproc();
sz = myproc()->sz; sz = curproc->sz;
if(n > 0){ if(n > 0){
if((sz = allocuvm(myproc()->pgdir, sz, sz + n)) == 0) if((sz = allocuvm(curproc->pgdir, sz, sz + n)) == 0)
return -1; return -1;
} else if(n < 0){ } else if(n < 0){
if((sz = deallocuvm(myproc()->pgdir, sz, sz + n)) == 0) if((sz = deallocuvm(curproc->pgdir, sz, sz + n)) == 0)
return -1; return -1;
} }
myproc()->sz = sz; curproc->sz = sz;
switchuvm(myproc()); switchuvm(curproc);
return 0; return 0;
} }
@ -152,6 +162,7 @@ fork(void)
{ {
int i, pid; int i, pid;
struct proc *np; struct proc *np;
struct proc *curproc = myproc();
// Allocate process. // Allocate process.
if((np = allocproc()) == 0){ if((np = allocproc()) == 0){
@ -159,25 +170,25 @@ fork(void)
} }
// Copy process state from proc. // 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); kfree(np->kstack);
np->kstack = 0; np->kstack = 0;
np->state = UNUSED; np->state = UNUSED;
return -1; return -1;
} }
np->sz = myproc()->sz; np->sz = curproc->sz;
np->parent = myproc(); np->parent = curproc;
*np->tf = *myproc()->tf; *np->tf = *curproc->tf;
// Clear %eax so that fork returns 0 in the child. // Clear %eax so that fork returns 0 in the child.
np->tf->eax = 0; np->tf->eax = 0;
for(i = 0; i < NOFILE; i++) for(i = 0; i < NOFILE; i++)
if(myproc()->ofile[i]) if(curproc->ofile[i])
np->ofile[i] = filedup(myproc()->ofile[i]); np->ofile[i] = filedup(curproc->ofile[i]);
np->cwd = idup(myproc()->cwd); np->cwd = idup(curproc->cwd);
safestrcpy(np->name, myproc()->name, sizeof(myproc()->name)); safestrcpy(np->name, curproc->name, sizeof(curproc->name));
pid = np->pid; pid = np->pid;
@ -196,33 +207,34 @@ fork(void)
void void
exit(void) exit(void)
{ {
struct proc *curproc = myproc();
struct proc *p; struct proc *p;
int fd; int fd;
if(myproc() == initproc) if(curproc == initproc)
panic("init exiting"); panic("init exiting");
// Close all open files. // Close all open files.
for(fd = 0; fd < NOFILE; fd++){ for(fd = 0; fd < NOFILE; fd++){
if(myproc()->ofile[fd]){ if(curproc->ofile[fd]){
fileclose(myproc()->ofile[fd]); fileclose(curproc->ofile[fd]);
myproc()->ofile[fd] = 0; curproc->ofile[fd] = 0;
} }
} }
begin_op(); begin_op();
iput(myproc()->cwd); iput(curproc->cwd);
end_op(); end_op();
myproc()->cwd = 0; curproc->cwd = 0;
acquire(&ptable.lock); acquire(&ptable.lock);
// Parent might be sleeping in wait(). // Parent might be sleeping in wait().
wakeup1(myproc()->parent); wakeup1(curproc->parent);
// Pass abandoned children to init. // Pass abandoned children to init.
for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){ for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){
if(p->parent == myproc()){ if(p->parent == curproc){
p->parent = initproc; p->parent = initproc;
if(p->state == ZOMBIE) if(p->state == ZOMBIE)
wakeup1(initproc); wakeup1(initproc);
@ -230,7 +242,7 @@ exit(void)
} }
// Jump into the scheduler, never to return. // Jump into the scheduler, never to return.
myproc()->state = ZOMBIE; curproc->state = ZOMBIE;
sched(); sched();
panic("zombie exit"); panic("zombie exit");
} }
@ -242,13 +254,14 @@ wait(void)
{ {
struct proc *p; struct proc *p;
int havekids, pid; int havekids, pid;
struct proc *curproc = myproc();
acquire(&ptable.lock); acquire(&ptable.lock);
for(;;){ for(;;){
// Scan through table looking for exited children. // Scan through table looking for exited children.
havekids = 0; havekids = 0;
for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){ for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){
if(p->parent != myproc()) if(p->parent != curproc)
continue; continue;
havekids = 1; havekids = 1;
if(p->state == ZOMBIE){ if(p->state == ZOMBIE){
@ -268,13 +281,13 @@ wait(void)
} }
// No point waiting if we don't have any children. // No point waiting if we don't have any children.
if(!havekids || myproc()->killed){ if(!havekids || curproc->killed){
release(&ptable.lock); release(&ptable.lock);
return -1; return -1;
} }
// Wait for children to exit. (See wakeup1 call in proc_exit.) // 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) scheduler(void)
{ {
struct proc *p; struct proc *p;
struct cpu *c = mycpu();
for(;;){ for(;;){
// Enable interrupts on this processor. // Enable interrupts on this processor.
@ -304,15 +318,18 @@ scheduler(void)
// Switch to chosen process. It is the process's job // Switch to chosen process. It is the process's job
// to release ptable.lock and then reacquire it // to release ptable.lock and then reacquire it
// before jumping back to us. // before jumping back to us.
setproc(p); c->proc = p;
switchuvm(p); switchuvm(p);
p->state = RUNNING; 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(); switchkvm();
// 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.
setproc(0); c->proc = 0;
p->cpu = 0;
} }
release(&ptable.lock); release(&ptable.lock);
@ -330,17 +347,20 @@ void
sched(void) sched(void)
{ {
int intena; int intena;
struct proc *p = myproc();
if(!holding(&ptable.lock)) if(!holding(&ptable.lock))
panic("sched ptable.lock"); panic("sched ptable.lock");
if(mycpu()->ncli != 1) if(mycpu()->ncli != 1)
panic("sched locks"); panic("sched locks");
if(myproc()->state == RUNNING) if(p->state == RUNNING)
panic("sched running"); panic("sched running");
if(readeflags()&FL_IF) if(readeflags()&FL_IF)
panic("sched interruptible"); panic("sched interruptible");
intena = mycpu()->intena; 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; mycpu()->intena = intena;
} }
@ -380,7 +400,9 @@ forkret(void)
void void
sleep(void *chan, struct spinlock *lk) sleep(void *chan, struct spinlock *lk)
{ {
if(myproc() == 0) struct proc *p = myproc();
if(p == 0)
panic("sleep"); panic("sleep");
if(lk == 0) if(lk == 0)
@ -397,12 +419,15 @@ sleep(void *chan, struct spinlock *lk)
release(lk); release(lk);
} }
// Go to sleep. // Go to sleep.
myproc()->chan = chan; p->chan = chan;
myproc()->state = SLEEPING; p->state = SLEEPING;
// cprintf("sleep %d\n", p->pid);
sched(); sched();
// Tidy up. // Tidy up.
myproc()->chan = 0; p->chan = 0;
// Reacquire original lock. // Reacquire original lock.
if(lk != &ptable.lock){ //DOC: sleeplock2 if(lk != &ptable.lock){ //DOC: sleeplock2

3
proc.h
View file

@ -30,12 +30,14 @@ mycpu(void) {
return cpu; return cpu;
} }
#if 0
static inline struct proc* static inline struct proc*
myproc(void) { myproc(void) {
struct proc *proc; struct proc *proc;
asm("movl %%gs:4, %0" : "=r"(proc)); asm("movl %%gs:4, %0" : "=r"(proc));
return proc; return proc;
} }
#endif
//PAGEBREAK: 17 //PAGEBREAK: 17
@ -74,6 +76,7 @@ struct proc {
struct file *ofile[NOFILE]; // Open files struct file *ofile[NOFILE]; // Open files
struct inode *cwd; // Current directory struct inode *cwd; // Current directory
char name[16]; // Process name (debugging) char name[16]; // Process name (debugging)
struct cpu *cpu; // If running, which cpu.
}; };
// Process memory is laid out contiguously, low addresses first: // Process memory is laid out contiguously, low addresses first:

View file

@ -17,7 +17,9 @@
int int
fetchint(uint addr, int *ip) 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; return -1;
*ip = *(int*)(addr); *ip = *(int*)(addr);
return 0; return 0;
@ -30,11 +32,12 @@ int
fetchstr(uint addr, char **pp) fetchstr(uint addr, char **pp)
{ {
char *s, *ep; char *s, *ep;
struct proc *curproc = myproc();
if(addr >= myproc()->sz) if(addr >= curproc->sz)
return -1; return -1;
*pp = (char*)addr; *pp = (char*)addr;
ep = (char*)myproc()->sz; ep = (char*)curproc->sz;
for(s = *pp; s < ep; s++){ for(s = *pp; s < ep; s++){
if(*s == 0) if(*s == 0)
return s - *pp; return s - *pp;
@ -56,10 +59,11 @@ int
argptr(int n, char **pp, int size) argptr(int n, char **pp, int size)
{ {
int i; int i;
struct proc *curproc = myproc();
if(argint(n, &i) < 0) if(argint(n, &i) < 0)
return -1; 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; return -1;
*pp = (char*)i; *pp = (char*)i;
return 0; return 0;
@ -128,13 +132,14 @@ void
syscall(void) syscall(void)
{ {
int num; int num;
struct proc *curproc = myproc();
num = myproc()->tf->eax; num = curproc->tf->eax;
if(num > 0 && num < NELEM(syscalls) && syscalls[num]) { if(num > 0 && num < NELEM(syscalls) && syscalls[num]) {
myproc()->tf->eax = syscalls[num](); curproc->tf->eax = syscalls[num]();
} else { } else {
cprintf("%d %s: unknown sys call %d\n", cprintf("%d %s: unknown sys call %d\n",
myproc()->pid, myproc()->name, num); curproc->pid, curproc->name, num);
myproc()->tf->eax = -1; curproc->tf->eax = -1;
} }
} }

View file

@ -41,10 +41,11 @@ static int
fdalloc(struct file *f) fdalloc(struct file *f)
{ {
int fd; int fd;
struct proc *curproc = myproc();
for(fd = 0; fd < NOFILE; fd++){ for(fd = 0; fd < NOFILE; fd++){
if(myproc()->ofile[fd] == 0){ if(curproc->ofile[fd] == 0){
myproc()->ofile[fd] = f; curproc->ofile[fd] = f;
return fd; return fd;
} }
} }
@ -373,6 +374,7 @@ sys_chdir(void)
{ {
char *path; char *path;
struct inode *ip; struct inode *ip;
struct proc *curproc = myproc();
begin_op(); begin_op();
if(argstr(0, &path) < 0 || (ip = namei(path)) == 0){ if(argstr(0, &path) < 0 || (ip = namei(path)) == 0){
@ -386,9 +388,9 @@ sys_chdir(void)
return -1; return -1;
} }
iunlock(ip); iunlock(ip);
iput(myproc()->cwd); iput(curproc->cwd);
end_op(); end_op();
myproc()->cwd = ip; curproc->cwd = ip;
return 0; return 0;
} }

4
vm.c
View file

@ -27,13 +27,11 @@ seginit(void)
c->gdt[SEG_UCODE] = SEG(STA_X|STA_R, 0, 0xffffffff, DPL_USER); 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->gdt[SEG_UDATA] = SEG(STA_W, 0, 0xffffffff, DPL_USER);
c->cpu = c; c->cpu = c;
c->proc = 0;
// Map cpu and proc -- these are private per cpu. // Map cpu and proc -- these are private per cpu.
c->gdt[SEG_KCPU] = SEG(STA_W, &c->cpu, 4, 0); c->gdt[SEG_KCPU] = SEG(STA_W, &c->cpu, 4, 0);
lgdt(c->gdt, sizeof(c->gdt)); lgdt(c->gdt, sizeof(c->gdt));
loadgs(SEG_KCPU << 3); loadgs(SEG_KCPU << 3);
// Initialize cpu-local storage.
// setcpu(c);
setproc(0);
} }
// Return the address of the PTE in page table pgdir // Return the address of the PTE in page table pgdir