提交 020c8e23 创建 作者: Robert Morris's avatar Robert Morris

use acquire/release to force order for pid=np->pid;np->state=RUNNING

for bug reported by symingz@gmail.com and cs1100254@cse.iitd.ernet.in
上级 86188d9d
...@@ -116,21 +116,25 @@ processors will need it. ...@@ -116,21 +116,25 @@ processors will need it.
--- ---
The code in fork needs to read np->pid before The code in fork needs to read np->pid before
setting np->state to RUNNABLE. setting np->state to RUNNABLE. The following
is not a correct way to do this:
int int
fork(void) fork(void)
{ {
... ...
pid = np->pid;
np->state = RUNNABLE; np->state = RUNNABLE;
return pid; return np->pid; // oops
} }
After setting np->state to RUNNABLE, some other CPU After setting np->state to RUNNABLE, some other CPU
might run the process, it might exit, and then it might might run the process, it might exit, and then it might
get reused for a different process (with a new pid), all get reused for a different process (with a new pid), all
before the return statement. So it's not safe to just do before the return statement. So it's not safe to just
"return np->pid;". "return np->pid". Even saving a copy of np->pid before
setting np->state isn't safe, since the compiler is
This works because proc.h marks the pid as volatile. allowed to re-order statements.
The real code saves a copy of np->pid, then acquires a lock
around the write to np->state. The acquire() prevents the
compiler from re-ordering.
...@@ -153,10 +153,16 @@ fork(void) ...@@ -153,10 +153,16 @@ fork(void)
if(proc->ofile[i]) if(proc->ofile[i])
np->ofile[i] = filedup(proc->ofile[i]); np->ofile[i] = filedup(proc->ofile[i]);
np->cwd = idup(proc->cwd); np->cwd = idup(proc->cwd);
safestrcpy(np->name, proc->name, sizeof(proc->name));
pid = np->pid; pid = np->pid;
// lock to force the compiler to emit the np->state write last.
acquire(&ptable.lock);
np->state = RUNNABLE; np->state = RUNNABLE;
safestrcpy(np->name, proc->name, sizeof(proc->name)); release(&ptable.lock);
return pid; return pid;
} }
...@@ -455,5 +461,3 @@ procdump(void) ...@@ -455,5 +461,3 @@ procdump(void)
cprintf("\n"); cprintf("\n");
} }
} }
...@@ -57,7 +57,7 @@ struct proc { ...@@ -57,7 +57,7 @@ struct proc {
pde_t* pgdir; // Page table pde_t* pgdir; // Page table
char *kstack; // Bottom of kernel stack for this process char *kstack; // Bottom of kernel stack for this process
enum procstate state; // Process state enum procstate state; // Process state
volatile int pid; // Process ID int pid; // Process ID
struct proc *parent; // Parent process struct proc *parent; // Parent process
struct trapframe *tf; // Trap frame for current syscall struct trapframe *tf; // Trap frame for current syscall
struct context *context; // swtch() here to run process struct context *context; // swtch() here to run process
......
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论