@@ -0,0 +1,63 @@
1+From 96f8e2a47c5e53ae5fb86739aecd27c502e7f121 Mon Sep 17 00:00:00 2001
2+From: Ben Gamari <ben@smart-cactus.org>
3+Date: Tue, 23 Feb 2021 18:30:48 +0000
4+Subject: [PATCH] rts: Make markLiveObject thread-safe
6+markLiveObject is called by GC worker threads and therefore must be
7+thread-safe. This was a rather egregious oversight which the testsuite
11+(cherry picked from commit fe28a062e47bd914a6879f2d01ff268983c075ad)
13+ rts/CheckUnload.c | 10 ++++++++--
14+ rts/LinkerInternals.h | 2 +-
15+ 2 files changed, 9 insertions(+), 3 deletions(-)
17+diff --git a/rts/CheckUnload.c b/rts/CheckUnload.c
18+index 8f834d13fa..345a17cfec 100644
19+--- a/rts/CheckUnload.c
20++++ b/rts/CheckUnload.c
21+@@ -381,11 +381,16 @@ static ObjectCode *findOC(OCSectionIndices *s_indices, const void *addr) {
23+ static bool markObjectLive(void *data STG_UNUSED, StgWord key, const void *value STG_UNUSED) {
24+ ObjectCode *oc = (ObjectCode*)key;
25+- if (oc->mark == object_code_mark_bit) {
27++ // N.B. we may be called by the parallel GC and therefore this must be
28++ // thread-safe. To avoid taking the linker_mutex in the fast path
29++ // (when the object is already marked) we do an atomic exchange here and
30++ // only take the lock in the case that the object is unmarked.
31++ if (xchg(&oc->mark, object_code_mark_bit) == object_code_mark_bit) {
32+ return true; // for hash table iteration
35+- oc->mark = object_code_mark_bit;
36++ ACQUIRE_LOCK(&linker_mutex);
37+ // Remove from 'old_objects' list
38+ if (oc->prev != NULL) {
39+ // TODO(osa): Maybe 'prev' should be a pointer to the referencing
40+@@ -405,6 +410,7 @@ static bool markObjectLive(void *data STG_UNUSED, StgWord key, const void *value
44++ RELEASE_LOCK(&linker_mutex);
46+ // Mark its dependencies
47+ iterHashTable(oc->dependencies, NULL, markObjectLive);
48+diff --git a/rts/LinkerInternals.h b/rts/LinkerInternals.h
49+index 44fe337802..444849fbac 100644
50+--- a/rts/LinkerInternals.h
51++++ b/rts/LinkerInternals.h
52+@@ -262,7 +262,7 @@ struct _ObjectCode {
53+ struct _ObjectCode *next_loaded_object;
59+ // Set of dependencies (ObjectCode*) of the object file. Traverse
60+ // dependencies using `iterHashTable`.