Resolves race with __unmap and __map_vcore()
authorBarret Rhoden <brho@cs.berkeley.edu>
Mon, 26 Sep 2011 20:49:06 +0000 (13:49 -0700)
committerKevin Klues <klueska@cs.berkeley.edu>
Thu, 3 Nov 2011 00:36:07 +0000 (17:36 -0700)
When you send a __preempt message (or __death), the unmapping happens on
the destination core.  If you were to try and give out the vcore
immediately, the old mapping would still be there.  This is a problem
that came about when we switch to using vcore lists.

Now we'll spin til the remote core unmaps.  This means that we can't
have scheduler code (or whatever) try to preempt its current pcore's
vcore and then try to give out that same vcore somewhere else without
take the stack-smashing __preempt message.  No one does this yet, since
our scheduler() only runs on LL cores.

kern/src/process.c

index c7b87b1..b085869 100644 (file)
@@ -1349,6 +1349,8 @@ void __proc_kmsg_pending(struct proc *p, bool ipi_pending)
  * calling. */
 void __map_vcore(struct proc *p, uint32_t vcoreid, uint32_t pcoreid)
 {
+       while (p->procinfo->vcoremap[vcoreid].valid)
+               cpu_relax();
        p->procinfo->vcoremap[vcoreid].pcoreid = pcoreid;
        p->procinfo->vcoremap[vcoreid].valid = TRUE;
        p->procinfo->pcoremap[pcoreid].vcoreid = vcoreid;
@@ -1359,8 +1361,9 @@ void __map_vcore(struct proc *p, uint32_t vcoreid, uint32_t pcoreid)
  * calling. */
 void __unmap_vcore(struct proc *p, uint32_t vcoreid)
 {
-       p->procinfo->vcoremap[vcoreid].valid = FALSE;
        p->procinfo->pcoremap[p->procinfo->vcoremap[vcoreid].pcoreid].valid = FALSE;
+       wmb();
+       p->procinfo->vcoremap[vcoreid].valid = FALSE;
 }
 
 /* Stop running whatever context is on this core, load a known-good cr3, and