summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Gamari <ben@smart-cactus.org>2021-02-23 13:30:48 -0500
committerBen Gamari <ben@smart-cactus.org>2021-02-23 13:44:09 -0500
commitfe28a062e47bd914a6879f2d01ff268983c075ad (patch)
treee45e052102ac387caafab8a7ccad8e447f9b0db9
parentab571457b9960cc05d46d3ae6a3796e760766750 (diff)
downloadhaskell-wip/T19417-ghc-8.10.tar.gz
rts: Make markLiveObject thread-safewip/T19417-ghc-8.10
markLiveObject is called by GC worker threads and therefore must be thread-safe. This was a rather egregious oversight which the testsuite missed.
-rw-r--r--rts/CheckUnload.c10
-rw-r--r--rts/LinkerInternals.h2
2 files changed, 9 insertions, 3 deletions
diff --git a/rts/CheckUnload.c b/rts/CheckUnload.c
index fcbe0f6156..d67696a061 100644
--- a/rts/CheckUnload.c
+++ b/rts/CheckUnload.c
@@ -357,11 +357,16 @@ static ObjectCode *findOC(OCSectionIndices *s_indices, const void *addr) {
static bool markObjectLive(void *data STG_UNUSED, StgWord key, const void *value STG_UNUSED) {
ObjectCode *oc = (ObjectCode*)key;
- if (oc->mark == object_code_mark_bit) {
+
+ // N.B. we may be called by the parallel GC and therefore this must be
+ // thread-safe. To avoid taking the linker_mutex in the fast path
+ // (when the object is already marked) we do an atomic exchange here and
+ // only take the lock in the case that the object is unmarked.
+ if (xchg(&oc->mark, object_code_mark_bit) == object_code_mark_bit) {
return true; // for hash table iteration
}
- oc->mark = object_code_mark_bit;
+ ACQUIRE_LOCK(&linker_mutex);
// Remove from 'old_objects' list
if (oc->prev != NULL) {
// TODO(osa): Maybe 'prev' should be a pointer to the referencing
@@ -381,6 +386,7 @@ static bool markObjectLive(void *data STG_UNUSED, StgWord key, const void *value
objects->prev = oc;
}
objects = oc;
+ RELEASE_LOCK(&linker_mutex);
// Mark its dependencies
iterHashTable(oc->dependencies, NULL, markObjectLive);
diff --git a/rts/LinkerInternals.h b/rts/LinkerInternals.h
index 1a83771439..8c977ce767 100644
--- a/rts/LinkerInternals.h
+++ b/rts/LinkerInternals.h
@@ -221,7 +221,7 @@ typedef struct _ObjectCode {
struct _ObjectCode *next_loaded_object;
// Mark bit
- uint8_t mark;
+ StgWord mark;
// Set of dependencies (ObjectCode*) of the object file. Traverse
// dependencies using `iterHashTable`.