diff options
| author | Austin Clements <amdragon@mit.edu> | 2010-09-02 04:15:17 -0400 | 
|---|---|---|
| committer | Austin Clements <amdragon@mit.edu> | 2010-09-02 04:15:17 -0400 | 
| commit | d8828817d72962a6220cb1fca315cab4bbf6d0a3 (patch) | |
| tree | 018515d8e7ce0c6681121914fb9d78e9955025b3 | |
| parent | dd3ecd42cd6c8dee72e5212848cd8037d47f81dd (diff) | |
| download | xv6-labs-d8828817d72962a6220cb1fca315cab4bbf6d0a3.tar.gz xv6-labs-d8828817d72962a6220cb1fca315cab4bbf6d0a3.tar.bz2 xv6-labs-d8828817d72962a6220cb1fca315cab4bbf6d0a3.zip | |
Rearrange proc.h and proc.c to get our action-packed spreads back (mostly).  They also make sense in this order, so it's not just for page layout.
| -rw-r--r-- | proc.c | 172 | ||||
| -rw-r--r-- | proc.h | 59 | ||||
| -rw-r--r-- | runoff.spec | 15 | 
3 files changed, 126 insertions, 120 deletions
| @@ -193,6 +193,92 @@ fork(void)    return pid;  } +// Exit the current process.  Does not return. +// An exited process remains in the zombie state +// until its parent calls wait() to find out it exited. +void +exit(void) +{ +  struct proc *p; +  int fd; + +  if(proc == initproc) +    panic("init exiting"); + +  // Close all open files. +  for(fd = 0; fd < NOFILE; fd++){ +    if(proc->ofile[fd]){ +      fileclose(proc->ofile[fd]); +      proc->ofile[fd] = 0; +    } +  } + +  iput(proc->cwd); +  proc->cwd = 0; + +  acquire(&ptable.lock); + +  // Parent might be sleeping in wait(). +  wakeup1(proc->parent); + +  // Pass abandoned children to init. +  for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){ +    if(p->parent == proc){ +      p->parent = initproc; +      if(p->state == ZOMBIE) +        wakeup1(initproc); +    } +  } + +  // Jump into the scheduler, never to return. +  proc->state = ZOMBIE; +  sched(); +  panic("zombie exit"); +} + +// Wait for a child process to exit and return its pid. +// Return -1 if this process has no children. +int +wait(void) +{ +  struct proc *p; +  int havekids, pid; + +  acquire(&ptable.lock); +  for(;;){ +    // Scan through table looking for zombie children. +    havekids = 0; +    for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){ +      if(p->parent != proc) +        continue; +      havekids = 1; +      if(p->state == ZOMBIE){ +        // Found one. +        pid = p->pid; +        kfree(p->kstack); +        p->kstack = 0; +        freevm(p->pgdir); +        p->state = UNUSED; +        p->pid = 0; +        p->parent = 0; +        p->name[0] = 0; +        p->killed = 0; +        release(&ptable.lock); +        return pid; +      } +    } + +    // No point waiting if we don't have any children. +    if(!havekids || proc->killed){ +      release(&ptable.lock); +      return -1; +    } + +    // Wait for children to exit.  (See wakeup1 call in proc_exit.) +    sleep(proc, &ptable.lock);  //DOC: wait-sleep +  } +} +  //PAGEBREAK: 42  // Per-CPU process scheduler.  // Each CPU calls scheduler() after setting itself up. @@ -357,89 +443,3 @@ kill(int pid)    return -1;  } -// Exit the current process.  Does not return. -// An exited process remains in the zombie state -// until its parent calls wait() to find out it exited. -void -exit(void) -{ -  struct proc *p; -  int fd; - -  if(proc == initproc) -    panic("init exiting"); - -  // Close all open files. -  for(fd = 0; fd < NOFILE; fd++){ -    if(proc->ofile[fd]){ -      fileclose(proc->ofile[fd]); -      proc->ofile[fd] = 0; -    } -  } - -  iput(proc->cwd); -  proc->cwd = 0; - -  acquire(&ptable.lock); - -  // Parent might be sleeping in wait(). -  wakeup1(proc->parent); - -  // Pass abandoned children to init. -  for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){ -    if(p->parent == proc){ -      p->parent = initproc; -      if(p->state == ZOMBIE) -        wakeup1(initproc); -    } -  } - -  // Jump into the scheduler, never to return. -  proc->state = ZOMBIE; -  sched(); -  panic("zombie exit"); -} - -// Wait for a child process to exit and return its pid. -// Return -1 if this process has no children. -int -wait(void) -{ -  struct proc *p; -  int havekids, pid; - -  acquire(&ptable.lock); -  for(;;){ -    // Scan through table looking for zombie children. -    havekids = 0; -    for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){ -      if(p->parent != proc) -        continue; -      havekids = 1; -      if(p->state == ZOMBIE){ -        // Found one. -        pid = p->pid; -        kfree(p->kstack); -        p->kstack = 0; -        freevm(p->pgdir); -        p->state = UNUSED; -        p->pid = 0; -        p->parent = 0; -        p->name[0] = 0; -        p->killed = 0; -        release(&ptable.lock); -        return pid; -      } -    } - -    // No point waiting if we don't have any children. -    if(!havekids || proc->killed){ -      release(&ptable.lock); -      return -1; -    } - -    // Wait for children to exit.  (See wakeup1 call in proc_exit.) -    sleep(proc, &ptable.lock);  //DOC: wait-sleep -  } -} - @@ -8,6 +8,36 @@  #define SEG_TSS   6  // this process's task state  #define NSEGS     7 +// Per-CPU state +struct cpu { +  uchar id;                    // Local APIC ID; index into cpus[] below +  struct context *scheduler;   // Switch here to enter scheduler +  struct taskstate ts;         // Used by x86 to find stack for interrupt +  struct segdesc gdt[NSEGS];   // x86 global descriptor table +  volatile uint booted;        // Has the CPU started? +  int ncli;                    // Depth of pushcli nesting. +  int intena;                  // Were interrupts enabled before pushcli? +   +  // Cpu-local storage variables; see below +  struct cpu *cpu; +  struct proc *proc; +}; + +extern struct cpu cpus[NCPU]; +extern int ncpu; + +// Per-CPU variables, holding pointers to the +// current cpu and to the current process. +// The asm suffix tells gcc to use "%gs:0" to refer to cpu +// and "%gs:4" to refer to proc.  ksegment sets up the +// %gs segment register so that %gs refers to the memory +// holding those two variables in the local cpu's struct cpu. +// This is similar to how thread-local variables are implemented +// in thread libraries such as Linux pthreads. +extern struct cpu *cpu asm("%gs:0");       // This cpu. +extern struct proc *proc asm("%gs:4");     // Current proc on this cpu. + +//PAGEBREAK: 17  // Saved registers for kernel context switches.  // Don't need to save all the segment registers (%cs, etc),  // because they are constant across kernel contexts. @@ -50,32 +80,3 @@ struct proc {  //   original data and bss  //   fixed-size stack  //   expandable heap - -// Per-CPU state -struct cpu { -  uchar id;                    // Local APIC ID; index into cpus[] below -  struct context *scheduler;   // Switch here to enter scheduler -  struct taskstate ts;         // Used by x86 to find stack for interrupt -  struct segdesc gdt[NSEGS];   // x86 global descriptor table -  volatile uint booted;        // Has the CPU started? -  int ncli;                    // Depth of pushcli nesting. -  int intena;                  // Were interrupts enabled before pushcli? -   -  // Cpu-local storage variables; see below -  struct cpu *cpu; -  struct proc *proc; -}; - -extern struct cpu cpus[NCPU]; -extern int ncpu; - -// Per-CPU variables, holding pointers to the -// current cpu and to the current process. -// The asm suffix tells gcc to use "%gs:0" to refer to cpu -// and "%gs:4" to refer to proc.  ksegment sets up the -// %gs segment register so that %gs refers to the memory -// holding those two variables in the local cpu's struct cpu. -// This is similar to how thread-local variables are implemented -// in thread libraries such as Linux pthreads. -extern struct cpu *cpu asm("%gs:0");       // This cpu. -extern struct proc *proc asm("%gs:4");     // Current proc on this cpu. diff --git a/runoff.spec b/runoff.spec index fe960ce..9d87528 100644 --- a/runoff.spec +++ b/runoff.spec @@ -20,22 +20,27 @@ sheet1: left  even: bootasm.S  # mild preference  even: bootother.S  # mild preference -even: bootmain.S  # mild preference +even: bootmain.c  # mild preference  even: main.c  # mp.c don't care at all  # even: initcode.S  # odd: init.c  # spinlock.h either -left: spinlock.c  # mild preference -even: proc.h  # mild preference +left: spinlock.h  # mild preference +even: spinlock.h  # mild preference + +# This gets struct proc and allocproc on the same spread +right: proc.h +odd: proc.h  # goal is to have two action-packed 2-page spreads,  # one with -#     allocproc userinit growproc fork +#     userinit growproc fork exit wait  # and another with  #     scheduler sched yield forkret sleep wakeup1 wakeup -right: proc.c   # VERY important +left: proc.c   # VERY important +odd: proc.c   # VERY important  # setjmp.S either  # vm.c either | 
