Updated memory barrier stuff
authorBarret Rhoden <brho@cs.berkeley.edu>
Mon, 3 Oct 2011 23:26:28 +0000 (16:26 -0700)
committerKevin Klues <klueska@cs.berkeley.edu>
Thu, 3 Nov 2011 00:36:08 +0000 (17:36 -0700)
Minor change to the MCS lock (which did not appear to be a problem in
the assembly) and some talk about the Alpha memory model.

Note that I caught a process deadlocked on an MCS lock in a VM (one
vcore, spinning on a locked lock, no preemptions etc outstanding), so
something out there is probably jacked up.

Documentation/memory_barriers.txt
user/parlib/mcs.c

index aa8cd13..29b186b 100644 (file)
@@ -218,6 +218,24 @@ Some of it doesn't make any sense.  I've asked our architects about things
 like read_barrier_depends() and a few other things.  They also support some
 non-Intel x86 clones that need wmb_f() in place of a wmb() (support out of
 order writes).  If this pops up, we'll deal with it.
 like read_barrier_depends() and a few other things.  They also support some
 non-Intel x86 clones that need wmb_f() in place of a wmb() (support out of
 order writes).  If this pops up, we'll deal with it.
+
+I chatted with Andrew a bit, and it turns out the following needs a barrier
+on P2 under the Alpha's memory model:
+
+       (global) int x = 0, *p = 0;
+       
+       P1:
+       x = 3;
+       FENCE
+       p = &x;
+       
+       P2:
+       while (p == NULL) ;
+       assert(*p == 3);
+
+As far as we can figure, you'd need some sort of 'value-speculating' hardware
+to make this an issue in practice.  For now, we'll mark these spots in the code
+if we see them, but I'm not overly concerned about it.
        
 Also note that none of these barriers deal with things like page talble walks,
 page/segmentation update writes, non-temporal hints on writes, etc.  glhf with
        
 Also note that none of these barriers deal with things like page talble walks,
 page/segmentation update writes, non-temporal hints on writes, etc.  glhf with
index 9b25f27..d06e361 100644 (file)
@@ -20,6 +20,7 @@ static inline mcs_lock_qnode_t *mcs_qnode_swap(mcs_lock_qnode_t **addr,
 void mcs_lock_lock(struct mcs_lock *lock, struct mcs_lock_qnode *qnode)
 {
        qnode->next = 0;
 void mcs_lock_lock(struct mcs_lock *lock, struct mcs_lock_qnode *qnode)
 {
        qnode->next = 0;
+       cmb();  /* swap provides a CPU mb() */
        mcs_lock_qnode_t *predecessor = mcs_qnode_swap(&lock->lock, qnode);
        if (predecessor) {
                qnode->locked = 1;
        mcs_lock_qnode_t *predecessor = mcs_qnode_swap(&lock->lock, qnode);
        if (predecessor) {
                qnode->locked = 1;