Breaks proc_run() into _S and _M functions
authorBarret Rhoden <brho@cs.berkeley.edu>
Fri, 24 Feb 2012 22:47:05 +0000 (14:47 -0800)
committerBarret Rhoden <brho@cs.berkeley.edu>
Mon, 27 Feb 2012 21:27:59 +0000 (13:27 -0800)
Eventually, proc_run_m will be called internally (or will go away
completely).

kern/include/process.h
kern/src/manager.c
kern/src/process.c
kern/src/schedule.c
kern/src/syscall.c

index 34d8001..c0f44d9 100644 (file)
@@ -17,7 +17,7 @@
 /* Process States.  Not 100% on the names yet.  RUNNABLE_* are waiting to go to
  * RUNNING_*.  For instance, RUNNABLE_M is expecting to go to RUNNING_M.  It
  * could be waiting for it's timeslice, or possibly for all the cores it asked
 /* Process States.  Not 100% on the names yet.  RUNNABLE_* are waiting to go to
  * RUNNING_*.  For instance, RUNNABLE_M is expecting to go to RUNNING_M.  It
  * could be waiting for it's timeslice, or possibly for all the cores it asked
- * for.  You use proc_run() to transition between these states.
+ * for.
  *
  * Difference between the _M and the _S states:
  * - _S : legacy process mode
  *
  * Difference between the _M and the _S states:
  * - _S : legacy process mode
@@ -27,7 +27,7 @@
  * - The time slicing is at a coarser granularity for _M states.  This means
  *   that when you run an _S on a core, it should be interrupted/time sliced
  *   more often, which also means the core should be classified differently for
  * - The time slicing is at a coarser granularity for _M states.  This means
  *   that when you run an _S on a core, it should be interrupted/time sliced
  *   more often, which also means the core should be classified differently for
- *   a while.  Possibly even using it's local APIC timer.
+ *   a while.  Possibly even using its local APIC timer.
  * - A process in an _M state will be informed about changes to its state, e.g.,
  *   will have a handler run in the event of a page fault
  */
  * - A process in an _M state will be informed about changes to its state, e.g.,
  *   will have a handler run in the event of a page fault
  */
@@ -69,7 +69,8 @@ struct proc *pid2proc(pid_t pid);
 bool proc_controls(struct proc *SAFE actor, struct proc *SAFE target);
 void proc_incref(struct proc *p, unsigned int val);
 void proc_decref(struct proc *p);
 bool proc_controls(struct proc *SAFE actor, struct proc *SAFE target);
 void proc_incref(struct proc *p, unsigned int val);
 void proc_decref(struct proc *p);
-void proc_run(struct proc *SAFE p);
+void proc_run_s(struct proc *p);
+void __proc_run_m(struct proc *p);
 void proc_restartcore(void);
 void proc_destroy(struct proc *SAFE p);
 void __proc_switch_to_m(struct proc *p);
 void proc_restartcore(void);
 void proc_destroy(struct proc *SAFE p);
 void __proc_switch_to_m(struct proc *p);
index 35bddfc..32d9aa5 100644 (file)
@@ -67,7 +67,7 @@ char *p_envp[] = {"LD_LIBRARY_PATH=/lib", 0};
        spin_lock(&(p)->proc_lock);                                                  \
        __proc_set_state((p), PROC_RUNNABLE_S);                                      \
        spin_unlock(&(p)->proc_lock);                                                \
        spin_lock(&(p)->proc_lock);                                                  \
        __proc_set_state((p), PROC_RUNNABLE_S);                                      \
        spin_unlock(&(p)->proc_lock);                                                \
-       proc_run((p));                                                               \
+       proc_run_s((p));                                                             \
        proc_decref((p));
 
 #define quick_proc_create(x, p, f)                                               \
        proc_decref((p));
 
 #define quick_proc_create(x, p, f)                                               \
@@ -92,7 +92,7 @@ char *p_envp[] = {"LD_LIBRARY_PATH=/lib", 0};
        p->cache_colors_map = cache_colors_map_alloc();                              \
        for (int i = 0; i < (c); i++)                                                \
                cache_color_alloc(llc_cache, p->cache_colors_map);                       \
        p->cache_colors_map = cache_colors_map_alloc();                              \
        for (int i = 0; i < (c); i++)                                                \
                cache_color_alloc(llc_cache, p->cache_colors_map);                       \
-       proc_run((p));                                                               \
+       proc_run_s((p));                                                             \
        proc_decref((p));
 
 #define quick_proc_color_create(x, p, c, f)                                      \
        proc_decref((p));
 
 #define quick_proc_color_create(x, p, c, f)                                      \
@@ -236,7 +236,7 @@ void manager_klueska()
                panic("what do you want to do?");
                //envs[0] = kfs_proc_create(kfs_lookup_path("fillmeup"));
                __proc_set_state(envs[0], PROC_RUNNABLE_S);
                panic("what do you want to do?");
                //envs[0] = kfs_proc_create(kfs_lookup_path("fillmeup"));
                __proc_set_state(envs[0], PROC_RUNNABLE_S);
-               proc_run(envs[0]);
+               proc_run_s(envs[0]);
                warn("DEPRECATED");
        }
        schedule();
                warn("DEPRECATED");
        }
        schedule();
index fd1e5fa..88049d7 100644 (file)
@@ -411,11 +411,8 @@ static void __set_proc_current(struct proc *p)
        }
 }
 
        }
 }
 
-/* Dispatches a process to run, either on the current core in the case of a
- * RUNNABLE_S, or on its partition in the case of a RUNNABLE_M.  This should
- * never be called to "restart" a core.  This expects that the "instructions"
- * for which core(s) to run this on will be in the vcoremap, which needs to be
- * set externally (give_cores()).
+/* Dispatches a _S process to run on the current core.  This should never be
+ * called to "restart" a core.   
  *
  * This will always return, regardless of whether or not the calling core is
  * being given to a process. (it used to pop the tf directly, before we had
  *
  * This will always return, regardless of whether or not the calling core is
  * being given to a process. (it used to pop the tf directly, before we had
@@ -423,9 +420,8 @@ static void __set_proc_current(struct proc *p)
  *
  * Since it always returns, it will never "eat" your reference (old
  * documentation talks about this a bit). */
  *
  * Since it always returns, it will never "eat" your reference (old
  * documentation talks about this a bit). */
-void proc_run(struct proc *p)
+void proc_run_s(struct proc *p)
 {
 {
-       struct vcore *vc_i;
        spin_lock(&p->proc_lock);
        switch (p->state) {
                case (PROC_DYING):
        spin_lock(&p->proc_lock);
        switch (p->state) {
                case (PROC_DYING):
@@ -446,8 +442,9 @@ void proc_run(struct proc *p)
                         * work. */
                        __map_vcore(p, 0, core_id()); // sort of.  this needs work.
                        __seq_end_write(&p->procinfo->coremap_seqctr);
                         * work. */
                        __map_vcore(p, 0, core_id()); // sort of.  this needs work.
                        __seq_end_write(&p->procinfo->coremap_seqctr);
-                       /* incref, since we're saving a reference in current */
+                       /* incref, since we're saving a reference in owning proc */
                        proc_incref(p, 1);
                        proc_incref(p, 1);
+                       /* redundant with proc_startcore, might be able to remove that one*/
                        __set_proc_current(p);
                        /* We restartcore, instead of startcore, since startcore is a bit
                         * lower level and we want a chance to process kmsgs before starting
                        __set_proc_current(p);
                        /* We restartcore, instead of startcore, since startcore is a bit
                         * lower level and we want a chance to process kmsgs before starting
@@ -461,6 +458,28 @@ void proc_run(struct proc *p)
                        /* When the calling core idles, it'll call restartcore and run the
                         * _S process's context. */
                        return;
                        /* When the calling core idles, it'll call restartcore and run the
                         * _S process's context. */
                        return;
+               default:
+                       spin_unlock(&p->proc_lock);
+                       panic("Invalid process state %p in %s()!!", p->state, __FUNCTION__);
+       }
+}
+
+/* Run an _M.  Can be called safely on one that is already running.  Hold the
+ * lock before calling.  Other than state checks, this just starts up the _M's
+ * vcores, much like the second part of give_cores_running.  More specifically,
+ * give_cores_runnable puts cores on the online list, which this then sends
+ * messages to.  give_cores_running immediately puts them on the list and sends
+ * the message.  the two-step style may go out of fashion soon.
+ *
+ * This expects that the "instructions" for which core(s) to run this on will be
+ * in the vcoremap, which needs to be set externally (give_cores()). */
+void __proc_run_m(struct proc *p)
+{
+       struct vcore *vc_i;
+       switch (p->state) {
+               case (PROC_DYING):
+                       printk("Process %d not starting due to async death\n", p->pid);
+                       return;
                case (PROC_RUNNABLE_M):
                        /* vcoremap[i] holds the coreid of the physical core allocated to
                         * this process.  It is set outside proc_run.  For the kernel
                case (PROC_RUNNABLE_M):
                        /* vcoremap[i] holds the coreid of the physical core allocated to
                         * this process.  It is set outside proc_run.  For the kernel
@@ -480,18 +499,21 @@ void proc_run(struct proc *p)
                        } else {
                                warn("Tried to proc_run() an _M with no vcores!");
                        }
                        } else {
                                warn("Tried to proc_run() an _M with no vcores!");
                        }
-                       /* There a subtle race avoidance here.  __proc_startcore can handle
-                        * a death message, but we can't have the startcore come after the
-                        * death message.  Otherwise, it would look like a new process.  So
-                        * we hold the lock til after we send our message, which prevents a
-                        * possible death message.
+                       /* There a subtle race avoidance here (when we unlock after sending
+                        * the message).  __proc_startcore can handle a death message, but
+                        * we can't have the startcore come after the death message.
+                        * Otherwise, it would look like a new process.  So we hold the lock
+                        * til after we send our message, which prevents a possible death
+                        * message.
                         * - Note there is no guarantee this core's interrupts were on, so
                         *   it may not get the message for a while... */
                         * - Note there is no guarantee this core's interrupts were on, so
                         *   it may not get the message for a while... */
-                       spin_unlock(&p->proc_lock);
+                       return;
+               case (PROC_RUNNING_M):
                        return;
                default:
                        return;
                default:
+                       /* unlock just so the monitor can call something that might lock*/
                        spin_unlock(&p->proc_lock);
                        spin_unlock(&p->proc_lock);
-                       panic("Invalid process state %p in proc_run()!!", p->state);
+                       panic("Invalid process state %p in %s()!!", p->state, __FUNCTION__);
        }
 }
 
        }
 }
 
@@ -694,7 +716,7 @@ void __proc_switch_to_m(struct proc *p)
                        __seq_start_write(&p->procinfo->coremap_seqctr);
                        // TODO: (VC#) might need to adjust num_vcores
                        // TODO: (ACR) will need to unmap remotely (receive-side)
                        __seq_start_write(&p->procinfo->coremap_seqctr);
                        // TODO: (VC#) might need to adjust num_vcores
                        // TODO: (ACR) will need to unmap remotely (receive-side)
-                       __unmap_vcore(p, 0);    /* VC# keep in sync with proc_run _S */
+                       __unmap_vcore(p, 0);    /* VC# keep in sync with proc_run_s */
                        __seq_end_write(&p->procinfo->coremap_seqctr);
                        /* change to runnable_m (it's TF is already saved) */
                        __proc_set_state(p, PROC_RUNNABLE_M);
                        __seq_end_write(&p->procinfo->coremap_seqctr);
                        /* change to runnable_m (it's TF is already saved) */
                        __proc_set_state(p, PROC_RUNNABLE_M);
@@ -772,7 +794,7 @@ void __proc_yield_s(struct proc *p, struct trapframe *tf)
        assert(p->state == PROC_RUNNING_S);
        p->env_tf= *tf;
        env_push_ancillary_state(p);                    /* TODO: (HSS) */
        assert(p->state == PROC_RUNNING_S);
        p->env_tf= *tf;
        env_push_ancillary_state(p);                    /* TODO: (HSS) */
-       __unmap_vcore(p, 0);    /* VC# keep in sync with proc_run _S */
+       __unmap_vcore(p, 0);    /* VC# keep in sync with proc_run_s */
        __proc_set_state(p, PROC_RUNNABLE_S);
        schedule_proc(p);
 }
        __proc_set_state(p, PROC_RUNNABLE_S);
        schedule_proc(p);
 }
@@ -1220,12 +1242,12 @@ static void __proc_give_cores_running(struct proc *p, uint32_t *pc_arr,
 /* Gives process p the additional num cores listed in pcorelist.  You must be
  * RUNNABLE_M or RUNNING_M before calling this.  If you're RUNNING_M, this will
  * startup your new cores at the entry point with their virtual IDs (or restore
 /* Gives process p the additional num cores listed in pcorelist.  You must be
  * RUNNABLE_M or RUNNING_M before calling this.  If you're RUNNING_M, this will
  * startup your new cores at the entry point with their virtual IDs (or restore
- * a preemption).  If you're RUNNABLE_M, you should call proc_run after this so
- * that the process can start to use its cores.
+ * a preemption).  If you're RUNNABLE_M, you should call __proc_run_m after this
+ * so that the process can start to use its cores.
  *
  * If you're *_S, make sure your core0's TF is set (which is done when coming in
  * via arch/trap.c and we are RUNNING_S), change your state, then call this.
  *
  * If you're *_S, make sure your core0's TF is set (which is done when coming in
  * via arch/trap.c and we are RUNNING_S), change your state, then call this.
- * Then call proc_run().
+ * Then call __proc_run_m().
  *
  * The reason I didn't bring the _S cases from core_request over here is so we
  * can keep this family of calls dealing with only *_Ms, to avoiding caring if
  *
  * The reason I didn't bring the _S cases from core_request over here is so we
  * can keep this family of calls dealing with only *_Ms, to avoiding caring if
@@ -1654,7 +1676,7 @@ out_failed:
 }
 
 /* Kernel message handler to start a process's context on this core, when the
 }
 
 /* Kernel message handler to start a process's context on this core, when the
- * core next considers running a process.  Tightly coupled with proc_run().
+ * core next considers running a process.  Tightly coupled with __proc_run_m().
  * Interrupts are disabled. */
 void __startcore(struct trapframe *tf, uint32_t srcid, long a0, long a1, long a2)
 {
  * Interrupts are disabled. */
 void __startcore(struct trapframe *tf, uint32_t srcid, long a0, long a1, long a2)
 {
@@ -1671,7 +1693,7 @@ void __startcore(struct trapframe *tf, uint32_t srcid, long a0, long a1, long a2
         * if no one else is there.  this is an optimization, since we expect to
         * send these __startcores to idles cores, and this saves a scramble to
         * incref when all of the cores restartcore/startcore later.  Keep in sync
         * if no one else is there.  this is an optimization, since we expect to
         * send these __startcores to idles cores, and this saves a scramble to
         * incref when all of the cores restartcore/startcore later.  Keep in sync
-        * with __proc_give_cores() and proc_run(). */
+        * with __proc_give_cores() and __proc_run_m(). */
        if (!pcpui->cur_proc) {
                pcpui->cur_proc = p_to_run;     /* install the ref to cur_proc */
                lcr3(p_to_run->env_cr3);        /* load the page tables to match cur_proc */
        if (!pcpui->cur_proc) {
                pcpui->cur_proc = p_to_run;     /* install the ref to cur_proc */
                lcr3(p_to_run->env_cr3);        /* load the page tables to match cur_proc */
index bebae8e..a64e9ba 100644 (file)
@@ -102,6 +102,8 @@ void schedule_proc(struct proc *p)
  *
  * Using irqsave spinlocks for now, since this could be called from a timer
  * interrupt handler (though ought to be in a bottom half or something).
  *
  * Using irqsave spinlocks for now, since this could be called from a timer
  * interrupt handler (though ought to be in a bottom half or something).
+ *     - TODO: the functions we call aren't irqsafe (proc_run, for instance), so
+ *     we'll have to not call this directly from interrupt context.
  */
 void schedule(void)
 {
  */
 void schedule(void)
 {
@@ -141,10 +143,12 @@ void schedule(void)
                                 * someone else could make p an _S (in theory), and then we
                                 * would be calling this with an inedible ref (which is
                                 * currently a concern). */
                                 * someone else could make p an _S (in theory), and then we
                                 * would be calling this with an inedible ref (which is
                                 * currently a concern). */
-                               proc_run(p); /* trying to run a RUNNABLE_M here */
+                               spin_lock(&p->proc_lock);
+                               __proc_run_m(p); /* trying to run a RUNNABLE_M here */
+                               spin_unlock(&p->proc_lock);
                } else {
                        /* _S proc, just run it */
                } else {
                        /* _S proc, just run it */
-                       proc_run(p);
+                       proc_run_s(p);
                }
                /* decref the ref from the TAILQ */
                proc_decref(p);
                }
                /* decref the ref from the TAILQ */
                proc_decref(p);
index ef1ec78..fae2b19 100644 (file)
@@ -547,7 +547,7 @@ early_error:
 success:
        /* Here's how we'll restart the new (or old) process: */
        spin_lock(&p->proc_lock);
 success:
        /* Here's how we'll restart the new (or old) process: */
        spin_lock(&p->proc_lock);
-       __unmap_vcore(p, 0);    /* VC# keep in sync with proc_run _S */
+       __unmap_vcore(p, 0);    /* VC# keep in sync with proc_run_s */
        __proc_set_state(p, PROC_RUNNABLE_S);
        schedule_proc(p);
        spin_unlock(&p->proc_lock);
        __proc_set_state(p, PROC_RUNNABLE_S);
        schedule_proc(p);
        spin_unlock(&p->proc_lock);