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
  22. wakeup
  23. kkill
  24. setkilled
  25. killed
  26. either_copyout
  27. either_copyin
  28. 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->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 // Create a user page table for a given process, with no user memory,
 175 // but with trampoline and trapframe pages.
 176 pagetable_t
 177 proc_pagetable(struct proc *p)
 178 {
 179   pagetable_t pagetable;
 180 
 181   // An empty page table.
 182   pagetable = uvmcreate();
 183   if(pagetable == 0)
 184     return 0;
 185 
 186   // map the trampoline code (for system call return)
 187   // at the highest user virtual address.
 188   // only the supervisor uses it, on the way
 189   // to/from user space, so not PTE_U.
 190   if(mappages(pagetable, TRAMPOLINE, PGSIZE,
 191               (uint64)trampoline, PTE_R | PTE_X) < 0){
 192     uvmfree(pagetable, 0);
 193     return 0;
 194   }
 195 
 196   // map the trapframe page just below the trampoline page, for
 197   // trampoline.S.
 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 // Free a process's page table, and free the
 209 // physical memory it refers to.
 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 // Set up first user process.
 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 // Grow or shrink user memory by n bytes.
 235 // Return 0 on success, -1 on failure.
 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 // Create a new process, copying the parent.
 258 // Sets up child kernel stack to return as if from fork() system call.
 259 int
 260 kfork(void)
 261 {
 262   int i, pid;
 263   struct proc *np;
 264   struct proc *p = myproc();
 265 
 266   // Allocate process.
 267   if((np = allocproc()) == 0){
 268     return -1;
 269   }
 270 
 271   // Copy user memory from parent to child.
 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   // copy saved user registers.
 280   *(np->trapframe) = *(p->trapframe);
 281 
 282   // Cause fork to return 0 in the child.
 283   np->trapframe->a0 = 0;
 284 
 285   // increment reference counts on open file descriptors.
 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 // Pass p's abandoned children to init.
 309 // Caller must hold wait_lock.
 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 // Exit the current process.  Does not return.
 324 // An exited process remains in the zombie state
 325 // until its parent calls wait().
 326 void
 327 kexit(int status)
 328 {
 329   struct proc *p = myproc();
 330 
 331   if(p == initproc)
 332     panic("init exiting");
 333 
 334   // Close all open files.
 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   // Give any children to init.
 351   reparent(p);
 352 
 353   // Parent might be sleeping in wait().
 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   // Jump into the scheduler, never to return.
 364   sched();
 365   panic("zombie exit");
 366 }
 367 
 368 // Wait for a child process to exit and return its pid.
 369 // Return -1 if this process has no children.
 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     // Scan through table looking for exited children.
 381     havekids = 0;
 382     for(pp = proc; pp < &proc[NPROC]; pp++){
 383       if(pp->parent == p){
 384         // make sure the child isn't still in exit() or swtch().
 385         acquire(&pp->lock);
 386 
 387         havekids = 1;
 388         if(pp->state == ZOMBIE){
 389           // Found one.
 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     // No point waiting if we don't have any children.
 407     if(!havekids || killed(p)){
 408       release(&wait_lock);
 409       return -1;
 410     }
 411     
 412     // Wait for a child to exit.
 413     sleep(p, &wait_lock);  //DOC: wait-sleep
 414   }
 415 }
 416 
 417 // Per-CPU process scheduler.
 418 // Each CPU calls scheduler() after setting itself up.
 419 // Scheduler never returns.  It loops, doing:
 420 //  - choose a process to run.
 421 //  - swtch to start running that process.
 422 //  - eventually that process transfers control
 423 //    via swtch back to the scheduler.
 424 void
 425 scheduler(void)
 426 {
 427   struct proc *p;
 428   struct cpu *c = mycpu();
 429 
 430   c->proc = 0;
 431   for(;;){
 432     // The most recent process to run may have had interrupts
 433     // turned off; enable them to avoid a deadlock if all
 434     // processes are waiting. Then turn them back off
 435     // to avoid a possible race between an interrupt
 436     // and wfi.
 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         // Switch to chosen process.  It is the process's job
 445         // to release its lock and then reacquire it
 446         // before jumping back to us.
 447         p->state = RUNNING;
 448         c->proc = p;
 449         swtch(&c->context, &p->context);
 450 
 451         // Process is done running for now.
 452         // It should have changed its p->state before coming back.
 453         c->proc = 0;
 454         found = 1;
 455       }
 456       release(&p->lock);
 457     }
 458     if(found == 0) {
 459       // nothing to run; stop running on this core until an interrupt.
 460       asm volatile("wfi");
 461     }
 462   }
 463 }
 464 
 465 // Switch to scheduler.  Must hold only p->lock
 466 // and have changed proc->state. Saves and restores
 467 // intena because intena is a property of this
 468 // kernel thread, not this CPU. It should
 469 // be proc->intena and proc->noff, but that would
 470 // break in the few places where a lock is held but
 471 // there's no process.
 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 // Give up the CPU for one scheduling round.
 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 // A fork child's very first scheduling by scheduler()
 504 // will swtch to forkret.
 505 void
 506 forkret(void)
 507 {
 508   extern char userret[];
 509   static int first = 1;
 510   struct proc *p = myproc();
 511 
 512   // Still holding p->lock from scheduler.
 513   release(&p->lock);
 514 
 515   if (first) {
 516     // File system initialization must be run in the context of a
 517     // regular process (e.g., because it calls sleep), and thus cannot
 518     // be run from main().
 519     fsinit(ROOTDEV);
 520 
 521     first = 0;
 522     // ensure other cores see first=0.
 523     __sync_synchronize();
 524 
 525     // We can invoke kexec() now that file system is initialized.
 526     // Put the return value (argc) of kexec into a0.
 527     p->trapframe->a0 = kexec("/init", (char *[]){ "/init", 0 });
 528     if (p->trapframe->a0 == -1) {
 529       panic("exec");
 530     }
 531   }
 532 
 533   // return to user space, mimicing usertrap()'s return.
 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 // Sleep on channel chan, releasing condition lock lk.
 541 // Re-acquires lk when awakened.
 542 void
 543 sleep(void *chan, struct spinlock *lk)
 544 {
 545   struct proc *p = myproc();
 546   
 547   // Must acquire p->lock in order to
 548   // change p->state and then call sched.
 549   // Once we hold p->lock, we can be
 550   // guaranteed that we won't miss any wakeup
 551   // (wakeup locks p->lock),
 552   // so it's okay to release lk.
 553 
 554   acquire(&p->lock);  //DOC: sleeplock1
 555   release(lk);
 556 
 557   // Go to sleep.
 558   p->chan = chan;
 559   p->state = SLEEPING;
 560 
 561   sched();
 562 
 563   // Tidy up.
 564   p->chan = 0;
 565 
 566   // Reacquire original lock.
 567   release(&p->lock);
 568   acquire(lk);
 569 }
 570 
 571 // Wake up all processes sleeping on channel chan.
 572 // Caller should hold the condition lock.
 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 // Kill the process with the given pid.
 590 // The victim won't exit until it tries to return
 591 // to user space (see usertrap() in trap.c).
 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         // Wake process from sleep().
 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 // Copy to either a user address, or kernel address,
 633 // depending on usr_dst.
 634 // Returns 0 on success, -1 on error.
 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 // Copy from either a user address, or kernel address,
 648 // depending on usr_src.
 649 // Returns 0 on success, -1 on error.
 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 // Print a process listing to console.  For debugging.
 663 // Runs when user types ^P on console.
 664 // No lock to avoid wedging a stuck machine further.
 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 }

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