[commit: ghc] ghc-parmake-gsoc: Binary: Make lazyGet more thread-safe (25f8cc8)

git at git.haskell.org git at git.haskell.org
Tue Aug 27 16:11:44 CEST 2013


Repository : ssh://git@git.haskell.org/ghc

On branch  : ghc-parmake-gsoc
Link       : http://ghc.haskell.org/trac/ghc/changeset/25f8cc8375068f8277eeaacc530248a7b33edaa1/ghc

>---------------------------------------------------------------

commit 25f8cc8375068f8277eeaacc530248a7b33edaa1
Author: Patrick Palka <patrick at parcs.ath.cx>
Date:   Fri Apr 26 11:20:02 2013 -0400

    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.


>---------------------------------------------------------------

25f8cc8375068f8277eeaacc530248a7b33edaa1
 compiler/utils/Binary.hs |    7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/compiler/utils/Binary.hs b/compiler/utils/Binary.hs
index d14c326..1997d43 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
 





More information about the ghc-commits mailing list