diff options
author | Simon Marlow <marlowsd@gmail.com> | 2014-12-19 20:10:40 +0000 |
---|---|---|
committer | Simon Marlow <marlowsd@gmail.com> | 2015-01-13 20:34:13 +0000 |
commit | 24bbc3e7077f5f6cd51f118393e5342a4047978c (patch) | |
tree | 668739a12812b3a01e8e12f95d500a5250c2e53e /rts | |
parent | 2a103c7d763c22dc9b0562dac1184ffb950da5ce (diff) | |
download | haskell-24bbc3e7077f5f6cd51f118393e5342a4047978c.tar.gz |
Allow the linker to run concurrently with the GC
Diffstat (limited to 'rts')
-rw-r--r-- | rts/CheckUnload.c | 4 | ||||
-rw-r--r-- | rts/Linker.c | 13 | ||||
-rw-r--r-- | rts/LinkerInternals.h | 1 |
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 ); |