@@ -15,7 +15,7 @@ static struct proc *initproc;
15
15
16
16
int nextpid = 1 ;
17
17
extern void forkret (void );
18
- extern void forkret1 ( struct trapframe * );
18
+ extern void trapret ( void );
19
19
20
20
void
21
21
pinit (void )
@@ -30,31 +30,39 @@ static struct proc*
30
30
allocproc (void )
31
31
{
32
32
struct proc * p ;
33
+ char * sp ;
33
34
34
35
acquire (& ptable .lock );
35
- for (p = ptable .proc ; p < & ptable .proc [NPROC ]; p ++ ){
36
- if (p -> state == UNUSED ){
37
- p -> state = EMBRYO ;
38
- p -> pid = nextpid ++ ;
36
+ for (p = ptable .proc ; p < & ptable .proc [NPROC ]; p ++ )
37
+ if (p -> state == UNUSED )
39
38
goto found ;
40
- }
41
- }
42
39
release (& ptable .lock );
43
40
return 0 ;
44
41
45
42
found :
43
+ p -> state = EMBRYO ;
44
+ p -> pid = nextpid ++ ;
46
45
release (& ptable .lock );
47
46
48
47
// Allocate kernel stack if necessary.
49
48
if ((p -> kstack = kalloc (KSTACKSIZE )) == 0 ){
50
49
p -> state = UNUSED ;
51
50
return 0 ;
52
51
}
53
- p -> tf = (struct trapframe * )(p -> kstack + KSTACKSIZE ) - 1 ;
54
-
55
- // Set up new context to start executing at forkret (see below).
56
- p -> context = (struct context * )p -> tf - 1 ;
57
- memset (p -> context , 0 , sizeof (* p -> context ));
52
+ sp = p -> kstack + KSTACKSIZE ;
53
+
54
+ // Leave room for trap frame.
55
+ sp -= sizeof * p -> tf ;
56
+ p -> tf = (struct trapframe * )sp ;
57
+
58
+ // Set up new context to start executing at forkret,
59
+ // which returns to trapret (see below).
60
+ sp -= 4 ;
61
+ * (uint * )sp = (uint )trapret ;
62
+
63
+ sp -= sizeof * p -> context ;
64
+ p -> context = (struct context * )sp ;
65
+ memset (p -> context , 0 , sizeof * p -> context );
58
66
p -> context -> eip = (uint )forkret ;
59
67
return p ;
60
68
}
@@ -79,19 +87,16 @@ growproc(int n)
79
87
}
80
88
81
89
// Set up CPU's kernel segment descriptors.
90
+ // Run once at boot time on each CPU.
82
91
void
83
92
ksegment (void )
84
93
{
85
94
struct cpu * c1 ;
86
95
87
96
c1 = & cpus [cpu ()];
88
- c1 -> gdt [0 ] = SEG_NULL ;
89
97
c1 -> gdt [SEG_KCODE ] = SEG (STA_X |STA_R , 0 , 0x100000 + 64 * 1024 - 1 , 0 );
90
98
c1 -> gdt [SEG_KDATA ] = SEG (STA_W , 0 , 0xffffffff , 0 );
91
- c1 -> gdt [SEG_KCPU ] = SEG (STA_W , (uint )& c1 -> tls + sizeof (c1 -> tls ), 0xffffffff , 0 );
92
- c1 -> gdt [SEG_UCODE ] = SEG_NULL ;
93
- c1 -> gdt [SEG_UDATA ] = SEG_NULL ;
94
- c1 -> gdt [SEG_TSS ] = SEG_NULL ;
99
+ c1 -> gdt [SEG_KCPU ] = SEG (STA_W , (uint )(& c1 -> tls + 1 ), 0xffffffff , 0 );
95
100
lgdt (c1 -> gdt , sizeof (c1 -> gdt ));
96
101
loadfsgs (SEG_KCPU << 3 );
97
102
@@ -106,23 +111,12 @@ void
106
111
usegment (void )
107
112
{
108
113
pushcli ();
109
- c -> ts .ss0 = SEG_KDATA << 3 ;
110
- if (cp )
111
- c -> ts .esp0 = (uint )(cp -> kstack + KSTACKSIZE );
112
- else
113
- c -> ts .esp0 = 0xffffffff ;
114
-
115
- if (cp ){
116
- c -> gdt [SEG_UCODE ] = SEG (STA_X |STA_R , (uint )cp -> mem , cp -> sz - 1 , DPL_USER );
117
- c -> gdt [SEG_UDATA ] = SEG (STA_W , (uint )cp -> mem , cp -> sz - 1 , DPL_USER );
118
- } else {
119
- c -> gdt [SEG_UCODE ] = SEG_NULL ;
120
- c -> gdt [SEG_UDATA ] = SEG_NULL ;
121
- }
114
+ c -> gdt [SEG_UCODE ] = SEG (STA_X |STA_R , (uint )cp -> mem , cp -> sz - 1 , DPL_USER );
115
+ c -> gdt [SEG_UDATA ] = SEG (STA_W , (uint )cp -> mem , cp -> sz - 1 , DPL_USER );
122
116
c -> gdt [SEG_TSS ] = SEG16 (STS_T32A , (uint )& c -> ts , sizeof (c -> ts )- 1 , 0 );
123
117
c -> gdt [SEG_TSS ].s = 0 ;
124
-
125
- lgdt ( c -> gdt , sizeof ( c -> gdt )) ;
118
+ c -> ts . ss0 = SEG_KDATA << 3 ;
119
+ c -> ts . esp0 = ( uint ) cp -> kstack + KSTACKSIZE ;
126
120
ltr (SEG_TSS << 3 );
127
121
popcli ();
128
122
}
@@ -171,14 +165,15 @@ void
171
165
userinit (void )
172
166
{
173
167
struct proc * p ;
174
- extern uchar _binary_initcode_start [], _binary_initcode_size [];
168
+ extern char _binary_initcode_start [], _binary_initcode_size [];
175
169
176
170
p = allocproc ();
177
171
initproc = p ;
178
172
179
173
// Initialize memory from initcode.S
180
174
p -> sz = PAGE ;
181
175
p -> mem = kalloc (p -> sz );
176
+ memset (p -> mem , 0 , p -> sz );
182
177
memmove (p -> mem , _binary_initcode_start , (int )_binary_initcode_size );
183
178
184
179
memset (p -> tf , 0 , sizeof (* p -> tf ));
@@ -210,7 +205,7 @@ scheduler(void)
210
205
struct proc * p ;
211
206
212
207
for (;;){
213
- // Enable interrupts on this processor, in lieu of saving intena .
208
+ // Enable interrupts on this processor.
214
209
sti ();
215
210
216
211
// Loop over process table looking for process to run.
@@ -225,44 +220,43 @@ scheduler(void)
225
220
cp = p ;
226
221
usegment ();
227
222
p -> state = RUNNING ;
228
- swtch (& c -> context , & p -> context );
223
+ swtch (& c -> context , p -> context );
229
224
230
225
// Process is done running for now.
231
226
// It should have changed its p->state before coming back.
232
227
cp = 0 ;
233
- usegment ();
234
228
}
235
229
release (& ptable .lock );
236
230
237
231
}
238
232
}
239
233
240
- // Enter scheduler. Must already hold ptable.lock
234
+ // Enter scheduler. Must hold only ptable.lock
241
235
// and have changed cp->state.
242
236
void
243
237
sched (void )
244
238
{
245
239
int intena ;
246
240
247
- if (readeflags ()& FL_IF )
248
- panic ("sched interruptible" );
249
- if (cp -> state == RUNNING )
250
- panic ("sched running" );
251
241
if (!holding (& ptable .lock ))
252
242
panic ("sched ptable.lock" );
253
243
if (c -> ncli != 1 )
254
244
panic ("sched locks" );
245
+ if (cp -> state == RUNNING )
246
+ panic ("sched running" );
247
+ if (readeflags ()& FL_IF )
248
+ panic ("sched interruptible" );
255
249
256
250
intena = c -> intena ;
257
- swtch (& cp -> context , & c -> context );
251
+ swtch (& cp -> context , c -> context );
258
252
c -> intena = intena ;
259
253
}
260
254
261
255
// Give up the CPU for one scheduling round.
262
256
void
263
257
yield (void )
264
258
{
265
- acquire (& ptable .lock );
259
+ acquire (& ptable .lock ); //DOC: yieldlock
266
260
cp -> state = RUNNABLE ;
267
261
sched ();
268
262
release (& ptable .lock );
@@ -275,9 +269,8 @@ forkret(void)
275
269
{
276
270
// Still holding ptable.lock from scheduler.
277
271
release (& ptable .lock );
278
-
279
- // Jump into assembly, never to return.
280
- forkret1 (cp -> tf );
272
+
273
+ // Return to "caller", actually trapret (see allocproc).
281
274
}
282
275
283
276
// Atomically release lock and sleep on chan.
0 commit comments