[commit: ghc] ghc-7.10: Allow the linker to run concurrently with the GC (8608429)

git at git.haskell.org git at git.haskell.org
Wed Jan 14 12:52:57 UTC 2015


Repository : ssh://git@git.haskell.org/ghc

On branch  : ghc-7.10
Link       : http://ghc.haskell.org/trac/ghc/changeset/860842904fc28406cea0cf070e06be6e07643abb/ghc

>---------------------------------------------------------------

commit 860842904fc28406cea0cf070e06be6e07643abb
Author: Simon Marlow <marlowsd at gmail.com>
Date:   Fri Dec 19 20:10:40 2014 +0000

    Allow the linker to run concurrently with the GC
    
    (cherry picked from commit 24bbc3e7077f5f6cd51f118393e5342a4047978c)


>---------------------------------------------------------------

860842904fc28406cea0cf070e06be6e07643abb
 rts/CheckUnload.c     |  4 ++--
 rts/Linker.c          | 13 +++++++++++++
 rts/LinkerInternals.h |  1 +
 3 files changed, 16 insertions(+), 2 deletions(-)

diff --git a/rts/CheckUnload.c b/rts/CheckUnload.c
index 73573fb..2c01113 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 4a0e5ea..29a4b75 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 */
@@ -1647,6 +1655,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
@@ -3234,9 +3243,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 4fe533b..4eab5de 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 );



More information about the ghc-commits mailing list