summaryrefslogtreecommitdiff
path: root/compiler/utils
diff options
context:
space:
mode:
authorPatrick Palka <patrick@parcs.ath.cx>2013-04-26 11:20:02 -0400
committerPatrick Palka <patrick@parcs.ath.cx>2013-08-26 22:21:16 -0400
commit25f8cc8375068f8277eeaacc530248a7b33edaa1 (patch)
tree234299892ad6cd9106ebc27c535d4a0bb7cffabf /compiler/utils
parent27d189a7fa833cb6bb33ff001d5472fbf1f589f1 (diff)
downloadhaskell-25f8cc8375068f8277eeaacc530248a7b33edaa1.tar.gz
Binary: Make lazyGet more thread-safe
All values read lazily from the same BinHandle share the same mutable offset variable (_off_r). If two such lazy values are simultaneously evaluated, the two threads will step over each other when writing to _off_r. Fortunately, for BinMem handles, making lazyGet thread-safe is simple: just use a fresh off_r variable when deferring the call to getAt. For BinIO handles, a race condition still exists because IO handles contain their own mutable file pointer variable that gets clobbered in a similar way that _off_r would. But GHC doesn't use BinIO handles anywhere so this particular issue could be ignored for now.
Diffstat (limited to 'compiler/utils')
-rw-r--r--compiler/utils/Binary.hs7
1 files changed, 6 insertions, 1 deletions
diff --git a/compiler/utils/Binary.hs b/compiler/utils/Binary.hs
index d14c326d34..1997d436f8 100644
--- a/compiler/utils/Binary.hs
+++ b/compiler/utils/Binary.hs
@@ -635,11 +635,16 @@ lazyPut bh a = do
putAt bh pre_a q -- fill in slot before a with ptr to q
seekBin bh q -- finally carry on writing at q
+-- XXX: This function is not thread-safe on BinIO handles.
lazyGet :: Binary a => BinHandle -> IO a
lazyGet bh = do
p <- get bh -- a BinPtr
p_a <- tellBin bh
- a <- unsafeInterleaveIO (getAt bh p_a)
+ a <- unsafeInterleaveIO $ do
+ -- NB: Use a fresh off_r variable in the child thread, for thread
+ -- safety.
+ off_r <- newFastMutInt
+ getAt bh { _off_r = off_r } p_a
seekBin bh p -- skip over the object for now
return a