root/kernel/proc.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. proc_mapstacks
  2. procinit
  3. cpuid
  4. mycpu
  5. myproc
  6. allocpid
  7. allocproc
  8. freeproc
  9. proc_pagetable
  10. proc_freepagetable
  11. userinit
  12. growproc
  13. kfork
  14. reparent
  15. kexit
  16. kwait
  17. scheduler
  18. sched
  19. yield
  20. forkret
  21. sleep_prepare
  22. sleep
  23. wakeup
  24. kkill
  25. setkilled
  26. killed
  27. either_copyout
  28. either_copyin
  29. 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[]; // trampoline.S
  22 
  23 // helps ensure that wakeups of wait()ing
  24 // parents are not lost. helps obey the
  25 // memory model when using p->parent.
  26 // must be acquired before any p->lock.
  27 struct spinlock wait_lock;
  28 
  29 // Allocate a page for each process's kernel stack.
  30 // Map it high in memory, followed by an invalid
  31 // guard page.
  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 // initialize the proc table.
  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 // Must be called with interrupts disabled,
  62 // to prevent race with process being moved
  63 // to a different CPU.
  64 int
  65 cpuid()
  66 {
  67   int id = r_tp();
  68   return id;
  69 }
  70 
  71 // Return this CPU's cpu struct.
  72 // Interrupts must be disabled.
  73 struct cpu *
  74 mycpu(void)
  75 {
  76   int id = cpuid();
  77   struct cpu *c = &cpus[id];
  78   return c;
  79 }
  80 
  81 // Return the current struct proc *, or zero if none.
  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 // Look in the process table for an UNUSED proc.
 106 // If found, initialize state required to run in the kernel,
 107 // and return with p->lock held.
 108 // If there are no free procs, or a memory allocation fails, return 0.
 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   // Allocate a trapframe page.
 129   if ((p->trapframe = (struct trapframe *)kalloc()) == 0) {
 130     freeproc(p);
 131     release(&p->lock);
 132     return 0;
 133   }
 134 
 135   // An empty user page table.
 136   p->pagetable = proc_pagetable(p);
 137   if (p->pagetable == 0) {
 138     freeproc(p);
 139     release(&p->lock);
 140     return 0;
 141   }
 142 
 143   // Set up new context to start executing at forkret,
 144   // which returns to user space.
 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 // free a proc structure and the data hanging from it,
 153 // including user pages.
 154 // p->lock must be held.
 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 // Create a user page table for a given process, with no user memory,
 174 // but with trampoline and trapframe pages.
 175 pagetable_t
 176 proc_pagetable(struct proc *p)
 177 {
 178   pagetable_t pagetable;
 179 
 180   // An empty page table.
 181   pagetable = uvmcreate();
 182   if (pagetable == 0)
 183     return 0;
 184 
 185   // map the trampoline code (for system call return)
 186   // at the highest user virtual address.
 187   // only the supervisor uses it, on the way
 188   // to/from user space, so not PTE_U.
 189   if (mappages(pagetable, TRAMPOLINE, PGSIZE, (uint64)trampoline,
 190                PTE_R | PTE_X) < 0) {
 191     uvmfree(pagetable, 0);
 192     return 0;
 193   }
 194 
 195   // map the trapframe page just below the trampoline page, for
 196   // trampoline.S.
 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 // Free a process's page table, and free the
 208 // physical memory it refers to.
 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 // Set up first user process.
 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 // Grow or shrink user memory by n bytes.
 234 // Return 0 on success, -1 on failure.
 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 // Create a new process, copying the parent.
 257 // Sets up child kernel stack to return as if from fork() system call.
 258 int
 259 kfork(void)
 260 {
 261   int i, pid;
 262   struct proc *np;
 263   struct proc *p = myproc();
 264 
 265   // Allocate process.
 266   if ((np = allocproc()) == 0) {
 267     return -1;
 268   }
 269 
 270   // Copy user memory from parent to child.
 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   // copy saved user registers.
 279   *(np->trapframe) = *(p->trapframe);
 280 
 281   // Cause fork to return 0 in the child.
 282   np->trapframe->a0 = 0;
 283 
 284   // increment reference counts on open file descriptors.
 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 // Pass p's abandoned children to init.
 308 // Caller must hold wait_lock.
 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 // Exit the current process.  Does not return.
 323 // An exited process remains in the zombie state
 324 // until its parent calls wait().
 325 void
 326 kexit(int status)
 327 {
 328   struct proc *p = myproc();
 329 
 330   if (p == initproc)
 331     panic("init exiting");
 332 
 333   // Close all open files.
 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   // Give any children to init.
 350   reparent(p);
 351 
 352   // Parent might be sleeping in wait().
 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   // Jump into the scheduler, never to return.
 363   sched();
 364   panic("zombie exit");
 365 }
 366 
 367 // Wait for a child process to exit and return its pid.
 368 // Return -1 if this process has no children.
 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     // Scan through table looking for exited children.
 380     havekids = 0;
 381     for (pp = proc; pp < &proc[NPROC]; pp++) {
 382       if (pp->parent == p) {
 383         // make sure the child isn't still in exit() or swtch().
 384         acquire(&pp->lock);
 385 
 386         havekids = 1;
 387         if (pp->state == ZOMBIE) {
 388           // Found one.
 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     // No point waiting if we don't have any children.
 408     if (!havekids || killed(p)) {
 409       release(&wait_lock);
 410       return -1;
 411     }
 412 
 413     // Wait for a child to exit.
 414     sleep_prepare(p); //DOC: wait-sleep
 415     release(&wait_lock);
 416     sleep();
 417     acquire(&wait_lock);
 418   }
 419 }
 420 
 421 // Per-CPU process scheduler.
 422 // Each CPU calls scheduler() after setting itself up.
 423 // Scheduler never returns.  It loops, doing:
 424 //  - choose a process to run.
 425 //  - swtch to start running that process.
 426 //  - eventually that process transfers control
 427 //    via swtch back to the scheduler.
 428 void
 429 scheduler(void)
 430 {
 431   struct proc *p;
 432   struct cpu *c = mycpu();
 433 
 434   c->proc = 0;
 435   for (;;) {
 436     // The most recent process to run may have had interrupts
 437     // turned off; enable them to avoid a deadlock if all
 438     // processes are waiting. Then turn them back off
 439     // to avoid a possible race between an interrupt
 440     // and wfi.
 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         // Switch to chosen process.  It is the process's job
 449         // to release its lock and then reacquire it
 450         // before jumping back to us.
 451         p->state = RUNNING;
 452         c->proc = p;
 453         swtch(&c->context, &p->context);
 454 
 455         // Don't re-enable interrupts on release.
 456         mycpu()->intena = 0;
 457 
 458         // Process is done running for now.
 459         // It should have changed its p->state before coming back.
 460         c->proc = 0;
 461         found = 1;
 462       }
 463       release(&p->lock);
 464     }
 465     if (found == 0) {
 466       // nothing to run; stop running on this core until an interrupt.
 467       asm volatile("wfi");
 468     }
 469   }
 470 }
 471 
 472 // Switch to scheduler.  Must hold only p->lock
 473 // and have changed proc->state. Saves and restores
 474 // intena because intena is a property of this
 475 // kernel thread, not this CPU. It should
 476 // be proc->intena and proc->noff, but that would
 477 // break in the few places where a lock is held but
 478 // there's no process.
 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 // Give up the CPU for one scheduling round.
 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 // A fork child's very first scheduling by scheduler()
 511 // will swtch to forkret.
 512 void
 513 forkret(void)
 514 {
 515   extern char userret[];
 516   static int first = 1;
 517   struct proc *p = myproc();
 518 
 519   // Still holding p->lock from scheduler.
 520   release(&p->lock);
 521 
 522   if (first) {
 523     first = 0;
 524 
 525     // File system initialization must be run in the context of a
 526     // regular process (e.g., because it calls sleep), and thus cannot
 527     // be run from main().
 528     fsinit(ROOTDEV);
 529 
 530     // We can invoke kexec() now that file system is initialized.
 531     // Put the return value (argc) of kexec into a0.
 532     p->trapframe->a0 = kexec("/init", (char *[]){"/init", 0});
 533     if (p->trapframe->a0 == -1) {
 534       panic("exec");
 535     }
 536   }
 537 
 538   // return to user space, mimicing usertrap()'s return.
 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 // Register current process as waiting for wakeups on chan.
 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 // Put the thread to sleep.  Assumes sleep_prepare() was called before.
 559 // If the channel registered by sleep_prepare() has been woken up in
 560 // the meantime, do not go to sleep, and instead return immediately.
 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 // Wake up all processes sleeping on channel chan.
 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       // If the process is waiting for wakeups on this channel,
 584       // signal that the wakeup happened by clearing p->chan.
 585       p->chan = 0;
 586 
 587       // If this waiting process has gotten so far as to actually
 588       // go to sleep, also set it back to RUNNING.
 589       if (p->state == SLEEPING) {
 590         p->state = RUNNABLE;
 591       }
 592     }
 593     release(&p->lock);
 594   }
 595 }
 596 
 597 // Kill the process with the given pid.
 598 // The victim won't exit until it tries to return
 599 // to user space (see usertrap() in trap.c).
 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         // Wake process from sleep().
 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 // Copy to either a user address, or kernel address,
 644 // depending on usr_dst.
 645 // Returns 0 on success, -1 on error.
 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 // Copy from either a user address, or kernel address,
 659 // depending on usr_src.
 660 // Returns 0 on success, -1 on error.
 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 // Print a process listing to console.  For debugging.
 674 // Runs when user types ^P on console.
 675 // No lock to avoid wedging a stuck machine further.
 676 void
 677 procdump(void)
 678 {
 679   static char *states[] = {
 680     // clang-format off
 681     [UNUSED]    = "unused",
 682     [USED]      = "used",
 683     [SLEEPING]  = "sleep ",
 684     [RUNNABLE]  = "runble",
 685     [RUNNING]   = "run   ",
 686     [ZOMBIE]    = "zombie"
 687     // clang-format on
 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 }

/* [<][>][^][v][top][bottom][index][help] */