fix a deadlock in atomicModifyMutVar#
authorSimon Marlow <simonmar@microsoft.com>
Tue, 21 Feb 2006 16:37:11 +0000 (16:37 +0000)
committerSimon Marlow <simonmar@microsoft.com>
Tue, 21 Feb 2006 16:37:11 +0000 (16:37 +0000)
atomicModifyMutVar# was re-using the storage manager mutex (sm_mutex)
to get its atomicity guarantee in SMP mode. But recently the addition
of a call to dirty_MUT_VAR() to implement the read barrier lead to a
rare deadlock case, because dirty_MUT_VAR() very occasionally needs to
allocate a new block to chain on the mutable list, which requires
sm_mutex.

ghc/includes/Storage.h
ghc/rts/PrimOps.cmm
ghc/rts/Storage.c

index a04a411..46081ad 100644 (file)
@@ -200,6 +200,7 @@ extern void GarbageCollect(void (*get_roots)(evac_fn),rtsBool force_major_gc);
  */
 #if defined(THREADED_RTS)
 extern Mutex sm_mutex;
+extern Mutex atomic_modify_mutvar_mutex;
 #endif
 
 #if defined(THREADED_RTS)
index 7d57092..2e81c1a 100644 (file)
@@ -207,7 +207,7 @@ atomicModifyMutVarzh_fast
    HP_CHK_GEN_TICKY(SIZE, R1_PTR & R2_PTR, atomicModifyMutVarzh_fast);
 
 #if defined(THREADED_RTS)
-    foreign "C" ACQUIRE_LOCK(sm_mutex "ptr") [R1,R2];
+    foreign "C" ACQUIRE_LOCK(atomic_modify_mutvar_mutex "ptr") [R1,R2];
 #endif
 
    x = StgMutVar_var(R1);
@@ -238,7 +238,7 @@ atomicModifyMutVarzh_fast
    StgThunk_payload(r,0) = z;
 
 #if defined(THREADED_RTS)
-    foreign "C" RELEASE_LOCK(sm_mutex "ptr") [];
+    foreign "C" RELEASE_LOCK(atomic_modify_mutvar_mutex "ptr") [];
 #endif
 
    RET_P(r);
index 195f410..ef58c1f 100644 (file)
@@ -51,14 +51,19 @@ ullong total_allocated = 0; /* total memory allocated during run */
 nat n_nurseries         = 0;    /* == RtsFlags.ParFlags.nNodes, convenience */
 step *nurseries         = NULL; /* array of nurseries, >1 only if THREADED_RTS */
 
+#ifdef THREADED_RTS
 /*
  * Storage manager mutex:  protects all the above state from
  * simultaneous access by two STG threads.
  */
-#ifdef THREADED_RTS
 Mutex sm_mutex;
+/*
+ * This mutex is used by atomicModifyMutVar# only
+ */
+Mutex atomic_modify_mutvar_mutex;
 #endif
 
+
 /*
  * Forward references
  */