summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Gamari <ben@smart-cactus.org>2021-02-23 18:30:48 +0000
committerBen Gamari <ben@well-typed.com>2021-03-02 18:37:31 -0500
commit96f8e2a47c5e53ae5fb86739aecd27c502e7f121 (patch)
treedef553cd64819e89e536a00c9507b11ab0313212
parentede60537b9c6827063734312d8068a7d30b89dd5 (diff)
downloadhaskell-cherry-pick-fe28a062.tar.gz
rts: Make markLiveObject thread-safecherry-pick-fe28a062
markLiveObject is called by GC worker threads and therefore must be thread-safe. This was a rather egregious oversight which the testsuite missed. (cherry picked from commit fe28a062e47bd914a6879f2d01ff268983c075ad)
-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 8f834d13fa..345a17cfec 100644
--- a/rts/CheckUnload.c
+++ b/rts/CheckUnload.c
@@ -381,11 +381,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
@@ -405,6 +410,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 44fe337802..444849fbac 100644
--- a/rts/LinkerInternals.h
+++ b/rts/LinkerInternals.h
@@ -262,7 +262,7 @@ 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`.