Vcores are unmapped by message receivers
authorBarret Rhoden <brho@cs.berkeley.edu>
Fri, 19 Mar 2010 01:39:10 +0000 (18:39 -0700)
committerKevin Klues <klueska@cs.berkeley.edu>
Thu, 3 Nov 2011 00:35:40 +0000 (17:35 -0700)
Documentation/process-internals.txt
kern/src/process.c
kern/src/resource.c

index 4db1bbf..ca00168 100644 (file)
@@ -551,6 +551,22 @@ we could not use the vcore/pcoremappings).  There should not be any issues
 with the new process sending messages to the pcore before the core is sorted,
 since a_msgs are delivered in order.
 
+Another tricky part is the seq_ctr used to signal userspace of changes to the
+coremap or num_vcores (coremap_seqctr).  While we may not even need this in the
+long run, it still seems like it could be useful.  The trickiness comes from
+when we update the seq_ctr when we are unmapping vcores on the receive side of a
+message (like __death or __preempt).  We'd rather not have each pcore contend on
+the seq_ctr cache line (let alone any locking) while they perform a somewhat
+data-parallel task.  So we continue to have the sending core handle the seq_ctr
+upping and downing.  This works, since the "unlocking" happens after messages
+are sent, which means the receiving core is no longer in userspace (if there is
+a delay, it is because the remote core is in the kernel, possibly with
+interrupts disabled).  Because of this, userspace will be unable to read the new
+value of the seq_ctr before the IPI hits and does the unmapping that the seq_ctr
+protects/advertises.  This is most likely true.  It wouldn't be if the "last IPI
+was sent" flag clears before the IPI actually hit the other core.
+
+
 4.9: Future Broadcast/Messaging Needs
 ---------------------------
 Currently, messaging is serialized.  Broadcast IPIs exist, but the active
index c1f24ed..93160e3 100644 (file)
@@ -592,7 +592,7 @@ void proc_destroy(struct proc *p)
                                           (void *SNT)0, (void *SNT)0, (void *SNT)0);
                        __seq_start_write(&p->procinfo->coremap_seqctr);
                        // TODO: might need to sort num_vcores too later (VC#)
-                       __unmap_vcore(p, 0);
+                       /* vcore is unmapped on the receive side */
                        __seq_end_write(&p->procinfo->coremap_seqctr);
                        #if 0
                        /* right now, RUNNING_S only runs on a mgmt core (0), not cores
@@ -884,15 +884,19 @@ bool __proc_take_cores(struct proc *SAFE p, uint32_t *pcorelist,
        __seq_start_write(&p->procinfo->coremap_seqctr);
        for (int i = 0; i < num; i++) {
                vcoreid = get_vcoreid(p, pcorelist[i]);
+               // while ugly, this is done to facilitate merging with take_all_cores
                pcoreid = p->procinfo->vcoremap[vcoreid].pcoreid;
                assert(pcoreid == pcorelist[i]);
                if (message) {
                        if (pcoreid == core_id())
                                self_ipi_pending = TRUE;
                        send_active_message(pcoreid, message, arg0, arg1, arg2);
+               } else {
+                       /* if there was a msg, the vcore is unmapped on the receive side.
+                        * o/w, we need to do it here. */
+                       __unmap_vcore(p, vcoreid);
                }
                // give the pcore back to the idlecoremap
-               __unmap_vcore(p, vcoreid);
                put_idle_core(pcoreid);
        }
        p->procinfo->num_vcores -= num;
@@ -935,10 +939,14 @@ bool __proc_take_allcores(struct proc *SAFE p, amr_t message,
                        if (pcoreid == core_id())
                                self_ipi_pending = TRUE;
                        send_active_message(pcoreid, message, arg0, arg1, arg2);
+               } else {
+                       /* if there was a msg, the vcore is unmapped on the receive side.
+                        * o/w, we need to do it here. */
+                       __unmap_vcore(p, active_vcoreid);
                }
                // give the pcore back to the idlecoremap
-               __unmap_vcore(p, active_vcoreid);
                put_idle_core(pcoreid);
+               active_vcoreid++; // for the next loop, skip the one we just used
        }
        p->procinfo->num_vcores = 0;
        __seq_end_write(&p->procinfo->coremap_seqctr);
@@ -1032,8 +1040,8 @@ void __startcore(trapframe_t *tf, uint32_t srcid, void * a0, void * a1,
        trapframe_t local_tf;
        trapframe_t *tf_to_pop = (trapframe_t *CT(1))a1;
 
-       printd("[kernel] Startcore on physical core %d for Process %d\n",
-              coreid, p_to_run->pid);
+       printd("[kernel] startcore on physical core %d for process %d's vcore %d\n",
+              coreid, p_to_run->pid, get_vcoreid(p_to_run, coreid));
        assert(p_to_run);
        // TODO: handle silly state (HSS)
        if (!tf_to_pop) {
@@ -1065,6 +1073,12 @@ void abandon_core(void)
 void __death(trapframe_t *tf, uint32_t srcid, void *SNT a0, void *SNT a1,
              void *SNT a2)
 {
+       uint32_t coreid = core_id();
+       if (current) {
+               printd("[kernel] death on physical core %d for process %d's vcore %d\n",
+                      coreid, current->pid, get_vcoreid(current, coreid));
+               __unmap_vcore(current, coreid);
+       }
        abandon_core();
 }
 
index ad8f97c..46be3df 100644 (file)
@@ -114,6 +114,7 @@ ssize_t core_request(struct proc *p)
                                 * this core, for now, since we don't handle async calls) */
                                __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);
                                __seq_end_write(&p->procinfo->coremap_seqctr);
                                // will need to give up this core / idle later (sync)