Process refcnt optimizations
authorBarret Rhoden <brho@cs.berkeley.edu>
Tue, 4 Oct 2011 21:06:08 +0000 (14:06 -0700)
committerKevin Klues <klueska@cs.berkeley.edu>
Thu, 3 Nov 2011 00:36:08 +0000 (17:36 -0700)
The __startcore optimization is similar to how it was before, but I
separated it from the owning_proc commit to show that it isn't necessary
and to make it more clear.

The kthread optimization is just a comment for now, since it's not clear
to me which way is best (if any).

kern/src/kthread.c
kern/src/process.c

index 277e87b..acc4248 100644 (file)
@@ -80,9 +80,9 @@ void sleep_on(struct semaphore *sem)
        *kth_stack_poison = 0;
 #endif /* __CONFIG_KTHREAD_POISON__ */
        /* The kthread needs to stay in the process context (if there is one), but
-        * we want the core (which could be a vcore) to stay in the context too.  If
-        * we want to leave, we'll need to do that in smp_idle() or elsewhere in the
-        * code. */
+        * we want the core (which could be a vcore) to stay in the context too.  In
+        * the future, we could check owning_proc. If it isn't set, we could leave
+        * the process context and transfer the refcnt to kthread->proc. */
        kthread->proc = current;
        /* kthread tracks the syscall it is working on, which implies errno */
        kthread->sysc = pcpui->cur_sysc;
index a7220af..59d18bc 100644 (file)
@@ -535,9 +535,9 @@ void proc_run(struct proc *p)
                         * message, a0 = struct proc*, a1 = struct trapframe*.   */
                        if (p->procinfo->num_vcores) {
                                __proc_set_state(p, PROC_RUNNING_M);
-                               /* Up the refcnt, since num_vcores are going to start using this
-                                * process and have it loaded in their 'current'. */
-                               proc_incref(p, p->procinfo->num_vcores);
+                               /* Up the refcnt, to avoid the n refcnt upping on the
+                                * destination cores.  Keep in sync with __startcore */
+                               proc_incref(p, p->procinfo->num_vcores * 2);
                                /* Send kernel messages to all online vcores (which were added
                                 * to the list and mapped in __proc_give_cores()), making them
                                 * turn online */
@@ -1169,8 +1169,8 @@ void __proc_give_cores(struct proc *SAFE p, uint32_t *pcorelist, size_t num)
                        break;
                case (PROC_RUNNING_M):
                        /* Up the refcnt, since num cores are going to start using this
-                        * process and have it loaded in their 'current'. */
-                       proc_incref(p, num);
+                        * process and have it loaded in their owning_proc and 'current'. */
+                       proc_incref(p, num * 2);        /* keep in sync with __startcore */
                        __seq_start_write(&p->procinfo->coremap_seqctr);
                        p->procinfo->num_vcores += num;
                        for (int i = 0; i < num; i++) {
@@ -1441,6 +1441,17 @@ void __startcore(struct trapframe *tf, uint32_t srcid, long a0, long a1, long a2
        assert(!pcpui->owning_proc);
        /* the sender of the amsg increfed already for this saved ref to p_to_run */
        pcpui->owning_proc = p_to_run;
+       /* sender increfed again, assuming we'd install to cur_proc.  only do this
+        * 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(). */
+       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 */
+       } else {
+               proc_decref(p_to_run);          /* can't install, decref the extra one */
+       }
        /* Note we are not necessarily in the cr3 of p_to_run */
        vcoreid = get_vcoreid(p_to_run, coreid);
        vcpd = &p_to_run->procdata->vcore_preempt_data[vcoreid];