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