|
| 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