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
- 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->parent = 0;
167 p->name[0] = 0;
168 p->chan = 0;
169 p->killed = 0;
170 p->xstate = 0;
171 p->state = UNUSED;
172 }
173
174
175
176 pagetable_t
177 proc_pagetable(struct proc *p)
178 {
179 pagetable_t pagetable;
180
181
182 pagetable = uvmcreate();
183 if(pagetable == 0)
184 return 0;
185
186
187
188
189
190 if(mappages(pagetable, TRAMPOLINE, PGSIZE,
191 (uint64)trampoline, PTE_R | PTE_X) < 0){
192 uvmfree(pagetable, 0);
193 return 0;
194 }
195
196
197
198 if(mappages(pagetable, TRAPFRAME, PGSIZE,
199 (uint64)(p->trapframe), PTE_R | PTE_W) < 0){
200 uvmunmap(pagetable, TRAMPOLINE, 1, 0);
201 uvmfree(pagetable, 0);
202 return 0;
203 }
204
205 return pagetable;
206 }
207
208
209
210 void
211 proc_freepagetable(pagetable_t pagetable, uint64 sz)
212 {
213 uvmunmap(pagetable, TRAMPOLINE, 1, 0);
214 uvmunmap(pagetable, TRAPFRAME, 1, 0);
215 uvmfree(pagetable, sz);
216 }
217
218
219 void
220 userinit(void)
221 {
222 struct proc *p;
223
224 p = allocproc();
225 initproc = p;
226
227 p->cwd = namei("/");
228
229 p->state = RUNNABLE;
230
231 release(&p->lock);
232 }
233
234
235
236 int
237 growproc(int n)
238 {
239 uint64 sz;
240 struct proc *p = myproc();
241
242 sz = p->sz;
243 if(n > 0){
244 if(sz + n > TRAPFRAME) {
245 return -1;
246 }
247 if((sz = uvmalloc(p->pagetable, sz, sz + n, PTE_W)) == 0) {
248 return -1;
249 }
250 } else if(n < 0){
251 sz = uvmdealloc(p->pagetable, sz, sz + n);
252 }
253 p->sz = sz;
254 return 0;
255 }
256
257
258
259 int
260 kfork(void)
261 {
262 int i, pid;
263 struct proc *np;
264 struct proc *p = myproc();
265
266
267 if((np = allocproc()) == 0){
268 return -1;
269 }
270
271
272 if(uvmcopy(p->pagetable, np->pagetable, p->sz) < 0){
273 freeproc(np);
274 release(&np->lock);
275 return -1;
276 }
277 np->sz = p->sz;
278
279
280 *(np->trapframe) = *(p->trapframe);
281
282
283 np->trapframe->a0 = 0;
284
285
286 for(i = 0; i < NOFILE; i++)
287 if(p->ofile[i])
288 np->ofile[i] = filedup(p->ofile[i]);
289 np->cwd = idup(p->cwd);
290
291 safestrcpy(np->name, p->name, sizeof(p->name));
292
293 pid = np->pid;
294
295 release(&np->lock);
296
297 acquire(&wait_lock);
298 np->parent = p;
299 release(&wait_lock);
300
301 acquire(&np->lock);
302 np->state = RUNNABLE;
303 release(&np->lock);
304
305 return pid;
306 }
307
308
309
310 void
311 reparent(struct proc *p)
312 {
313 struct proc *pp;
314
315 for(pp = proc; pp < &proc[NPROC]; pp++){
316 if(pp->parent == p){
317 pp->parent = initproc;
318 wakeup(initproc);
319 }
320 }
321 }
322
323
324
325
326 void
327 kexit(int status)
328 {
329 struct proc *p = myproc();
330
331 if(p == initproc)
332 panic("init exiting");
333
334
335 for(int fd = 0; fd < NOFILE; fd++){
336 if(p->ofile[fd]){
337 struct file *f = p->ofile[fd];
338 fileclose(f);
339 p->ofile[fd] = 0;
340 }
341 }
342
343 begin_op();
344 iput(p->cwd);
345 end_op();
346 p->cwd = 0;
347
348 acquire(&wait_lock);
349
350
351 reparent(p);
352
353
354 wakeup(p->parent);
355
356 acquire(&p->lock);
357
358 p->xstate = status;
359 p->state = ZOMBIE;
360
361 release(&wait_lock);
362
363
364 sched();
365 panic("zombie exit");
366 }
367
368
369
370 int
371 kwait(uint64 addr)
372 {
373 struct proc *pp;
374 int havekids, pid;
375 struct proc *p = myproc();
376
377 acquire(&wait_lock);
378
379 for(;;){
380
381 havekids = 0;
382 for(pp = proc; pp < &proc[NPROC]; pp++){
383 if(pp->parent == p){
384
385 acquire(&pp->lock);
386
387 havekids = 1;
388 if(pp->state == ZOMBIE){
389
390 pid = pp->pid;
391 if(addr != 0 && copyout(p->pagetable, addr, (char *)&pp->xstate,
392 sizeof(pp->xstate)) < 0) {
393 release(&pp->lock);
394 release(&wait_lock);
395 return -1;
396 }
397 freeproc(pp);
398 release(&pp->lock);
399 release(&wait_lock);
400 return pid;
401 }
402 release(&pp->lock);
403 }
404 }
405
406
407 if(!havekids || killed(p)){
408 release(&wait_lock);
409 return -1;
410 }
411
412
413 sleep(p, &wait_lock);
414 }
415 }
416
417
418
419
420
421
422
423
424 void
425 scheduler(void)
426 {
427 struct proc *p;
428 struct cpu *c = mycpu();
429
430 c->proc = 0;
431 for(;;){
432
433
434
435
436
437 intr_on();
438 intr_off();
439
440 int found = 0;
441 for(p = proc; p < &proc[NPROC]; p++) {
442 acquire(&p->lock);
443 if(p->state == RUNNABLE) {
444
445
446
447 p->state = RUNNING;
448 c->proc = p;
449 swtch(&c->context, &p->context);
450
451
452
453 c->proc = 0;
454 found = 1;
455 }
456 release(&p->lock);
457 }
458 if(found == 0) {
459
460 asm volatile("wfi");
461 }
462 }
463 }
464
465
466
467
468
469
470
471
472 void
473 sched(void)
474 {
475 int intena;
476 struct proc *p = myproc();
477
478 if(!holding(&p->lock))
479 panic("sched p->lock");
480 if(mycpu()->noff != 1)
481 panic("sched locks");
482 if(p->state == RUNNING)
483 panic("sched RUNNING");
484 if(intr_get())
485 panic("sched interruptible");
486
487 intena = mycpu()->intena;
488 swtch(&p->context, &mycpu()->context);
489 mycpu()->intena = intena;
490 }
491
492
493 void
494 yield(void)
495 {
496 struct proc *p = myproc();
497 acquire(&p->lock);
498 p->state = RUNNABLE;
499 sched();
500 release(&p->lock);
501 }
502
503
504
505 void
506 forkret(void)
507 {
508 extern char userret[];
509 static int first = 1;
510 struct proc *p = myproc();
511
512
513 release(&p->lock);
514
515 if (first) {
516
517
518
519 fsinit(ROOTDEV);
520
521 first = 0;
522
523 __sync_synchronize();
524
525
526
527 p->trapframe->a0 = kexec("/init", (char *[]){ "/init", 0 });
528 if (p->trapframe->a0 == -1) {
529 panic("exec");
530 }
531 }
532
533
534 prepare_return();
535 uint64 satp = MAKE_SATP(p->pagetable);
536 uint64 trampoline_userret = TRAMPOLINE + (userret - trampoline);
537 ((void (*)(uint64))trampoline_userret)(satp);
538 }
539
540
541
542 void
543 sleep(void *chan, struct spinlock *lk)
544 {
545 struct proc *p = myproc();
546
547
548
549
550
551
552
553
554 acquire(&p->lock);
555 release(lk);
556
557
558 p->chan = chan;
559 p->state = SLEEPING;
560
561 sched();
562
563
564 p->chan = 0;
565
566
567 release(&p->lock);
568 acquire(lk);
569 }
570
571
572
573 void
574 wakeup(void *chan)
575 {
576 struct proc *p;
577
578 for(p = proc; p < &proc[NPROC]; p++) {
579 if(p != myproc()){
580 acquire(&p->lock);
581 if(p->state == SLEEPING && p->chan == chan) {
582 p->state = RUNNABLE;
583 }
584 release(&p->lock);
585 }
586 }
587 }
588
589
590
591
592 int
593 kkill(int pid)
594 {
595 struct proc *p;
596
597 for(p = proc; p < &proc[NPROC]; p++){
598 acquire(&p->lock);
599 if(p->pid == pid){
600 p->killed = 1;
601 if(p->state == SLEEPING){
602
603 p->state = RUNNABLE;
604 }
605 release(&p->lock);
606 return 0;
607 }
608 release(&p->lock);
609 }
610 return -1;
611 }
612
613 void
614 setkilled(struct proc *p)
615 {
616 acquire(&p->lock);
617 p->killed = 1;
618 release(&p->lock);
619 }
620
621 int
622 killed(struct proc *p)
623 {
624 int k;
625
626 acquire(&p->lock);
627 k = p->killed;
628 release(&p->lock);
629 return k;
630 }
631
632
633
634
635 int
636 either_copyout(int user_dst, uint64 dst, void *src, uint64 len)
637 {
638 struct proc *p = myproc();
639 if(user_dst){
640 return copyout(p->pagetable, dst, src, len);
641 } else {
642 memmove((char *)dst, src, len);
643 return 0;
644 }
645 }
646
647
648
649
650 int
651 either_copyin(void *dst, int user_src, uint64 src, uint64 len)
652 {
653 struct proc *p = myproc();
654 if(user_src){
655 return copyin(p->pagetable, dst, src, len);
656 } else {
657 memmove(dst, (char*)src, len);
658 return 0;
659 }
660 }
661
662
663
664
665 void
666 procdump(void)
667 {
668 static char *states[] = {
669 [UNUSED] "unused",
670 [USED] "used",
671 [SLEEPING] "sleep ",
672 [RUNNABLE] "runble",
673 [RUNNING] "run ",
674 [ZOMBIE] "zombie"
675 };
676 struct proc *p;
677 char *state;
678
679 printf("\n");
680 for(p = proc; p < &proc[NPROC]; p++){
681 if(p->state == UNUSED)
682 continue;
683 if(p->state >= 0 && p->state < NELEM(states) && states[p->state])
684 state = states[p->state];
685 else
686 state = "???";
687 printf("%d %s %s", p->pid, state, p->name);
688 printf("\n");
689 }
690 }