RTS: Add missing memory barrier
authorPeter Trommler <ptrommler@acm.org>
Sun, 24 Feb 2019 16:11:00 +0000 (17:11 +0100)
committerMarge Bot <ben+marge-bot@smart-cactus.org>
Wed, 27 Feb 2019 14:59:59 +0000 (09:59 -0500)
In the work stealing queue a load-load-barrier is required to ensure
that a read of queue data cannot be reordered before a read of the
bottom pointer into the queue.

The added load-load-barrier ensures that the ordering of writes enforced
at the end of `pushWSDeque` is also respected in the order of reads in
`stealWSDeque_`. In other words, when reading `q->bottom` we want to make
sure that we see the updates to `q->elements`.

Fixes #13633

rts/WSDeque.c
testsuite/tests/rts/testwsdeque.c

index b9393b1..60b8948 100644 (file)
@@ -194,14 +194,17 @@ stealWSDeque_ (WSDeque *q)
     // concurrent popWSQueue() operation.
     if ((long)b - (long)t <= 0 ) {
         return NULL; /* already looks empty, abort */
-  }
-
+    }
+    // NB. the load of q->bottom must be ordered before the load of
+    // q->elements[t & q-> moduloSize]. See comment "KG:..." below
+    // and Ticket #13633.
+    load_load_barrier();
     /* now access array, see pushBottom() */
     stolen = q->elements[t & q->moduloSize];
 
     /* now decide whether we have won */
     if ( !(CASTOP(&(q->top),t,t+1)) ) {
-        /* lost the race, someon else has changed top in the meantime */
+        /* lost the race, someone else has changed top in the meantime */
         return NULL;
     }  /* else: OK, top has been incremented by the cas call */
 
index 3f17f32..0a2a64d 100644 (file)
@@ -50,14 +50,17 @@ myStealWSDeque_ (WSDeque *q, uint32_t n)
     // concurrent popWSQueue() operation.
     if ((long)b - (long)t <= 0 ) { 
         return NULL; /* already looks empty, abort */
-  }
-    
+    }
+    // NB. the load of q->bottom must be ordered before the load of
+    // q->elements[t & q-> moduloSize]. See comment "KG:..." below
+    // and Ticket #13633.
+    load_load_barrier();
     /* now access array, see pushBottom() */
     stolen = q->elements[t & q->moduloSize];
     
     /* now decide whether we have won */
     if ( !(CASTOP(&(q->top),t,t+1)) ) {
-        /* lost the race, someon else has changed top in the meantime */
+        /* lost the race, someone else has changed top in the meantime */
         return NULL;
     }  /* else: OK, top has been incremented by the cas call */