File tree 3 files changed +19
-11
lines changed
3 files changed +19
-11
lines changed Original file line number Diff line number Diff line change @@ -116,21 +116,25 @@ processors will need it.
116
116
---
117
117
118
118
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:
120
121
121
122
int
122
123
fork(void)
123
124
{
124
125
...
125
- pid = np->pid;
126
126
np->state = RUNNABLE;
127
- return pid;
127
+ return np-> pid; // oops
128
128
}
129
129
130
130
After setting np->state to RUNNABLE, some other CPU
131
131
might run the process, it might exit, and then it might
132
132
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.
Original file line number Diff line number Diff line change @@ -153,10 +153,16 @@ fork(void)
153
153
if (proc -> ofile [i ])
154
154
np -> ofile [i ] = filedup (proc -> ofile [i ]);
155
155
np -> cwd = idup (proc -> cwd );
156
+
157
+ safestrcpy (np -> name , proc -> name , sizeof (proc -> name ));
156
158
157
159
pid = np -> pid ;
160
+
161
+ // lock to force the compiler to emit the np->state write last.
162
+ acquire (& ptable .lock );
158
163
np -> state = RUNNABLE ;
159
- safestrcpy (np -> name , proc -> name , sizeof (proc -> name ));
164
+ release (& ptable .lock );
165
+
160
166
return pid ;
161
167
}
162
168
@@ -455,5 +461,3 @@ procdump(void)
455
461
cprintf ("\n" );
456
462
}
457
463
}
458
-
459
-
Original file line number Diff line number Diff line change @@ -57,7 +57,7 @@ struct proc {
57
57
pde_t * pgdir ; // Page table
58
58
char * kstack ; // Bottom of kernel stack for this process
59
59
enum procstate state ; // Process state
60
- volatile int pid ; // Process ID
60
+ int pid ; // Process ID
61
61
struct proc * parent ; // Parent process
62
62
struct trapframe * tf ; // Trap frame for current syscall
63
63
struct context * context ; // swtch() here to run process
You can’t perform that action at this time.
0 commit comments