Skip to content

Commit 6762449

Browse files
committed
Add GHC 8.10 Make markLiveObject thread-safe
See #1062
1 parent 962ecfe commit 6762449

File tree

2 files changed

+65
-0
lines changed

2 files changed

+65
-0
lines changed

overlays/bootstrap.nix

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,8 @@ in {
151151
++ fromUntil "8.10.1" "8.10.3" ./patches/ghc/ghc-8.10-ubxt.patch
152152
++ fromUntil "8.10.3" "8.11" ./patches/ghc/ghc-8.10.3-ubxt.patch
153153
++ final.lib.optional (versionAtLeast "8.6.4") ./patches/ghc/Cabal-3886.patch
154+
155+
++ fromUntil "8.10.3" "8.10.5" ./patches/ghc/ghc-8.10.3-rts-make-markLiveObject-thread-safe.patch
154156
;
155157
in ({
156158
ghc844 = final.callPackage ../compiler/ghc {
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
From 96f8e2a47c5e53ae5fb86739aecd27c502e7f121 Mon Sep 17 00:00:00 2001
2+
From: Ben Gamari <[email protected]>
3+
Date: Tue, 23 Feb 2021 18:30:48 +0000
4+
Subject: [PATCH] rts: Make markLiveObject thread-safe
5+
6+
markLiveObject is called by GC worker threads and therefore must be
7+
thread-safe. This was a rather egregious oversight which the testsuite
8+
missed.
9+
10+
11+
(cherry picked from commit fe28a062e47bd914a6879f2d01ff268983c075ad)
12+
---
13+
rts/CheckUnload.c | 10 ++++++++--
14+
rts/LinkerInternals.h | 2 +-
15+
2 files changed, 9 insertions(+), 3 deletions(-)
16+
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) {
22+
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) {
26+
+
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
33+
}
34+
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
41+
objects->prev = oc;
42+
}
43+
objects = oc;
44+
+ RELEASE_LOCK(&linker_mutex);
45+
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;
54+
55+
// Mark bit
56+
- uint8_t mark;
57+
+ StgWord mark;
58+
59+
// Set of dependencies (ObjectCode*) of the object file. Traverse
60+
// dependencies using `iterHashTable`.
61+
--
62+
GitLab
63+

0 commit comments

Comments
 (0)