summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Trommler <ptrommler@acm.org>2019-02-24 17:11:00 +0100
committerMarge Bot <ben+marge-bot@smart-cactus.org>2019-02-27 09:59:59 -0500
commit5c084e0468be46f5ab48b2c1669a7e4d4d0f3c43 (patch)
tree148d5b9dcae8f5f3701bc05a0a0d89386a33a1d7
parent5bc195b1fe788e9a900a15fbe473967850517c3e (diff)
downloadhaskell-5c084e0468be46f5ab48b2c1669a7e4d4d0f3c43.tar.gz
RTS: Add missing memory barrier
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
-rw-r--r--rts/WSDeque.c9
-rw-r--r--testsuite/tests/rts/testwsdeque.c9
2 files changed, 12 insertions, 6 deletions
diff --git a/rts/WSDeque.c b/rts/WSDeque.c
index b9393b1839..60b8948149 100644
--- a/rts/WSDeque.c
+++ b/rts/WSDeque.c
@@ -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 */
diff --git a/testsuite/tests/rts/testwsdeque.c b/testsuite/tests/rts/testwsdeque.c
index 3f17f321cd..0a2a64d78e 100644
--- a/testsuite/tests/rts/testwsdeque.c
+++ b/testsuite/tests/rts/testwsdeque.c
@@ -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 */