[commit: ghc] wip/T15449: rts: Fix write barrier on thunk updates (5585c55)

git at git.haskell.org git at git.haskell.org
Sun Feb 10 21:31:27 UTC 2019


Repository : ssh://git@git.haskell.org/ghc

On branch  : wip/T15449
Link       : http://ghc.haskell.org/trac/ghc/changeset/5585c55f8db4b6a0cc36d924dbbe0bd285aac8c0/ghc

>---------------------------------------------------------------

commit 5585c55f8db4b6a0cc36d924dbbe0bd285aac8c0
Author: Ben Gamari <ben at smart-cactus.org>
Date:   Sat Feb 9 17:14:50 2019 -0500

    rts: Fix write barrier on thunk updates


>---------------------------------------------------------------

5585c55f8db4b6a0cc36d924dbbe0bd285aac8c0
 rts/ThreadPaused.c |  3 ++-
 rts/Updates.h      | 30 ++++++++++++++++++++++++++++--
 2 files changed, 30 insertions(+), 3 deletions(-)

diff --git a/rts/ThreadPaused.c b/rts/ThreadPaused.c
index a916891..4feb790 100644
--- a/rts/ThreadPaused.c
+++ b/rts/ThreadPaused.c
@@ -331,8 +331,9 @@ threadPaused(Capability *cap, StgTSO *tso)
 #endif
 
             // The payload of the BLACKHOLE points to the TSO
-            ((StgInd *)bh)->indirectee = (StgClosure *)tso;
+            // See Note [Write barrier on thunk updates] in rts/Updates.h
             write_barrier();
+            ((StgInd *)bh)->indirectee = (StgClosure *)tso;
             SET_INFO(bh,&stg_BLACKHOLE_info);
 
             // .. and we need a write barrier, since we just mutated the closure:
diff --git a/rts/Updates.h b/rts/Updates.h
index 1ba398b..2c9be5a 100644
--- a/rts/Updates.h
+++ b/rts/Updates.h
@@ -23,6 +23,31 @@
  *  field. So, we call LDV_RECORD_CREATE().
  */
 
+/* Note [Write barrier on thunk updates]
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * Thunk updates are rather tricky, especially on architectures with weak memory
+ * ordering guarantees. updateWithIndirection plays a significant role in the
+ * update process, implementing the logic for turning a thunk or blackhole into
+ * an indirection.
+ *
+ * Before replacing a closure with an indirection we must first ensure that the
+ * writes that initialize the newly-created indirectee are available to other
+ * cores. For this reason, we must place a write barrier between the
+ * construction of the indirectee and the write to the indirectee field of the
+ * indirection.
+ *
+ * However note that we do *not* impose an ordering on the writes to the
+ * indirection's indirectee and info table pointer fields. It is in principle
+ * possible for the writes to p1->info to become visible before those to
+ * p1->indirectee. However, this is okay since we know that this field was
+ * earlier set to the owning TSO or blocking queue. When the stg_BLACKHOLE entry
+ * code sees a blackhole whose indirectee is a TSO or blocking queue it will
+ * retry or block as appropriate.
+ *
+ * See #15449.
+ */
+
 /*
  * We have two versions of this macro (sadly), one for use in C-- code,
  * and the other for C.
@@ -40,12 +65,13 @@
                  p_ updatee
 
 
+// See Note [Write barrier on thunk update]
 #define updateWithIndirection(p1, p2, and_then) \
     W_ bd;                                                      \
                                                                 \
     OVERWRITING_CLOSURE(p1);                                    \
-    StgInd_indirectee(p1) = p2;                                 \
     prim_write_barrier;                                         \
+    StgInd_indirectee(p1) = p2;                                 \
     SET_INFO(p1, stg_BLACKHOLE_info);                           \
     LDV_RECORD_CREATE(p1);                                      \
     bd = Bdescr(p1);                                            \
@@ -70,8 +96,8 @@ INLINE_HEADER void updateWithIndirection (Capability *cap,
     /* not necessarily true: ASSERT( !closure_IND(p1) ); */
     /* occurs in RaiseAsync.c:raiseAsync() */
     OVERWRITING_CLOSURE(p1);
+    write_barrier();  // See Note [Write barrier on thunk update]
     ((StgInd *)p1)->indirectee = p2;
-    write_barrier();
     SET_INFO(p1, &stg_BLACKHOLE_info);
     LDV_RECORD_CREATE(p1);
     bd = Bdescr((StgPtr)p1);



More information about the ghc-commits mailing list