summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--includes/Stable.h3
-rw-r--r--rts/Stable.c17
-rw-r--r--rts/sm/GC.c6
3 files changed, 26 insertions, 0 deletions
diff --git a/includes/Stable.h b/includes/Stable.h
index 5404bab46e..9752a534bb 100644
--- a/includes/Stable.h
+++ b/includes/Stable.h
@@ -57,4 +57,7 @@ extern void threadStablePtrTable ( evac_fn evac, void *user );
extern void gcStablePtrTable ( void );
extern void updateStablePtrTable ( rtsBool full );
+extern void stablePtrPreGC ( void );
+extern void stablePtrPostGC ( void );
+
#endif
diff --git a/rts/Stable.c b/rts/Stable.c
index 94a756a380..97796b89a7 100644
--- a/rts/Stable.c
+++ b/rts/Stable.c
@@ -316,6 +316,23 @@ enlargeStablePtrTable(void)
}
/* -----------------------------------------------------------------------------
+ * We must lock the StablePtr table during GC, to prevent simultaneous
+ * calls to freeStablePtr().
+ * -------------------------------------------------------------------------- */
+
+void
+stablePtrPreGC(void)
+{
+ ACQUIRE_LOCK(&stable_mutex);
+}
+
+void
+stablePtrPostGC(void)
+{
+ RELEASE_LOCK(&stable_mutex);
+}
+
+/* -----------------------------------------------------------------------------
* Treat stable pointers as roots for the garbage collector.
*
* A stable pointer is any stable name entry with a ref > 0. We'll
diff --git a/rts/sm/GC.c b/rts/sm/GC.c
index e0c8b05436..cfe4c6bdb5 100644
--- a/rts/sm/GC.c
+++ b/rts/sm/GC.c
@@ -215,6 +215,9 @@ GarbageCollect (rtsBool force_major_gc,
// tell the STM to discard any cached closures it's hoping to re-use
stmPreGCHook();
+ // lock the StablePtr table
+ stablePtrPreGC();
+
#ifdef DEBUG
mutlist_MUTVARS = 0;
mutlist_MUTARRS = 0;
@@ -794,6 +797,9 @@ SET_GCT(gc_threads[0]);
slop = calcLiveBlocks() * BLOCK_SIZE_W - live;
stat_endGC(allocated, live, copied, N, max_copied, avg_copied, slop);
+ // unlock the StablePtr table
+ stablePtrPostGC();
+
// Guess which generation we'll collect *next* time
initialise_N(force_major_gc);