Clarifies/fixes some issues with __preempt and MCS
authorBarret Rhoden <brho@cs.berkeley.edu>
Mon, 24 Oct 2011 18:00:08 +0000 (11:00 -0700)
committerBarret Rhoden <brho@cs.berkeley.edu>
Thu, 15 Dec 2011 22:48:40 +0000 (14:48 -0800)
We need the wmb() in __preempt, which is racing with __map_vcore()
(among other things).  Basically, we need to make sure we don't give out
the vcore while cleaning up the vcore.  Once we __unmap_vcore(), we need
to never touch it again til it is mapped.

Likewise, the MCS-PDR code can quite easily see a situation where a core
is preempted but is still mapped.  The old assertion was mostly to catch
bugs, but that wasn't a "safe" check, since the preempting and unmapping
isn't atomic from the perspective of other cores.

kern/src/process.c
user/parlib/mcs.c

index 702ab72..19ce670 100644 (file)
@@ -1687,6 +1687,7 @@ void __preempt(struct trapframe *tf, uint32_t srcid, long a0, long a1, long a2)
        vcpd->preempt_tf = *pcpui->cur_tf;
        save_fp_state(&vcpd->preempt_anc);
        __seq_start_write(&vcpd->preempt_tf_valid);
+       wmb();  /* make sure everything else hits before we unmap */
        __unmap_vcore(p, vcoreid);
        /* We won't restart the process later.  current gets cleared later when we
         * notice there is no owning_proc and we have nothing to do (smp_idle,
index 7cc4818..b34556a 100644 (file)
@@ -194,12 +194,13 @@ void __ensure_qnode_runs(struct mcs_pdr_qnode *qnode)
 {
        assert(qnode);
        if (vcore_is_preempted(qnode->vcoreid)) {
-               assert(!vcore_is_mapped(qnode->vcoreid));
+               /* Note that at this moment, the vcore could still be mapped (we're
+                * racing with __preempt.  If that happens, we'll just fail the
+                * sys_change_vcore(), and next time __ensure runs we'll get it. */
                /* We want to recover them from preemption.  Since we know they have
                 * notifs disabled, they will need to be directly restarted, so we can
                 * skip the other logic and cut straight to the sys_change_vcore() */
                sys_change_vcore(qnode->vcoreid, FALSE);
-               cmb();
        }
 }