diff --git a/CHANGELOG.markdown b/CHANGELOG.markdown
--- a/CHANGELOG.markdown
+++ b/CHANGELOG.markdown
@@ -22,3 +22,8 @@
 - revisited memory barriers in light of https://github.com/rrnewton/haskell-lockfree/issues/39, and document them better
 - Added `tryReadChan` functions to all variants
 - get rid of upper bounds on `atomic-primops`
+
+### 0.3.0.1
+
+- fix upper bounds on atomic-primops again (made as revision to cabal metadata for 0.3.0.0
+- fix some docs
diff --git a/benchmarks/multi.hs b/benchmarks/multi.hs
--- a/benchmarks/multi.hs
+++ b/benchmarks/multi.hs
@@ -36,8 +36,16 @@
 
   putStrLn $ "Running with capabilities: "++(show procs)
 
+
+  let writersContending = do
+      writersIndependent = do
+
   defaultMain $
-    [ bgroup ("Operations on "++(show n)++" messages") $
+    [ bgroup "Experiments" $
+       [ bench "Writers contending" $ nfIO $ writersContending
+       , bench "Writers independent" $ nfIO $ writersIndependent
+       ]
+    , bgroup ("Operations on "++(show n)++" messages") $
         [ bgroup "unagi-chan Unagi" $
               -- this gives us a measure of effects of contention between
               -- readers and writers when compared with single-threaded
diff --git a/src/Control/Concurrent/Chan/Unagi/NoBlocking/Internal.hs b/src/Control/Concurrent/Chan/Unagi/NoBlocking/Internal.hs
--- a/src/Control/Concurrent/Chan/Unagi/NoBlocking/Internal.hs
+++ b/src/Control/Concurrent/Chan/Unagi/NoBlocking/Internal.hs
@@ -194,20 +194,22 @@
 --
 -- Usage example:
 --
--- > do mapM_ ('writeChan' i) [1..9]
--- >    [str1, str2, str2] <- 'streamChan' 3 o
--- >    forkIO $ printStream str1   -- prints: 1,4,7
--- >    forkIO $ printStream str2   -- prints: 2,5,8
--- >    forkIO $ printStream str3   -- prints: 3,6,9
--- >  where 
--- >    printStream str = do
--- >      h <- 'tryReadNext' str
--- >      case h of
--- >        'Next' a str' -> print a >> printStream str'
--- >        -- We know that all values were already written, so a Pending tells 
--- >        -- us we can exit; in other cases we might call 'yield' and then 
--- >        -- retry that same @'tryReadNext' str@:
--- >        'Pending' -> return ()
+-- @
+--   do mapM_ ('writeChan' i) [1..9]
+--      [str1, str2, str2] <- 'streamChan' 3 o
+--      forkIO $ printStream str1   -- prints: 1,4,7
+--      forkIO $ printStream str2   -- prints: 2,5,8
+--      forkIO $ printStream str3   -- prints: 3,6,9
+--    where 
+--      printStream str = do
+--        h <- 'tryReadNext' str
+--        case h of
+--          'Next' a str' -> print a >> printStream str'
+--          -- We know that all values were already written, so a Pending tells 
+--          -- us we can exit; in other cases we might call 'yield' and then 
+--          -- retry that same @'tryReadNext' str@:
+--          'Pending' -> return ()
+-- @
 --
 -- Be aware: if one stream consumer falls behind another (e.g. because it is
 -- slower) the number of elements in the queue which can't be GC'd will grow.
diff --git a/src/Control/Concurrent/Chan/Unagi/NoBlocking/Unboxed/Internal.hs b/src/Control/Concurrent/Chan/Unagi/NoBlocking/Unboxed/Internal.hs
--- a/src/Control/Concurrent/Chan/Unagi/NoBlocking/Unboxed/Internal.hs
+++ b/src/Control/Concurrent/Chan/Unagi/NoBlocking/Unboxed/Internal.hs
@@ -240,20 +240,22 @@
 --
 -- Usage example:
 --
--- > do mapM_ ('writeChan' i) [1..9]
--- >    [str1, str2, str2] <- 'streamChan' 3 o
--- >    forkIO $ printStream str1   -- prints: 1,4,7
--- >    forkIO $ printStream str2   -- prints: 2,5,8
--- >    forkIO $ printStream str3   -- prints: 3,6,9
--- >  where 
--- >    printStream str = do
--- >      h <- 'tryReadNext' str
--- >      case h of
--- >        'Next' a str' -> print a >> printStream str'
--- >        -- We know that all values were already written, so a Pending tells 
--- >        -- us we can exit; in other cases we might call 'yield' and then 
--- >        -- retry that same @'tryReadNext' str@:
--- >        'Pending' -> return ()
+-- @
+--   do mapM_ ('writeChan' i) [1..9]
+--      [str1, str2, str2] <- 'streamChan' 3 o
+--      forkIO $ printStream str1   -- prints: 1,4,7
+--      forkIO $ printStream str2   -- prints: 2,5,8
+--      forkIO $ printStream str3   -- prints: 3,6,9
+--    where 
+--      printStream str = do
+--        h <- 'tryReadNext' str
+--        case h of
+--          'Next' a str' -> print a >> printStream str'
+--          -- We know that all values were already written, so a Pending tells 
+--          -- us we can exit; in other cases we might call 'yield' and then 
+--          -- retry that same @'tryReadNext' str@:
+--          'Pending' -> return ()
+-- @
 --
 -- Be aware: if one stream consumer falls behind another (e.g. because it is
 -- slower) the number of elements in the queue which can't be GC'd will grow.
diff --git a/unagi-chan.cabal b/unagi-chan.cabal
--- a/unagi-chan.cabal
+++ b/unagi-chan.cabal
@@ -1,5 +1,5 @@
 name:                unagi-chan
-version:             0.3.0.0
+version:             0.3.0.1
 
 synopsis:            Fast concurrent queues with a Chan-like API, and more
 
@@ -80,9 +80,8 @@
 
   ghc-options:        -Wall -funbox-strict-fields
   build-depends:       base < 5
-                     -- Hopefully if atomic-primops breaks in any subtle ways
-                     -- our tests will be sufficient to notice:
-                     , atomic-primops >= 0.6.0.5
+                     -- 0.6.1.1 is broken on GHC 7.10
+                     , atomic-primops >= 0.6.0.5 && <= 0.6.1
                      , primitive>=0.5.3
                      , ghc-prim
   default-language:    Haskell2010
@@ -143,7 +142,7 @@
     , UnagiUnboxed
   build-depends:       base
                      , primitive>=0.5.3
-                     , atomic-primops >= 0.6.0.5
+                     , atomic-primops >= 0.6.0.5 && <= 0.6.1
                      , containers
                      , ghc-prim
   default-language:    Haskell2010
