diff options
author | Ben Gamari <ben@smart-cactus.org> | 2021-02-23 18:30:48 +0000 |
---|---|---|
committer | Marge Bot <ben+marge-bot@smart-cactus.org> | 2021-03-04 23:15:48 -0500 |
commit | 9de44e57808e601f78eaafeaa4287666bf8bfb95 (patch) | |
tree | de6e681736966e0b8d1caed3bb19d4cd79c20029 /rts | |
parent | f191fce702c4bfe251067807a8ad1aa1de7550b1 (diff) | |
download | haskell-9de44e57808e601f78eaafeaa4287666bf8bfb95.tar.gz |
rts: Make markLiveObject thread-safe
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)
Diffstat (limited to 'rts')
-rw-r--r-- | rts/CheckUnload.c | 10 | ||||
-rw-r--r-- | rts/LinkerInternals.h | 2 |
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`. |