This source file includes following definitions.
- proc_mapstacks
- procinit
- cpuid
- mycpu
- myproc
- allocpid
- allocproc
- freeproc
- proc_pagetable
- proc_freepagetable
- userinit
- growproc
- kfork
- reparent
- kexit
- kwait
- scheduler
- sched
- yield
- forkret
- sleep_prepare
- sleep
- wakeup
- kkill
- setkilled
- killed
- either_copyout
- either_copyin
- procdump
1 #include "types.h"
2 #include "param.h"
3 #include "memlayout.h"
4 #include "riscv.h"
5 #include "spinlock.h"
6 #include "proc.h"
7 #include "defs.h"
8
9 struct cpu cpus[NCPU];
10
11 struct proc proc[NPROC];
12
13 struct proc *initproc;
14
15 int nextpid = 1;
16 struct spinlock pid_lock;
17
18 extern void forkret(void);
19 static void freeproc(struct proc *p);
20
21 extern char trampoline[];
22
23
24
25
26
27 struct spinlock wait_lock;
28
29
30
31
32 void
33 proc_mapstacks(pagetable_t kpgtbl)
34 {
35 struct proc *p;
36
37 for (p = proc; p < &proc[NPROC]; p++) {
38 char *pa = kalloc();
39 if (pa == 0)
40 panic("kalloc");
41 uint64 va = KSTACK((int)(p - proc));
42 kvmmap(kpgtbl, va, (uint64)pa, PGSIZE, PTE_R | PTE_W);
43 }
44 }
45
46
47 void
48 procinit(void)
49 {
50 struct proc *p;
51
52 initlock(&pid_lock, "nextpid");
53 initlock(&wait_lock, "wait_lock");
54 for (p = proc; p < &proc[NPROC]; p++) {
55 initlock(&p->lock, "proc");
56 p->state = UNUSED;
57 p->kstack = KSTACK((int)(p - proc));
58 }
59 }
60
61
62
63
64 int
65 cpuid()
66 {
67 int id = r_tp();
68 return id;
69 }
70
71
72
73 struct cpu *
74 mycpu(void)
75 {
76 int id = cpuid();
77 struct cpu *c = &cpus[id];
78 return c;
79 }
80
81
82 struct proc *
83 myproc(void)
84 {
85 push_off();
86 struct cpu *c = mycpu();
87 struct proc *p = c->proc;
88 pop_off();
89 return p;
90 }
91
92 int
93 allocpid()
94 {
95 int pid;
96
97 acquire(&pid_lock);
98 pid = nextpid;
99 nextpid = nextpid + 1;
100 release(&pid_lock);
101
102 return pid;
103 }
104
105
106
107
108
109 static struct proc *
110 allocproc(void)
111 {
112 struct proc *p;
113
114 for (p = proc; p < &proc[NPROC]; p++) {
115 acquire(&p->lock);
116 if (p->state == UNUSED) {
117 goto found;
118 } else {
119 release(&p->lock);
120 }
121 }
122 return 0;
123
124 found:
125 p->pid = allocpid();
126 p->state = USED;
127
128
129 if ((p->trapframe = (struct trapframe *)kalloc()) == 0) {
130 freeproc(p);
131 release(&p->lock);
132 return 0;
133 }
134
135
136 p->pagetable = proc_pagetable(p);
137 if (p->pagetable == 0) {
138 freeproc(p);
139 release(&p->lock);
140 return 0;
141 }
142
143
144
145 memset(&p->context, 0, sizeof(p->context));
146 p->context.ra = (uint64)forkret;
147 p->context.sp = p->kstack + PGSIZE;
148
149 return p;
150 }
151
152
153
154
155 static void
156 freeproc(struct proc *p)
157 {
158 if (p->trapframe)
159 kfree((void *)p->trapframe);
160 p->trapframe = 0;
161 if (p->pagetable)
162 proc_freepagetable(p->pagetable, p->sz);
163 p->pagetable = 0;
164 p->sz = 0;
165 p->pid = 0;
166 p->name[0] = 0;
167 p->chan = 0;
168 p->killed = 0;
169 p->xstate = 0;
170 p->state = UNUSED;
171 }
172
173
174
175 pagetable_t
176 proc_pagetable(struct proc *p)
177 {
178 pagetable_t pagetable;
179
180
181 pagetable = uvmcreate();
182 if (pagetable == 0)
183 return 0;
184
185
186
187
188
189 if (mappages(pagetable, TRAMPOLINE, PGSIZE, (uint64)trampoline,
190 PTE_R | PTE_X) < 0) {
191 uvmfree(pagetable, 0);
192 return 0;
193 }
194
195
196
197 if (mappages(pagetable, TRAPFRAME, PGSIZE, (uint64)(p->trapframe),
198 PTE_R | PTE_W) < 0) {
199 uvmunmap(pagetable, TRAMPOLINE, 1, 0);
200 uvmfree(pagetable, 0);
201 return 0;
202 }
203
204 return pagetable;
205 }
206
207
208
209 void
210 proc_freepagetable(pagetable_t pagetable, uint64 sz)
211 {
212 uvmunmap(pagetable, TRAMPOLINE, 1, 0);
213 uvmunmap(pagetable, TRAPFRAME, 1, 0);
214 uvmfree(pagetable, sz);
215 }
216
217
218 void
219 userinit(void)
220 {
221 struct proc *p;
222
223 p = allocproc();
224 initproc = p;
225
226 p->cwd = namei("/");
227
228 p->state = RUNNABLE;
229
230 release(&p->lock);
231 }
232
233
234
235 int
236 growproc(int n)
237 {
238 uint64 sz;
239 struct proc *p = myproc();
240
241 sz = p->sz;
242 if (n > 0) {
243 if (sz + n > TRAPFRAME) {
244 return -1;
245 }
246 if ((sz = uvmalloc(p->pagetable, sz, sz + n, PTE_W)) == 0) {
247 return -1;
248 }
249 } else if (n < 0) {
250 sz = uvmdealloc(p->pagetable, sz, sz + n);
251 }
252 p->sz = sz;
253 return 0;
254 }
255
256
257
258 int
259 kfork(void)
260 {
261 int i, pid;
262 struct proc *np;
263 struct proc *p = myproc();
264
265
266 if ((np = allocproc()) == 0) {
267 return -1;
268 }
269
270
271 if (uvmcopy(p->pagetable, np->pagetable, p->sz) < 0) {
272 freeproc(np);
273 release(&np->lock);
274 return -1;
275 }
276 np->sz = p->sz;
277
278
279 *(np->trapframe) = *(p->trapframe);
280
281
282 np->trapframe->a0 = 0;
283
284
285 for (i = 0; i < NOFILE; i++)
286 if (p->ofile[i])
287 np->ofile[i] = filedup(p->ofile[i]);
288 np->cwd = idup(p->cwd);
289
290 safestrcpy(np->name, p->name, sizeof(p->name));
291
292 pid = np->pid;
293
294 release(&np->lock);
295
296 acquire(&wait_lock);
297 np->parent = p;
298 release(&wait_lock);
299
300 acquire(&np->lock);
301 np->state = RUNNABLE;
302 release(&np->lock);
303
304 return pid;
305 }
306
307
308
309 void
310 reparent(struct proc *p)
311 {
312 struct proc *pp;
313
314 for (pp = proc; pp < &proc[NPROC]; pp++) {
315 if (pp->parent == p) {
316 pp->parent = initproc;
317 wakeup(initproc);
318 }
319 }
320 }
321
322
323
324
325 void
326 kexit(int status)
327 {
328 struct proc *p = myproc();
329
330 if (p == initproc)
331 panic("init exiting");
332
333
334 for (int fd = 0; fd < NOFILE; fd++) {
335 if (p->ofile[fd]) {
336 struct file *f = p->ofile[fd];
337 fileclose(f);
338 p->ofile[fd] = 0;
339 }
340 }
341
342 begin_op();
343 iput(p->cwd);
344 end_op();
345 p->cwd = 0;
346
347 acquire(&wait_lock);
348
349
350 reparent(p);
351
352
353 wakeup(p->parent);
354
355 acquire(&p->lock);
356
357 p->xstate = status;
358 p->state = ZOMBIE;
359
360 release(&wait_lock);
361
362
363 sched();
364 panic("zombie exit");
365 }
366
367
368
369 int
370 kwait(uint64 addr)
371 {
372 struct proc *pp;
373 int havekids, pid;
374 struct proc *p = myproc();
375
376 acquire(&wait_lock);
377
378 for (;;) {
379
380 havekids = 0;
381 for (pp = proc; pp < &proc[NPROC]; pp++) {
382 if (pp->parent == p) {
383
384 acquire(&pp->lock);
385
386 havekids = 1;
387 if (pp->state == ZOMBIE) {
388
389 pid = pp->pid;
390 if (addr != 0 &&
391 copyout(p->pagetable, p->sz, addr, (char *)&pp->xstate,
392 sizeof(pp->xstate)) < 0) {
393 release(&pp->lock);
394 release(&wait_lock);
395 return -1;
396 }
397 pp->parent = 0;
398 freeproc(pp);
399 release(&pp->lock);
400 release(&wait_lock);
401 return pid;
402 }
403 release(&pp->lock);
404 }
405 }
406
407
408 if (!havekids || killed(p)) {
409 release(&wait_lock);
410 return -1;
411 }
412
413
414 sleep_prepare(p);
415 release(&wait_lock);
416 sleep();
417 acquire(&wait_lock);
418 }
419 }
420
421
422
423
424
425
426
427
428 void
429 scheduler(void)
430 {
431 struct proc *p;
432 struct cpu *c = mycpu();
433
434 c->proc = 0;
435 for (;;) {
436
437
438
439
440
441 intr_on();
442 intr_off();
443
444 int found = 0;
445 for (p = proc; p < &proc[NPROC]; p++) {
446 acquire(&p->lock);
447 if (p->state == RUNNABLE) {
448
449
450
451 p->state = RUNNING;
452 c->proc = p;
453 swtch(&c->context, &p->context);
454
455
456 mycpu()->intena = 0;
457
458
459
460 c->proc = 0;
461 found = 1;
462 }
463 release(&p->lock);
464 }
465 if (found == 0) {
466
467 asm volatile("wfi");
468 }
469 }
470 }
471
472
473
474
475
476
477
478
479 void
480 sched(void)
481 {
482 int intena;
483 struct proc *p = myproc();
484
485 if (!holding(&p->lock))
486 panic("sched p->lock");
487 if (mycpu()->noff != 1)
488 panic("sched locks");
489 if (p->state == RUNNING)
490 panic("sched RUNNING");
491 if (intr_get())
492 panic("sched interruptible");
493
494 intena = mycpu()->intena;
495 swtch(&p->context, &mycpu()->context);
496 mycpu()->intena = intena;
497 }
498
499
500 void
501 yield(void)
502 {
503 struct proc *p = myproc();
504 acquire(&p->lock);
505 p->state = RUNNABLE;
506 sched();
507 release(&p->lock);
508 }
509
510
511
512 void
513 forkret(void)
514 {
515 extern char userret[];
516 static int first = 1;
517 struct proc *p = myproc();
518
519
520 release(&p->lock);
521
522 if (first) {
523 first = 0;
524
525
526
527
528 fsinit(ROOTDEV);
529
530
531
532 p->trapframe->a0 = kexec("/init", (char *[]){"/init", 0});
533 if (p->trapframe->a0 == -1) {
534 panic("exec");
535 }
536 }
537
538
539 prepare_return();
540 uint64 satp = MAKE_SATP(p->pagetable);
541 uint64 trampoline_userret = TRAMPOLINE + (userret - trampoline);
542 ((void (*)(uint64))trampoline_userret)(satp);
543 }
544
545
546 void
547 sleep_prepare(void *chan)
548 {
549 struct proc *p = myproc();
550
551 acquire(&p->lock);
552 if (chan == 0)
553 panic("sleep_prepare: zero chan");
554 p->chan = chan;
555 release(&p->lock);
556 }
557
558
559
560
561 void
562 sleep(void)
563 {
564 struct proc *p = myproc();
565
566 acquire(&p->lock);
567 if (p->chan != 0) {
568 p->state = SLEEPING;
569 sched();
570 }
571 release(&p->lock);
572 }
573
574
575 void
576 wakeup(void *chan)
577 {
578 struct proc *p;
579
580 for (p = proc; p < &proc[NPROC]; p++) {
581 acquire(&p->lock);
582 if (p->chan == chan) {
583
584
585 p->chan = 0;
586
587
588
589 if (p->state == SLEEPING) {
590 p->state = RUNNABLE;
591 }
592 }
593 release(&p->lock);
594 }
595 }
596
597
598
599
600 int
601 kkill(int pid)
602 {
603 struct proc *p;
604
605 if (pid == 0)
606 return -1;
607
608 for (p = proc; p < &proc[NPROC]; p++) {
609 acquire(&p->lock);
610 if (p->pid == pid) {
611 p->killed = 1;
612 if (p->state == SLEEPING) {
613
614 p->state = RUNNABLE;
615 }
616 release(&p->lock);
617 return 0;
618 }
619 release(&p->lock);
620 }
621 return -1;
622 }
623
624 void
625 setkilled(struct proc *p)
626 {
627 acquire(&p->lock);
628 p->killed = 1;
629 release(&p->lock);
630 }
631
632 int
633 killed(struct proc *p)
634 {
635 int k;
636
637 acquire(&p->lock);
638 k = p->killed;
639 release(&p->lock);
640 return k;
641 }
642
643
644
645
646 int
647 either_copyout(int user_dst, uint64 dst, void *src, uint64 len)
648 {
649 struct proc *p = myproc();
650 if (user_dst) {
651 return copyout(p->pagetable, p->sz, dst, src, len);
652 } else {
653 memmove((char *)dst, src, len);
654 return 0;
655 }
656 }
657
658
659
660
661 int
662 either_copyin(void *dst, int user_src, uint64 src, uint64 len)
663 {
664 struct proc *p = myproc();
665 if (user_src) {
666 return copyin(p->pagetable, p->sz, dst, src, len);
667 } else {
668 memmove(dst, (char *)src, len);
669 return 0;
670 }
671 }
672
673
674
675
676 void
677 procdump(void)
678 {
679 static char *states[] = {
680
681 [UNUSED] = "unused",
682 [USED] = "used",
683 [SLEEPING] = "sleep ",
684 [RUNNABLE] = "runble",
685 [RUNNING] = "run ",
686 [ZOMBIE] = "zombie"
687
688 };
689 struct proc *p;
690 char *state;
691
692 printk("\n");
693 for (p = proc; p < &proc[NPROC]; p++) {
694 if (p->state == UNUSED)
695 continue;
696 if (p->state >= 0 && p->state < NELEM(states) && states[p->state])
697 state = states[p->state];
698 else
699 state = "???";
700 printk("%d %s %s", p->pid, state, p->name);
701 printk("\n");
702 }
703 }