This source file includes following definitions.
- pinit
- cpuid
- mycpu
- myproc
- allocproc
- userinit
- growproc
- fork
- exit
- wait
- scheduler
- sched
- yield
- forkret
- sleep
- wakeup1
- wakeup
- kill
- procdump
1 #include "types.h"
2 #include "defs.h"
3 #include "param.h"
4 #include "memlayout.h"
5 #include "mmu.h"
6 #include "x86.h"
7 #include "proc.h"
8 #include "spinlock.h"
9
10 struct {
11 struct spinlock lock;
12 struct proc proc[NPROC];
13 } ptable;
14
15 static struct proc *initproc;
16
17 int nextpid = 1;
18 extern void forkret(void);
19 extern void trapret(void);
20
21 static void wakeup1(void *chan);
22
23 void
24 pinit(void)
25 {
26 initlock(&ptable.lock, "ptable");
27 }
28
29
30 int
31 cpuid() {
32 return mycpu()-cpus;
33 }
34
35
36
37 struct cpu*
38 mycpu(void)
39 {
40 int apicid, i;
41
42 if(readeflags()&FL_IF)
43 panic("mycpu called with interrupts enabled\n");
44
45 apicid = lapicid();
46
47
48 for (i = 0; i < ncpu; ++i) {
49 if (cpus[i].apicid == apicid)
50 return &cpus[i];
51 }
52 panic("unknown apicid\n");
53 }
54
55
56
57 struct proc*
58 myproc(void) {
59 struct cpu *c;
60 struct proc *p;
61 pushcli();
62 c = mycpu();
63 p = c->proc;
64 popcli();
65 return p;
66 }
67
68
69
70
71
72
73 static struct proc*
74 allocproc(void)
75 {
76 struct proc *p;
77 char *sp;
78
79 acquire(&ptable.lock);
80
81 for(p = ptable.proc; p < &ptable.proc[NPROC]; p++)
82 if(p->state == UNUSED)
83 goto found;
84
85 release(&ptable.lock);
86 return 0;
87
88 found:
89 p->state = EMBRYO;
90 p->pid = nextpid++;
91
92 release(&ptable.lock);
93
94
95 if((p->kstack = kalloc()) == 0){
96 p->state = UNUSED;
97 return 0;
98 }
99 sp = p->kstack + KSTACKSIZE;
100
101
102 sp -= sizeof *p->tf;
103 p->tf = (struct trapframe*)sp;
104
105
106
107 sp -= 4;
108 *(uint*)sp = (uint)trapret;
109
110 sp -= sizeof *p->context;
111 p->context = (struct context*)sp;
112 memset(p->context, 0, sizeof *p->context);
113 p->context->eip = (uint)forkret;
114
115 return p;
116 }
117
118
119
120 void
121 userinit(void)
122 {
123 struct proc *p;
124 extern char _binary_initcode_start[], _binary_initcode_size[];
125
126 p = allocproc();
127
128 initproc = p;
129 if((p->pgdir = setupkvm()) == 0)
130 panic("userinit: out of memory?");
131 inituvm(p->pgdir, _binary_initcode_start, (int)_binary_initcode_size);
132 p->sz = PGSIZE;
133 memset(p->tf, 0, sizeof(*p->tf));
134 p->tf->cs = (SEG_UCODE << 3) | DPL_USER;
135 p->tf->ds = (SEG_UDATA << 3) | DPL_USER;
136 p->tf->es = p->tf->ds;
137 p->tf->ss = p->tf->ds;
138 p->tf->eflags = FL_IF;
139 p->tf->esp = PGSIZE;
140 p->tf->eip = 0;
141
142 safestrcpy(p->name, "initcode", sizeof(p->name));
143 p->cwd = namei("/");
144
145
146
147
148
149 acquire(&ptable.lock);
150
151 p->state = RUNNABLE;
152
153 release(&ptable.lock);
154 }
155
156
157
158 int
159 growproc(int n)
160 {
161 uint sz;
162 struct proc *curproc = myproc();
163
164 sz = curproc->sz;
165 if(n > 0){
166 if((sz = allocuvm(curproc->pgdir, sz, sz + n)) == 0)
167 return -1;
168 } else if(n < 0){
169 if((sz = deallocuvm(curproc->pgdir, sz, sz + n)) == 0)
170 return -1;
171 }
172 curproc->sz = sz;
173 switchuvm(curproc);
174 return 0;
175 }
176
177
178
179
180 int
181 fork(void)
182 {
183 int i, pid;
184 struct proc *np;
185 struct proc *curproc = myproc();
186
187
188 if((np = allocproc()) == 0){
189 return -1;
190 }
191
192
193 if((np->pgdir = copyuvm(curproc->pgdir, curproc->sz)) == 0){
194 kfree(np->kstack);
195 np->kstack = 0;
196 np->state = UNUSED;
197 return -1;
198 }
199 np->sz = curproc->sz;
200 np->parent = curproc;
201 *np->tf = *curproc->tf;
202
203
204 np->tf->eax = 0;
205
206 for(i = 0; i < NOFILE; i++)
207 if(curproc->ofile[i])
208 np->ofile[i] = filedup(curproc->ofile[i]);
209 np->cwd = idup(curproc->cwd);
210
211 safestrcpy(np->name, curproc->name, sizeof(curproc->name));
212
213 pid = np->pid;
214
215 acquire(&ptable.lock);
216
217 np->state = RUNNABLE;
218
219 release(&ptable.lock);
220
221 return pid;
222 }
223
224
225
226
227 void
228 exit(void)
229 {
230 struct proc *curproc = myproc();
231 struct proc *p;
232 int fd;
233
234 if(curproc == initproc)
235 panic("init exiting");
236
237
238 for(fd = 0; fd < NOFILE; fd++){
239 if(curproc->ofile[fd]){
240 fileclose(curproc->ofile[fd]);
241 curproc->ofile[fd] = 0;
242 }
243 }
244
245 begin_op();
246 iput(curproc->cwd);
247 end_op();
248 curproc->cwd = 0;
249
250 acquire(&ptable.lock);
251
252
253 wakeup1(curproc->parent);
254
255
256 for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){
257 if(p->parent == curproc){
258 p->parent = initproc;
259 if(p->state == ZOMBIE)
260 wakeup1(initproc);
261 }
262 }
263
264
265 curproc->state = ZOMBIE;
266 sched();
267 panic("zombie exit");
268 }
269
270
271
272 int
273 wait(void)
274 {
275 struct proc *p;
276 int havekids, pid;
277 struct proc *curproc = myproc();
278
279 acquire(&ptable.lock);
280 for(;;){
281
282 havekids = 0;
283 for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){
284 if(p->parent != curproc)
285 continue;
286 havekids = 1;
287 if(p->state == ZOMBIE){
288
289 pid = p->pid;
290 kfree(p->kstack);
291 p->kstack = 0;
292 freevm(p->pgdir);
293 p->pid = 0;
294 p->parent = 0;
295 p->name[0] = 0;
296 p->killed = 0;
297 p->state = UNUSED;
298 release(&ptable.lock);
299 return pid;
300 }
301 }
302
303
304 if(!havekids || curproc->killed){
305 release(&ptable.lock);
306 return -1;
307 }
308
309
310 sleep(curproc, &ptable.lock);
311 }
312 }
313
314
315
316
317
318
319
320
321
322 void
323 scheduler(void)
324 {
325 struct proc *p;
326 struct cpu *c = mycpu();
327 c->proc = 0;
328
329 for(;;){
330
331 sti();
332
333
334 acquire(&ptable.lock);
335 for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){
336 if(p->state != RUNNABLE)
337 continue;
338
339
340
341
342 c->proc = p;
343 switchuvm(p);
344 p->state = RUNNING;
345
346 swtch(&(c->scheduler), p->context);
347 switchkvm();
348
349
350
351 c->proc = 0;
352 }
353 release(&ptable.lock);
354
355 }
356 }
357
358
359
360
361
362
363
364
365 void
366 sched(void)
367 {
368 int intena;
369 struct proc *p = myproc();
370
371 if(!holding(&ptable.lock))
372 panic("sched ptable.lock");
373 if(mycpu()->ncli != 1)
374 panic("sched locks");
375 if(p->state == RUNNING)
376 panic("sched running");
377 if(readeflags()&FL_IF)
378 panic("sched interruptible");
379 intena = mycpu()->intena;
380 swtch(&p->context, mycpu()->scheduler);
381 mycpu()->intena = intena;
382 }
383
384
385 void
386 yield(void)
387 {
388 acquire(&ptable.lock);
389 myproc()->state = RUNNABLE;
390 sched();
391 release(&ptable.lock);
392 }
393
394
395
396 void
397 forkret(void)
398 {
399 static int first = 1;
400
401 release(&ptable.lock);
402
403 if (first) {
404
405
406
407 first = 0;
408 iinit(ROOTDEV);
409 initlog(ROOTDEV);
410 }
411
412
413 }
414
415
416
417 void
418 sleep(void *chan, struct spinlock *lk)
419 {
420 struct proc *p = myproc();
421
422 if(p == 0)
423 panic("sleep");
424
425 if(lk == 0)
426 panic("sleep without lk");
427
428
429
430
431
432
433
434 if(lk != &ptable.lock){
435 acquire(&ptable.lock);
436 release(lk);
437 }
438
439 p->chan = chan;
440 p->state = SLEEPING;
441
442 sched();
443
444
445 p->chan = 0;
446
447
448 if(lk != &ptable.lock){
449 release(&ptable.lock);
450 acquire(lk);
451 }
452 }
453
454
455
456
457 static void
458 wakeup1(void *chan)
459 {
460 struct proc *p;
461
462 for(p = ptable.proc; p < &ptable.proc[NPROC]; p++)
463 if(p->state == SLEEPING && p->chan == chan)
464 p->state = RUNNABLE;
465 }
466
467
468 void
469 wakeup(void *chan)
470 {
471 acquire(&ptable.lock);
472 wakeup1(chan);
473 release(&ptable.lock);
474 }
475
476
477
478
479 int
480 kill(int pid)
481 {
482 struct proc *p;
483
484 acquire(&ptable.lock);
485 for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){
486 if(p->pid == pid){
487 p->killed = 1;
488
489 if(p->state == SLEEPING)
490 p->state = RUNNABLE;
491 release(&ptable.lock);
492 return 0;
493 }
494 }
495 release(&ptable.lock);
496 return -1;
497 }
498
499
500
501
502
503 void
504 procdump(void)
505 {
506 static char *states[] = {
507 [UNUSED] "unused",
508 [EMBRYO] "embryo",
509 [SLEEPING] "sleep ",
510 [RUNNABLE] "runble",
511 [RUNNING] "run ",
512 [ZOMBIE] "zombie"
513 };
514 int i;
515 struct proc *p;
516 char *state;
517 uint pc[10];
518
519 for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){
520 if(p->state == UNUSED)
521 continue;
522 if(p->state >= 0 && p->state < NELEM(states) && states[p->state])
523 state = states[p->state];
524 else
525 state = "???";
526 cprintf("%d %s %s", p->pid, state, p->name);
527 if(p->state == SLEEPING){
528 getcallerpcs((uint*)p->context->ebp+2, pc);
529 for(i=0; i<10 && pc[i] != 0; i++)
530 cprintf(" %p", pc[i]);
531 }
532 cprintf("\n");
533 }
534 }