diff options
author | Simon Marlow <marlowsd@gmail.com> | 2016-12-07 13:20:03 +0000 |
---|---|---|
committer | Simon Marlow <marlowsd@gmail.com> | 2016-12-07 13:20:03 +0000 |
commit | 9043a4002623679989a2fdc4e97d484a9d58d619 (patch) | |
tree | cbcc1eb08a735a1dcf038fb2cabb44935c26afa5 | |
parent | 5aa9c750c6c3adc47a8e526007254b1f49de1d16 (diff) | |
download | haskell-9043a4002623679989a2fdc4e97d484a9d58d619.tar.gz |
Fix crashes in hash table scanning with THREADED_RTS
See comments.
-rw-r--r-- | rts/sm/Scav.c | 22 |
1 files changed, 19 insertions, 3 deletions
diff --git a/rts/sm/Scav.c b/rts/sm/Scav.c index 10ce1e46a8..bbe049cc2a 100644 --- a/rts/sm/Scav.c +++ b/rts/sm/Scav.c @@ -105,13 +105,26 @@ scavengeTSO (StgTSO *tso) Scavenging compact objects ------------------------------------------------------------------------- */ +typedef struct { + // We must save gct when calling mapHashTable(), which is compiled + // without GCThread.h and so uses a different calling convention. + // See also GC.c:mark_root where we do a similar thing. + gc_thread *saved_gct; + HashTable *newHash; +} MapHashData; + static void -evacuate_hash_entry(HashTable *newHash, StgWord key, const void *value) +evacuate_hash_entry(MapHashData *dat, StgWord key, const void *value) { StgClosure *p = (StgClosure*)key; +#ifdef THREADED_RTS + gc_thread *old_gct = gct; +#endif + SET_GCT(dat->saved_gct); evacuate(&p); - insertHashTable(newHash, (StgWord)p, value); + insertHashTable(dat->newHash, (StgWord)p, value); + SET_GCT(old_gct); } static void @@ -122,8 +135,11 @@ scavenge_compact(StgCompactNFData *str) gct->eager_promotion = false; if (str->hash) { + MapHashData dat; + dat.saved_gct = gct; HashTable *newHash = allocHashTable(); - mapHashTable(str->hash, (void*)newHash, (MapHashFn)evacuate_hash_entry); + dat.newHash = newHash; + mapHashTable(str->hash, (void*)&dat, (MapHashFn)evacuate_hash_entry); freeHashTable(str->hash, NULL); str->hash = newHash; } |