messageBlackHole: fix deadlock bug caused by a missing 'volatile'
authorSimon Marlow <marlowsd@gmail.com>
Thu, 10 Jun 2010 08:06:36 +0000 (08:06 +0000)
committerSimon Marlow <marlowsd@gmail.com>
Thu, 10 Jun 2010 08:06:36 +0000 (08:06 +0000)
includes/stg/SMP.h
rts/Messages.c

index b302f48..ad8c0ba 100644 (file)
@@ -293,6 +293,12 @@ load_load_barrier(void) {
 #endif
 }
 
+// Load a pointer from a memory location that might be being modified
+// concurrently.  This prevents the compiler from optimising away
+// multiple loads of the memory location, as it might otherwise do in
+// a busy wait loop for example.
+#define VOLATILE_LOAD(p) (*((StgVolatilePtr)(p)))
+
 /* ---------------------------------------------------------------------- */
 #else /* !THREADED_RTS */
 
@@ -331,6 +337,8 @@ atomic_dec(StgVolatilePtr p)
     return --(*p);
 }
 
+#define VOLATILE_LOAD(p) ((StgWord)*((StgWord*)(p)))
+
 #endif /* !THREADED_RTS */
 
 #endif /* SMP_H */
index 91ee9a6..7a37a86 100644 (file)
@@ -186,7 +186,9 @@ nat messageBlackHole(Capability *cap, MessageBlackHole *msg)
     // The blackhole must indirect to a TSO, a BLOCKING_QUEUE, an IND,
     // or a value.
 loop:
-    p = UNTAG_CLOSURE(((StgInd*)bh)->indirectee);
+    // NB. VOLATILE_LOAD(), because otherwise gcc hoists the load
+    // and turns this into an infinite loop.
+    p = UNTAG_CLOSURE((StgClosure*)VOLATILE_LOAD(&((StgInd*)bh)->indirectee));
     info = p->header.info;
 
     if (info == &stg_IND_info)