summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Marlow <marlowsd@gmail.com>2016-12-07 13:20:03 +0000
committerSimon Marlow <marlowsd@gmail.com>2016-12-07 13:20:03 +0000
commit9043a4002623679989a2fdc4e97d484a9d58d619 (patch)
treecbcc1eb08a735a1dcf038fb2cabb44935c26afa5
parent5aa9c750c6c3adc47a8e526007254b1f49de1d16 (diff)
downloadhaskell-9043a4002623679989a2fdc4e97d484a9d58d619.tar.gz
Fix crashes in hash table scanning with THREADED_RTS
See comments.
-rw-r--r--rts/sm/Scav.c22
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;
}