Compact normal form block allocation can race with GC initialization
While looking at !1603 (closed) I stumbled upon the following data race:
==================
WARNING: ThreadSanitizer: data race (pid=9105)
Atomic read of size 8 at 0x7b5800000048 by thread T6:
#0 __tsan_atomic64_load <null> (libtsan.so.0+0x00000006130c)
#1 calcNeeded rts/sm/Storage.c:1294 (compact_mutable+0x00000075c945)
#2 scheduleDoGC rts/Schedule.c:1549 (compact_mutable+0x00000072f361)
#3 schedule rts/Schedule.c:255 (compact_mutable+0x000000731722)
#4 scheduleWorker rts/Schedule.c:2576 (compact_mutable+0x000000733dce)
#5 workerStart rts/Task.c:445 (compact_mutable+0x00000073a9e5)
#6 <null> <null> (libtsan.so.0+0x000000028d5b)
Previous write of size 8 at 0x7b5800000048 by main thread (mutexes: write M16):
#0 compactAllocateBlockInternal rts/sm/CNF.c:209 (compact_mutable+0x000000780661)
#1 compactNew rts/sm/CNF.c:372 (compact_mutable+0x000000780965)
#2 stg_compactNewzh <null> (compact_mutable+0x000000761ceb)
#3 scheduleWaitThread rts/Schedule.c:2559 (compact_mutable+0x000000733d5d)
#4 rts_evalLazyIO rts/RtsAPI.c:530 (compact_mutable+0x00000077b681)
#5 hs_main rts/RtsMain.c:72 (compact_mutable+0x00000072b3e5)
#6 main <null> (compact_mutable+0x000000412da5)
Location is heap block of size 768 at 0x7b5800000000 allocated by main thread:
#0 malloc <null> (libtsan.so.0+0x00000002b251)
#1 stgMallocBytes rts/RtsUtils.c:64 (compact_mutable+0x00000072c63b)
#2 initStorage rts/sm/Storage.c:154 (compact_mutable+0x000000759b40)
#3 hs_init_ghc rts/RtsStartup.c:245 (compact_mutable+0x00000072c210)
#4 hs_main rts/RtsMain.c:57 (compact_mutable+0x00000072b3bb)
#5 main <null> (compact_mutable+0x000000412da5)
Mutex M16 (0x0000009127c0) created at:
#0 pthread_mutex_init <null> (libtsan.so.0+0x00000002c81e)
#1 initMutex rts/posix/OSThreads.c:170 (compact_mutable+0x00000075f937)
#2 initStorage rts/sm/Storage.c:148 (compact_mutable+0x000000759b0b)
#3 hs_init_ghc rts/RtsStartup.c:245 (compact_mutable+0x00000072c210)
#4 hs_main rts/RtsMain.c:57 (compact_mutable+0x00000072b3bb)
#5 main <null> (compact_mutable+0x000000412da5)
Thread T6 (tid=9112, running) created by thread T5 at:
#0 pthread_create <null> (libtsan.so.0+0x00000002c010)
#1 createOSThread rts/posix/OSThreads.c:137 (compact_mutable+0x00000075f8af)
#2 startWorkerTask rts/Task.c:497 (compact_mutable+0x00000073b3fa)
#3 releaseCapability_ rts/Capability.c:567 (compact_mutable+0x000000725367)
#4 suspendThread rts/Schedule.c:2424 (compact_mutable+0x0000007335b4)
#5 <null> <null> (compact_mutable+0x00000068e541)
#6 scheduleWorker rts/Schedule.c:2576 (compact_mutable+0x000000733dce)
#7 workerStart rts/Task.c:445 (compact_mutable+0x00000073a9e5)
#8 <null> <null> (libtsan.so.0+0x000000028d5b)
SUMMARY: ThreadSanitizer: data race (/nix/store/c7hj2bk4aqgpb3q0h5xhq7lag0lq3jm7-gcc-7.4.0-lib/lib/libtsan.so.0+0x6130c) in __tsan_atomic64_load
compactAllocateBlockInternal
updates generation->n_compact_blocks
while holding SM_LOCK
yet calcNeeded
doesn't bother to take SM_LOCK
itself.
Arguably this isn't the end of the world resulting in only a slight change in GC timing.