os161-1.99
 All Data Structures
proc.c
00001 /*
00002  * Copyright (c) 2013
00003  *      The President and Fellows of Harvard College.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  * 1. Redistributions of source code must retain the above copyright
00009  *    notice, this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright
00011  *    notice, this list of conditions and the following disclaimer in the
00012  *    documentation and/or other materials provided with the distribution.
00013  * 3. Neither the name of the University nor the names of its contributors
00014  *    may be used to endorse or promote products derived from this software
00015  *    without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
00018  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED.  IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
00021  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00022  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00023  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00024  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00025  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00026  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00027  * SUCH DAMAGE.
00028  */
00029 
00030 /*
00031  * Process support.
00032  *
00033  * There is (intentionally) not much here; you will need to add stuff
00034  * and maybe change around what's already present.
00035  *
00036  * p_lock is intended to be held when manipulating the pointers in the
00037  * proc structure, not while doing any significant work with the
00038  * things they point to. Rearrange this (and/or change it to be a
00039  * regular lock) as needed.
00040  *
00041  * Unless you're implementing multithreaded user processes, the only
00042  * process that will have more than one thread is the kernel process.
00043  */
00044 
00045 #include <types.h>
00046 #include <proc.h>
00047 #include <current.h>
00048 #include <addrspace.h>
00049 #include <vnode.h>
00050 #include <vfs.h>
00051 #include <synch.h>
00052 #include <kern/fcntl.h>  
00053 
00054 /*
00055  * The process for the kernel; this holds all the kernel-only threads.
00056  */
00057 struct proc *kproc;
00058 
00059 /*
00060  * Mechanism for making the kernel menu thread sleep while processes are running
00061  */
00062 #ifdef UW
00063 /* count of the number of processes, excluding kproc */
00064 static unsigned int proc_count;
00065 /* provides mutual exclusion for proc_count */
00066 /* it would be better to use a lock here, but we use a semaphore because locks are not implemented in the base kernel */ 
00067 static struct semaphore *proc_count_mutex;
00068 /* used to signal the kernel menu thread when there are no processes */
00069 struct semaphore *no_proc_sem;   
00070 #endif  // UW
00071 
00072 
00073 
00074 /*
00075  * Create a proc structure.
00076  */
00077 static
00078 struct proc *
00079 proc_create(const char *name)
00080 {
00081         struct proc *proc;
00082 
00083         proc = kmalloc(sizeof(*proc));
00084         if (proc == NULL) {
00085                 return NULL;
00086         }
00087         proc->p_name = kstrdup(name);
00088         if (proc->p_name == NULL) {
00089                 kfree(proc);
00090                 return NULL;
00091         }
00092 
00093         threadarray_init(&proc->p_threads);
00094         spinlock_init(&proc->p_lock);
00095 
00096         /* VM fields */
00097         proc->p_addrspace = NULL;
00098 
00099         /* VFS fields */
00100         proc->p_cwd = NULL;
00101 
00102 #ifdef UW
00103         proc->console = NULL;
00104 #endif // UW
00105 
00106         return proc;
00107 }
00108 
00109 /*
00110  * Destroy a proc structure.
00111  */
00112 void
00113 proc_destroy(struct proc *proc)
00114 {
00115         /*
00116          * note: some parts of the process structure, such as the address space,
00117          *  are destroyed in sys_exit, before we get here
00118          *
00119          * note: depending on where this function is called from, curproc may not
00120          * be defined because the calling thread may have already detached itself
00121          * from the process.
00122          */
00123 
00124         KASSERT(proc != NULL);
00125         KASSERT(proc != kproc);
00126 
00127         /*
00128          * We don't take p_lock in here because we must have the only
00129          * reference to this structure. (Otherwise it would be
00130          * incorrect to destroy it.)
00131          */
00132 
00133         /* VFS fields */
00134         if (proc->p_cwd) {
00135                 VOP_DECREF(proc->p_cwd);
00136                 proc->p_cwd = NULL;
00137         }
00138 
00139 
00140 #ifndef UW  // in the UW version, space destruction occurs in sys_exit, not here
00141         if (proc->p_addrspace) {
00142                 /*
00143                  * In case p is the currently running process (which
00144                  * it might be in some circumstances, or if this code
00145                  * gets moved into exit as suggested above), clear
00146                  * p_addrspace before calling as_destroy. Otherwise if
00147                  * as_destroy sleeps (which is quite possible) when we
00148                  * come back we'll be calling as_activate on a
00149                  * half-destroyed address space. This tends to be
00150                  * messily fatal.
00151                  */
00152                 struct addrspace *as;
00153 
00154                 as_deactivate();
00155                 as = curproc_setas(NULL);
00156                 as_destroy(as);
00157         }
00158 #endif // UW
00159 
00160 #ifdef UW
00161         if (proc->console) {
00162           vfs_close(proc->console);
00163         }
00164 #endif // UW
00165 
00166         threadarray_cleanup(&proc->p_threads);
00167         spinlock_cleanup(&proc->p_lock);
00168 
00169         kfree(proc->p_name);
00170         kfree(proc);
00171 
00172 #ifdef UW
00173         /* decrement the process count */
00174         /* note: kproc is not included in the process count, but proc_destroy
00175            is never called on kproc (see KASSERT above), so we're OK to decrement
00176            the proc_count unconditionally here */
00177         P(proc_count_mutex); 
00178         KASSERT(proc_count > 0);
00179         proc_count--;
00180         /* signal the kernel menu thread if the process count has reached zero */
00181         if (proc_count == 0) {
00182           V(no_proc_sem);
00183         }
00184         V(proc_count_mutex);
00185 #endif // UW
00186         
00187 
00188 }
00189 
00190 /*
00191  * Create the process structure for the kernel.
00192  */
00193 void
00194 proc_bootstrap(void)
00195 {
00196   kproc = proc_create("[kernel]");
00197   if (kproc == NULL) {
00198     panic("proc_create for kproc failed\n");
00199   }
00200 #ifdef UW
00201   proc_count = 0;
00202   proc_count_mutex = sem_create("proc_count_mutex",1);
00203   if (proc_count_mutex == NULL) {
00204     panic("could not create proc_count_mutex semaphore\n");
00205   }
00206   no_proc_sem = sem_create("no_proc_sem",0);
00207   if (no_proc_sem == NULL) {
00208     panic("could not create no_proc_sem semaphore\n");
00209   }
00210 #endif // UW 
00211 }
00212 
00213 /*
00214  * Create a fresh proc for use by runprogram.
00215  *
00216  * It will have no address space and will inherit the current
00217  * process's (that is, the kernel menu's) current directory.
00218  */
00219 struct proc *
00220 proc_create_runprogram(const char *name)
00221 {
00222         struct proc *proc;
00223         char *console_path;
00224 
00225         proc = proc_create(name);
00226         if (proc == NULL) {
00227                 return NULL;
00228         }
00229 
00230 #ifdef UW
00231         /* open the console - this should always succeed */
00232         console_path = kstrdup("con:");
00233         if (console_path == NULL) {
00234           panic("unable to copy console path name during process creation\n");
00235         }
00236         if (vfs_open(console_path,O_WRONLY,0,&(proc->console))) {
00237           panic("unable to open the console during process creation\n");
00238         }
00239         kfree(console_path);
00240 #endif // UW
00241           
00242         /* VM fields */
00243 
00244         proc->p_addrspace = NULL;
00245 
00246         /* VFS fields */
00247 
00248 #ifdef UW
00249         /* we do not need to acquire the p_lock here, the running thread should
00250            have the only reference to this process */
00251         /* also, acquiring the p_lock is problematic because VOP_INCREF may block */
00252         if (curproc->p_cwd != NULL) {
00253                 VOP_INCREF(curproc->p_cwd);
00254                 proc->p_cwd = curproc->p_cwd;
00255         }
00256 #else // UW
00257         spinlock_acquire(&curproc->p_lock);
00258         if (curproc->p_cwd != NULL) {
00259                 VOP_INCREF(curproc->p_cwd);
00260                 proc->p_cwd = curproc->p_cwd;
00261         }
00262         spinlock_release(&curproc->p_lock);
00263 #endif // UW
00264 
00265 #ifdef UW
00266         /* increment the count of processes */
00267         /* we are assuming that all procs, including those created by fork(),
00268            are created using a call to proc_create_runprogram  */
00269         P(proc_count_mutex); 
00270         proc_count++;
00271         V(proc_count_mutex);
00272 #endif // UW
00273 
00274         return proc;
00275 }
00276 
00277 /*
00278  * Add a thread to a process. Either the thread or the process might
00279  * or might not be current.
00280  */
00281 int
00282 proc_addthread(struct proc *proc, struct thread *t)
00283 {
00284         int result;
00285 
00286         KASSERT(t->t_proc == NULL);
00287 
00288         spinlock_acquire(&proc->p_lock);
00289         result = threadarray_add(&proc->p_threads, t, NULL);
00290         spinlock_release(&proc->p_lock);
00291         if (result) {
00292                 return result;
00293         }
00294         t->t_proc = proc;
00295         return 0;
00296 }
00297 
00298 /*
00299  * Remove a thread from its process. Either the thread or the process
00300  * might or might not be current.
00301  */
00302 void
00303 proc_remthread(struct thread *t)
00304 {
00305         struct proc *proc;
00306         unsigned i, num;
00307 
00308         proc = t->t_proc;
00309         KASSERT(proc != NULL);
00310 
00311         spinlock_acquire(&proc->p_lock);
00312         /* ugh: find the thread in the array */
00313         num = threadarray_num(&proc->p_threads);
00314         for (i=0; i<num; i++) {
00315                 if (threadarray_get(&proc->p_threads, i) == t) {
00316                         threadarray_remove(&proc->p_threads, i);
00317                         spinlock_release(&proc->p_lock);
00318                         t->t_proc = NULL;
00319                         return;
00320                 }
00321         }
00322         /* Did not find it. */
00323         spinlock_release(&proc->p_lock);
00324         panic("Thread (%p) has escaped from its process (%p)\n", t, proc);
00325 }
00326 
00327 /*
00328  * Fetch the address space of the current process. Caution: it isn't
00329  * refcounted. If you implement multithreaded processes, make sure to
00330  * set up a refcount scheme or some other method to make this safe.
00331  */
00332 struct addrspace *
00333 curproc_getas(void)
00334 {
00335         struct addrspace *as;
00336 #ifdef UW
00337         /* Until user processes are created, threads used in testing 
00338          * (i.e., kernel threads) have no process or address space.
00339          */
00340         if (curproc == NULL) {
00341                 return NULL;
00342         }
00343 #endif
00344 
00345         spinlock_acquire(&curproc->p_lock);
00346         as = curproc->p_addrspace;
00347         spinlock_release(&curproc->p_lock);
00348         return as;
00349 }
00350 
00351 /*
00352  * Change the address space of the current process, and return the old
00353  * one.
00354  */
00355 struct addrspace *
00356 curproc_setas(struct addrspace *newas)
00357 {
00358         struct addrspace *oldas;
00359         struct proc *proc = curproc;
00360 
00361         spinlock_acquire(&proc->p_lock);
00362         oldas = proc->p_addrspace;
00363         proc->p_addrspace = newas;
00364         spinlock_release(&proc->p_lock);
00365         return oldas;
00366 }
 All Data Structures