Skip to content

Commit 020c8e2

Browse files
author
Robert Morris
committedAug 4, 2014
use acquire/release to force order for pid=np->pid;np->state=RUNNING
for bug reported by [email protected] and [email protected]
1 parent 86188d9 commit 020c8e2

File tree

3 files changed

+19
-11
lines changed

3 files changed

+19
-11
lines changed
 

‎TRICKS

+11-7
Original file line numberDiff line numberDiff line change
@@ -116,21 +116,25 @@ processors will need it.
116116
---
117117

118118
The code in fork needs to read np->pid before
119-
setting np->state to RUNNABLE.
119+
setting np->state to RUNNABLE. The following
120+
is not a correct way to do this:
120121

121122
int
122123
fork(void)
123124
{
124125
...
125-
pid = np->pid;
126126
np->state = RUNNABLE;
127-
return pid;
127+
return np->pid; // oops
128128
}
129129

130130
After setting np->state to RUNNABLE, some other CPU
131131
might run the process, it might exit, and then it might
132132
get reused for a different process (with a new pid), all
133-
before the return statement. So it's not safe to just do
134-
"return np->pid;".
135-
136-
This works because proc.h marks the pid as volatile.
133+
before the return statement. So it's not safe to just
134+
"return np->pid". Even saving a copy of np->pid before
135+
setting np->state isn't safe, since the compiler is
136+
allowed to re-order statements.
137+
138+
The real code saves a copy of np->pid, then acquires a lock
139+
around the write to np->state. The acquire() prevents the
140+
compiler from re-ordering.

‎proc.c

+7-3
Original file line numberDiff line numberDiff line change
@@ -153,10 +153,16 @@ fork(void)
153153
if(proc->ofile[i])
154154
np->ofile[i] = filedup(proc->ofile[i]);
155155
np->cwd = idup(proc->cwd);
156+
157+
safestrcpy(np->name, proc->name, sizeof(proc->name));
156158

157159
pid = np->pid;
160+
161+
// lock to force the compiler to emit the np->state write last.
162+
acquire(&ptable.lock);
158163
np->state = RUNNABLE;
159-
safestrcpy(np->name, proc->name, sizeof(proc->name));
164+
release(&ptable.lock);
165+
160166
return pid;
161167
}
162168

@@ -455,5 +461,3 @@ procdump(void)
455461
cprintf("\n");
456462
}
457463
}
458-
459-

‎proc.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ struct proc {
5757
pde_t* pgdir; // Page table
5858
char *kstack; // Bottom of kernel stack for this process
5959
enum procstate state; // Process state
60-
volatile int pid; // Process ID
60+
int pid; // Process ID
6161
struct proc *parent; // Parent process
6262
struct trapframe *tf; // Trap frame for current syscall
6363
struct context *context; // swtch() here to run process

0 commit comments

Comments
 (0)
Please sign in to comment.