summaryrefslogtreecommitdiff
path: root/rts
diff options
context:
space:
mode:
authorSimon Marlow <marlowsd@gmail.com>2014-12-19 20:10:40 +0000
committerSimon Marlow <marlowsd@gmail.com>2015-01-13 20:34:13 +0000
commit24bbc3e7077f5f6cd51f118393e5342a4047978c (patch)
tree668739a12812b3a01e8e12f95d500a5250c2e53e /rts
parent2a103c7d763c22dc9b0562dac1184ffb950da5ce (diff)
downloadhaskell-24bbc3e7077f5f6cd51f118393e5342a4047978c.tar.gz
Allow the linker to run concurrently with the GC
Diffstat (limited to 'rts')
-rw-r--r--rts/CheckUnload.c4
-rw-r--r--rts/Linker.c13
-rw-r--r--rts/LinkerInternals.h1
3 files changed, 16 insertions, 2 deletions
diff --git a/rts/CheckUnload.c b/rts/CheckUnload.c
index 73573fbb34..2c01113f63 100644
--- a/rts/CheckUnload.c
+++ b/rts/CheckUnload.c
@@ -260,7 +260,7 @@ void checkUnload (StgClosure *static_objects)
if (unloaded_objects == NULL) return;
- ACQUIRE_LOCK(&linker_mutex);
+ ACQUIRE_LOCK(&linker_unloaded_mutex);
// Mark every unloadable object as unreferenced initially
for (oc = unloaded_objects; oc; oc = oc->next) {
@@ -320,5 +320,5 @@ void checkUnload (StgClosure *static_objects)
freeHashTable(addrs, NULL);
- RELEASE_LOCK(&linker_mutex);
+ RELEASE_LOCK(&linker_unloaded_mutex);
}
diff --git a/rts/Linker.c b/rts/Linker.c
index 6bf06ed944..2ba84f8040 100644
--- a/rts/Linker.c
+++ b/rts/Linker.c
@@ -156,7 +156,15 @@ ObjectCode *objects = NULL; /* initially empty */
ObjectCode *unloaded_objects = NULL; /* initially empty */
#ifdef THREADED_RTS
+/* This protects all the Linker's global state except unloaded_objects */
Mutex linker_mutex;
+/*
+ * This protects unloaded_objects. We have a separate mutex for this, because
+ * the GC needs to access unloaded_objects in checkUnload, while the linker only
+ * needs to access unloaded_objects in unloadObj(), so this allows most linker
+ * operations proceed concurrently with the GC.
+ */
+Mutex linker_unloaded_mutex;
#endif
/* Type of the initializer */
@@ -1648,6 +1656,7 @@ initLinker_ (int retain_cafs)
#if defined(THREADED_RTS)
initMutex(&linker_mutex);
+ initMutex(&linker_unloaded_mutex);
#if defined(OBJFORMAT_ELF) || defined(OBJFORMAT_MACHO)
initMutex(&dl_mutex);
#endif
@@ -3235,9 +3244,13 @@ static HsInt unloadObj_ (pathchar *path, rtsBool just_purge)
} else {
prev->next = oc->next;
}
+ ACQUIRE_LOCK(&linker_unloaded_mutex);
oc->next = unloaded_objects;
unloaded_objects = oc;
oc->status = OBJECT_UNLOADED;
+ RELEASE_LOCK(&linker_unloaded_mutex);
+ // We do not own oc any more; it can be released at any time by
+ // the GC in checkUnload().
} else {
prev = oc;
}
diff --git a/rts/LinkerInternals.h b/rts/LinkerInternals.h
index 4fe533b903..4eab5deb45 100644
--- a/rts/LinkerInternals.h
+++ b/rts/LinkerInternals.h
@@ -146,6 +146,7 @@ extern ObjectCode *unloaded_objects;
#ifdef THREADED_RTS
extern Mutex linker_mutex;
+extern Mutex linker_unloaded_mutex;
#endif
void exitLinker( void );