Advertisement
lamiastella

proc.c

Sep 29th, 2013
139
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 11.17 KB | None | 0 0
  1. #include "types.h"
  2. #include "defs.h"
  3. #include "param.h"
  4. #include "mmu.h"
  5. #include "x86.h"
  6. #include "proc.h"
  7. #include "spinlock.h"
  8.  
  9. struct {
  10.   struct spinlock lock;
  11.   struct proc proc[NPROC];
  12. } ptable;
  13.  
  14. static struct proc *initproc;
  15.  
  16. static int num_tickets=0;  //mona2
  17. unsigned long winner;
  18. int nextpid = 1;
  19. extern void forkret(void);
  20. extern void trapret(void);
  21.  
  22.  
  23. ///// mona2  lcg invariant //not working because of uint32_t
  24.  
  25. /*
  26. static uint32_t temper(uint32_t x)
  27. {
  28.     x ^= x>>11;
  29.     x ^= x<<7 & 0x9D2C5680;
  30.     x ^= x<<15 & 0xEFC60000;
  31.     x ^= x>>18;
  32.     return x;
  33. }
  34. uint32_t lcg64_temper(uint64_t *seed)
  35. {
  36.     *seed = 6364136223846793005ULL * *seed + 1;
  37.     return temper(*seed >> 32);
  38. }
  39. */
  40.  
  41. static
  42. unsigned long
  43. lcg_rand(unsigned long a)
  44. {
  45.   return (a * 279470273UL) % 4294967291UL;
  46. }
  47.  
  48.  
  49.  
  50.  
  51. static void wakeup1(void *chan);
  52.  
  53.  
  54. void
  55. pinit(void)
  56. {
  57.   initlock(&ptable.lock, "ptable");
  58. }
  59.  
  60. // Look in the process table for an UNUSED proc.
  61. // If found, change state to EMBRYO and initialize
  62. // state required to run in the kernel.
  63. // Otherwise return 0.
  64. static struct proc*
  65. allocproc(void)
  66. {
  67.   struct proc *p;
  68.   char *sp;
  69.  
  70.   acquire(&ptable.lock);
  71.   for(p = ptable.proc; p < &ptable.proc[NPROC]; p++)
  72.     if(p->state == UNUSED)
  73.       {
  74.         goto found;
  75.         p->tickets=CREATION_TICKET; //mona2
  76.         num_tickets+=CREATION_TICKET; //mona2
  77.       }
  78.   release(&ptable.lock);
  79.   return 0;
  80.  
  81. found:
  82.   p->state = EMBRYO;
  83.   p->pid = nextpid++;
  84.   release(&ptable.lock);
  85.  
  86.   // Allocate kernel stack if possible.
  87.   if((p->kstack = kalloc()) == 0){
  88.     p->state = UNUSED;
  89.     return 0;
  90.   }
  91.   sp = p->kstack + KSTACKSIZE;
  92.  
  93.   // Leave room for trap frame.
  94.   sp -= sizeof *p->tf;
  95.   p->tf = (struct trapframe*)sp;
  96.  
  97.   // Set up new context to start executing at forkret,
  98.   // which returns to trapret.
  99.   sp -= 4;
  100.   *(uint*)sp = (uint)trapret;
  101.  
  102.   sp -= sizeof *p->context;
  103.   p->context = (struct context*)sp;
  104.   memset(p->context, 0, sizeof *p->context);
  105.   p->context->eip = (uint)forkret;
  106.  
  107.   return p;
  108. }
  109.  
  110. // Set up first user process.
  111. void
  112. userinit(void)
  113. {
  114.   struct proc *p;
  115.   extern char _binary_initcode_start[], _binary_initcode_size[];
  116.  
  117.   p = allocproc();
  118.   acquire(&ptable.lock);
  119.   initproc = p;
  120.   if((p->pgdir = setupkvm()) == 0)
  121.     panic("userinit: out of memory?");
  122.   inituvm(p->pgdir, _binary_initcode_start, (int)_binary_initcode_size);
  123.   p->sz = PGSIZE;
  124.   memset(p->tf, 0, sizeof(*p->tf));
  125.   p->tf->cs = (SEG_UCODE << 3) | DPL_USER;
  126.   p->tf->ds = (SEG_UDATA << 3) | DPL_USER;
  127.   p->tf->es = p->tf->ds;
  128.   p->tf->ss = p->tf->ds;
  129.   p->tf->eflags = FL_IF;
  130.   p->tf->esp = PGSIZE;
  131.   p->tf->eip = 0;  // beginning of initcode.S
  132.  
  133.   safestrcpy(p->name, "initcode", sizeof(p->name));
  134.   p->cwd = namei("/");
  135.  
  136.   p->state = RUNNABLE;
  137.   p->tickets=CREATION_TICKET;
  138.   release(&ptable.lock);
  139. }
  140.  
  141. // Grow current process's memory by n bytes.
  142. // Return 0 on success, -1 on failure.
  143. int
  144. growproc(int n)
  145. {
  146.   uint sz;
  147.  
  148.   sz = proc->sz;
  149.   if(n > 0){
  150.     if((sz = allocuvm(proc->pgdir, sz, sz + n)) == 0)
  151.       return -1;
  152.   } else if(n < 0){
  153.     if((sz = deallocuvm(proc->pgdir, sz, sz + n)) == 0)
  154.       return -1;
  155.   }
  156.   proc->sz = sz;
  157.   switchuvm(proc);
  158.   return 0;
  159. }
  160.  
  161. // Create a new process copying p as the parent.
  162. // Sets up stack to return as if from system call.
  163. // Caller must set state of returned proc to RUNNABLE.
  164. int
  165. fork(void)
  166. {
  167.   int i, pid;
  168.   struct proc *np;
  169.  
  170.   // Allocate process.
  171.   if((np = allocproc()) == 0)
  172.     return -1;
  173.  
  174.   // Copy process state from p.
  175.   if((np->pgdir = copyuvm(proc->pgdir, proc->sz)) == 0){
  176.     kfree(np->kstack);
  177.     np->kstack = 0;
  178.     np->state = UNUSED;
  179.     return -1;
  180.   }
  181.   np->sz = proc->sz;
  182.   np->parent = proc;
  183.   *np->tf = *proc->tf;
  184.  
  185.   // Clear %eax so that fork returns 0 in the child.
  186.   np->tf->eax = 0;
  187.  
  188.   for(i = 0; i < NOFILE; i++)
  189.     if(proc->ofile[i])
  190.       np->ofile[i] = filedup(proc->ofile[i]);
  191.   np->cwd = idup(proc->cwd);
  192.  
  193.   pid = np->pid;
  194.   np->state = RUNNABLE;
  195.   safestrcpy(np->name, proc->name, sizeof(proc->name));
  196.   return pid;
  197. }
  198.  
  199. // Exit the current process.  Does not return.
  200. // An exited process remains in the zombie state
  201. // until its parent calls wait() to find out it exited.
  202. void
  203. exit(void)
  204. {
  205.   struct proc *p;
  206.   int fd;
  207.  
  208.   if(proc == initproc)
  209.     panic("init exiting");
  210.  
  211.   // Close all open files.
  212.   for(fd = 0; fd < NOFILE; fd++){
  213.     if(proc->ofile[fd]){
  214.       fileclose(proc->ofile[fd]);
  215.       proc->ofile[fd] = 0;
  216.     }
  217.   }
  218.  
  219.   iput(proc->cwd);
  220.   proc->cwd = 0;
  221.  
  222.   acquire(&ptable.lock);
  223.  
  224.   // Parent might be sleeping in wait().
  225.   wakeup1(proc->parent);
  226.  
  227.   // Pass abandoned children to init.
  228.   for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){
  229.     if(p->parent == proc){
  230.       p->parent = initproc;
  231.       if(p->state == ZOMBIE)
  232.         wakeup1(initproc);
  233.     }
  234.   }
  235.  
  236.   // Jump into the scheduler, never to return.
  237.   proc->state = ZOMBIE;
  238.   sched();
  239.   panic("zombie exit");
  240. }
  241.  
  242. // Wait for a child process to exit and return its pid.
  243. // Return -1 if this process has no children.
  244. int
  245. wait(void)
  246. {
  247.   struct proc *p;
  248.   int havekids, pid;
  249.  
  250.   acquire(&ptable.lock);
  251.   for(;;){
  252.     // Scan through table looking for zombie children.
  253.     havekids = 0;
  254.     for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){
  255.       if(p->parent != proc)
  256.         continue;
  257.       havekids = 1;
  258.       if(p->state == ZOMBIE){
  259.         // Found one.
  260.         pid = p->pid;
  261.         kfree(p->kstack);
  262.         p->kstack = 0;
  263.         freevm(p->pgdir);
  264.         p->state = UNUSED;
  265.         p->pid = 0;
  266.         p->parent = 0;
  267.         p->name[0] = 0;
  268.         p->killed = 0;
  269.         release(&ptable.lock);
  270.         return pid;
  271.       }
  272.     }
  273.  
  274.     // No point waiting if we don't have any children.
  275.     if(!havekids || proc->killed){
  276.       release(&ptable.lock);
  277.       return -1;
  278.     }
  279.  
  280.     // Wait for children to exit.  (See wakeup1 call in proc_exit.)
  281.     sleep(proc, &ptable.lock);  //DOC: wait-sleep
  282.   }
  283. }
  284.  
  285. // Per-CPU process scheduler.
  286. // Each CPU calls scheduler() after setting itself up.
  287. // Scheduler never returns.  It loops, doing:
  288. //  - choose a process to run
  289. //  - swtch to start running that process
  290. //  - eventually that process transfers control
  291. //      via swtch back to the scheduler.
  292. void
  293. scheduler(void)
  294. {
  295.   struct proc *p;
  296.   int seed=0;
  297.   for(;;){
  298.     // Enable interrupts on this processor.
  299.     sti();
  300.     seed++;
  301.    // winner = lcg64_temper(seed) % num_tickets;
  302.     winner = lcg_rand(seed) % num_tickets;
  303.  
  304.    
  305.     // Loop over process table looking for process to run.
  306.     acquire(&ptable.lock);
  307.     for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){
  308.       if(p->state != RUNNABLE)
  309.         continue;
  310.  
  311.       // Switch to chosen process.  It is the process's job
  312.       // to release ptable.lock and then reacquire it
  313.       // before jumping back to us.
  314.       proc = p;
  315.       switchuvm(p);
  316.       p->state = RUNNING;
  317.       swtch(&cpu->scheduler, proc->context);
  318.       switchkvm();
  319.  
  320.       // Process is done running for now.
  321.       // It should have changed its p->state before coming back.
  322.       proc = 0;
  323.     }
  324.     release(&ptable.lock);
  325.  
  326.   }
  327. }
  328.  
  329. // Enter scheduler.  Must hold only ptable.lock
  330. // and have changed proc->state.
  331. void
  332. sched(void)
  333. {
  334.   int intena;
  335.  
  336.   if(!holding(&ptable.lock))
  337.     panic("sched ptable.lock");
  338.   if(cpu->ncli != 1)
  339.     panic("sched locks");
  340.   if(proc->state == RUNNING)
  341.     panic("sched running");
  342.   if(readeflags()&FL_IF)
  343.     panic("sched interruptible");
  344.   intena = cpu->intena;
  345.   swtch(&proc->context, cpu->scheduler);
  346.   cpu->intena = intena;
  347. }
  348.  
  349. // Give up the CPU for one scheduling round.
  350. void
  351. yield(void)
  352. {
  353.   acquire(&ptable.lock);  //DOC: yieldlock
  354.   proc->state = RUNNABLE;
  355.   sched();
  356.   release(&ptable.lock);
  357. }
  358.  
  359. // A fork child's very first scheduling by scheduler()
  360. // will swtch here.  "Return" to user space.
  361. void
  362. forkret(void)
  363. {
  364.   // Still holding ptable.lock from scheduler.
  365.   release(&ptable.lock);
  366.  
  367.   // Return to "caller", actually trapret (see allocproc).
  368. }
  369.  
  370. // Atomically release lock and sleep on chan.
  371. // Reacquires lock when awakened.
  372. void
  373. sleep(void *chan, struct spinlock *lk)
  374. {
  375.   if(proc == 0)
  376.     panic("sleep");
  377.  
  378.   if(lk == 0)
  379.     panic("sleep without lk");
  380.  
  381.   // Must acquire ptable.lock in order to
  382.   // change p->state and then call sched.
  383.   // Once we hold ptable.lock, we can be
  384.   // guaranteed that we won't miss any wakeup
  385.   // (wakeup runs with ptable.lock locked),
  386.   // so it's okay to release lk.
  387.   if(lk != &ptable.lock){  //DOC: sleeplock0
  388.     acquire(&ptable.lock);  //DOC: sleeplock1
  389.     release(lk);
  390.   }
  391.  
  392.   // Go to sleep.
  393.   proc->chan = chan;
  394.   proc->state = SLEEPING;
  395.   sched();
  396.  
  397.   // Tidy up.
  398.   proc->chan = 0;
  399.  
  400.   // Reacquire original lock.
  401.   if(lk != &ptable.lock){  //DOC: sleeplock2
  402.     release(&ptable.lock);
  403.     acquire(lk);
  404.   }
  405. }
  406.  
  407. // Wake up all processes sleeping on chan.
  408. // The ptable lock must be held.
  409. static void
  410. wakeup1(void *chan)
  411. {
  412.   struct proc *p;
  413.  
  414.   for(p = ptable.proc; p < &ptable.proc[NPROC]; p++)
  415.     if(p->state == SLEEPING && p->chan == chan)
  416.       p->state = RUNNABLE;
  417. }
  418.  
  419. // Wake up all processes sleeping on chan.
  420. void
  421. wakeup(void *chan)
  422. {
  423.   acquire(&ptable.lock);
  424.   wakeup1(chan);
  425.   release(&ptable.lock);
  426. }
  427.  
  428. // Kill the process with the given pid.
  429. // Process won't exit until it returns
  430. // to user space (see trap in trap.c).
  431. int
  432. kill(int pid)
  433. {
  434.   struct proc *p;
  435.  
  436.   acquire(&ptable.lock);
  437.   for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){
  438.     if(p->pid == pid){
  439.       p->killed = 1;
  440.       // Wake process from sleep if necessary.
  441.       if(p->state == SLEEPING)
  442.         p->state = RUNNABLE;
  443.       release(&ptable.lock);
  444.       return 0;
  445.     }
  446.   }
  447.   release(&ptable.lock);
  448.   return -1;
  449. }
  450.  
  451. // Print a process listing to console.  For debugging.
  452. // Runs when user types ^P on console.
  453. // No lock to avoid wedging a stuck machine further.
  454.  
  455. int
  456. lottery(int tickets, int pid)
  457. {
  458.   int i;
  459.   struct proc *p;
  460.  
  461.   //acquire(&proc_table_lock);
  462.   acquire(&ptable.lock); //mona2
  463.   for(i = 0; i < NPROC; i++){
  464.     p = &proc[i];
  465.  
  466.     if(p->pid != pid)
  467.       continue;
  468.  
  469.     if(p->state == UNUSED)
  470.       return -1;
  471.  
  472.     if(p->state == RUNNING || p->state == RUNNABLE)
  473.       num_tickets += (tickets - p->tickets);
  474.  
  475.     p->tickets = tickets;
  476.     //release(&proc_table_lock);
  477.  
  478.     release(&ptable.lock); //mona2
  479.     return 0;
  480.    }
  481.  
  482. }
  483.  
  484.  
  485. void
  486. procdump(void)
  487. {
  488.   static char *states[] = {
  489.   [UNUSED]    "unused",
  490.   [EMBRYO]    "embryo",
  491.   [SLEEPING]  "sleep ",
  492.   [RUNNABLE]  "runble",
  493.   [RUNNING]   "run   ",
  494.   [ZOMBIE]    "zombie"
  495.   };
  496.   int i;
  497.   struct proc *p;
  498.   char *state;
  499.   uint pc[10];
  500.  
  501.   for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){
  502.     if(p->state == UNUSED)
  503.       continue;
  504.     if(p->state >= 0 && p->state < NELEM(states) && states[p->state])
  505.       state = states[p->state];
  506.     else
  507.       state = "???";
  508.     cprintf("%d %s %s", p->pid, state, p->name);
  509.     if(p->state == SLEEPING){
  510.       getcallerpcs((uint*)p->context->ebp+2, pc);
  511.       for(i=0; i<10 && pc[i] != 0; i++)
  512.         cprintf(" %p", pc[i]);
  513.     } // end if
  514.     cprintf("\n");
  515.  
  516. } // end for
  517.  
  518. } // you need to add this
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement