diff options
author | Peter Trommler <ptrommler@acm.org> | 2019-02-24 17:11:00 +0100 |
---|---|---|
committer | Marge Bot <ben+marge-bot@smart-cactus.org> | 2019-02-27 09:59:59 -0500 |
commit | 5c084e0468be46f5ab48b2c1669a7e4d4d0f3c43 (patch) | |
tree | 148d5b9dcae8f5f3701bc05a0a0d89386a33a1d7 | |
parent | 5bc195b1fe788e9a900a15fbe473967850517c3e (diff) | |
download | haskell-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.c | 9 | ||||
-rw-r--r-- | testsuite/tests/rts/testwsdeque.c | 9 |
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 */ |