Git Product home page Git Product logo

haskell-lockfree's Issues

CAS fails with newly created ticket

Here I create a new IORef, get a ticket and immediately compare-and-swap. I expect that to succeed and thus the resulting boolean to be True, but it is actually False, regardless of optimization levels. The following features seem relevant, and removing any of them results in the output being True again:

  • the newtype T
  • binding the initial constant (to be put in the IORef) as an INLINE variable (surprisingly, either removing the INLINE pragma or inlining zero by hand make the result True)
  • forcing the ticket before the CAS.

What is wrong here?

import Data.IORef
import Data.Atomics

newtype T = T Int

zero :: T
zero = T 0
{-# INLINE zero #-}

main = do
  x <- newIORef zero
  ticket <- readForCAS x
  (b, _) <- ticket `seq` casIORef x ticket (T 1)
  print b

Counter in atomic-primops not atomic

Tested with 0.4 and whatever's currently in this repo

import Control.Concurrent
import Data.Atomics.Counter
import Control.Monad
import GHC.Conc

main = do
    n0 <- test newCounter readCounter incrCounter
    n1 <- test newMVar takeMVar (\n v-> modifyMVar_ v (return . (+1)) )
    if n0 /= n1
        then putStrLn $ "Counter broken: expecting "++(show n1)++" got "++(show n0)
        else putStrLn "OK"

test new read incr = do
  let n = 100000
  procs <- getNumCapabilities

  counter <- new (1::Int)
  dones <- replicateM procs newEmptyMVar ; starts <- replicateM procs newEmptyMVar
  mapM_ (\(start1,done1)-> forkIO $ takeMVar start1 >> replicateM_ (n `div` procs) (incr 1 counter) >> putMVar done1 ()) $ zip starts dones
  mapM_ (\v-> putMVar v ()) starts ; mapM_ (\v-> takeMVar v) dones

  read counter

On GHC 7.6.3, compiled with cabal 1.18.0.2 with:

executable test-atomics
  main-is:           TestAtomics.hs
  build-depends:       base >=4.6 && <4.7
                     , stm
                     , async
                     , atomic-primops == 0.4

  ghc-options: -O2  -rtsopts  -threaded -with-rtsopts=-N2
  ghc-options: -fforce-recomp
  default-language:    Haskell2010

Recursion in haddocks of `atomic-primops`

In haddocks for atomicModifyIORefCAS I see

A drop-in replacement for `atomicModifyIORefCAS` that...

How is it possible? I there some fixpoint operator for haddocks? :)

Build fail on armv8

GHC 7.10.3, stackage lts-5.1, atomic-primops 8.0.2, architecture: aarch64 (armv8)

[1 of 1] Compiling Main             ( /tmp/stack6984/atomic-primops-0.8.0.2/Setup.hs, /tmp/stack6984/atomic-primops-0.8.0.2/.stack-work/dist/aarch64-linux/Cabal-1.22.7.0/setup/Main.o )
Linking /tmp/stack6984/atomic-primops-0.8.0.2/.stack-work/dist/aarch64-linux/Cabal-1.22.7.0/setup/setup ...
Configuring atomic-primops-0.8.0.2...
Building atomic-primops-0.8.0.2...
Preprocessing library atomic-primops-0.8.0.2...
[1 of 3] Compiling Data.Atomics.Internal ( Data/Atomics/Internal.hs, .stack-work/dist/aarch64-linux/Cabal-1.22.7.0/build/Data/Atomics/Internal.o )

Data/Atomics/Internal.hs:69:20: Warning:
    Defined but not used: data constructor ‘Ticket’
[2 of 3] Compiling Data.Atomics.Counter ( Data/Atomics/Counter.hs, .stack-work/dist/aarch64-linux/Cabal-1.22.7.0/build/Data/Atomics/Counter.o )

In file included from /usr/local/lib/ghc-7.10.3/include/Stg.h:262:0:
    0,
                     from /tmp/ghc7100_0/ghc_14.hc:3:
/tmp/ghc7100_0/ghc_14.hc: In function ‘c1Ni_entry’:

/usr/local/lib/ghc-7.10.3/include/stg/Regs.h:445:28:
     warning: passing argument 1 of ‘hs_atomic_add64’ makes pointer from integer without a cast [enabled by default]
     #define BaseReg (&((struct PartCapability_ *)MainCapability)->r)
                                ^

/usr/local/lib/ghc-7.10.3/include/stg/Regs.h:452:13:
     note: in expansion of macro ‘BaseReg’
     #define Sp (BaseReg->rSp)
                 ^

/tmp/ghc7100_0/ghc_14.hc:59:93:
     note: in expansion of macro ‘Sp’
     _s1LV = hs_atomic_add64((((struct {W_ x;} __attribute__((packed))*) (R1.w+7))->x) + 0x10UL, Sp[1]);
                                                                                                 ^

In file included from /usr/local/lib/ghc-7.10.3/include/Stg.h:273:0:
    0,
                     from /tmp/ghc7100_0/ghc_14.hc:3:

/usr/local/lib/ghc-7.10.3/include/stg/Prim.h:21:11:
     note: expected ‘volatile StgWord64 *’ but argument is of type ‘long unsigned int’
     StgWord64 hs_atomic_add64(volatile StgWord64 *x, StgWord64 val);
               ^

In file included from /usr/local/lib/ghc-7.10.3/include/Stg.h:262:0:
    0,
                     from /tmp/ghc7100_0/ghc_14.hc:3:
/tmp/ghc7100_0/ghc_14.hc: In function ‘c1NY_entry’:

/usr/local/lib/ghc-7.10.3/include/stg/Regs.h:445:28:
     warning: passing argument 1 of ‘hs_atomic_add64’ makes pointer from integer without a cast [enabled by default]
     #define BaseReg (&((struct PartCapability_ *)MainCapability)->r)
                                ^

/usr/local/lib/ghc-7.10.3/include/stg/Regs.h:162:14:
     note: in expansion of macro ‘BaseReg’
     # define R1 (BaseReg->rR1)
                  ^

/tmp/ghc7100_0/ghc_14.hc:143:70:
     note: in expansion of macro ‘R1’
     _s1M5 = hs_atomic_add64((((struct {W_ x;} __attribute__((packed))*) (R1.w+7))->x) + 0x10UL, _s1M0);
                                                                          ^

In file included from /usr/local/lib/ghc-7.10.3/include/Stg.h:273:0:
    0,
                     from /tmp/ghc7100_0/ghc_14.hc:3:

/usr/local/lib/ghc-7.10.3/include/stg/Prim.h:21:11:
     note: expected ‘volatile StgWord64 *’ but argument is of type ‘long unsigned int’
     StgWord64 hs_atomic_add64(volatile StgWord64 *x, StgWord64 val);
               ^

In file included from /usr/local/lib/ghc-7.10.3/include/Stg.h:262:0:
    0,
                     from /tmp/ghc7100_0/ghc_14.hc:3:
/tmp/ghc7100_0/ghc_14.hc: In function ‘r1LH_entry’:

/usr/local/lib/ghc-7.10.3/include/stg/Regs.h:445:28:
     warning: passing argument 1 of ‘hs_cmpxchg64’ makes pointer from integer without a cast [enabled by default]
     #define BaseReg (&((struct PartCapability_ *)MainCapability)->r)
                                ^

/usr/local/lib/ghc-7.10.3/include/stg/Regs.h:452:13:
     note: in expansion of macro ‘BaseReg’
     #define Sp (BaseReg->rSp)
                 ^

/tmp/ghc7100_0/ghc_14.hc:466:45:
     note: in expansion of macro ‘Sp’
     _s1MD = hs_cmpxchg64((*Sp) + 0x10UL, _s1My, Sp[2]);
                                                 ^

In file included from /usr/local/lib/ghc-7.10.3/include/Stg.h:273:0:
    0,
                     from /tmp/ghc7100_0/ghc_14.hc:3:

/usr/local/lib/ghc-7.10.3/include/stg/Prim.h:45:9:
     note: expected ‘volatile StgWord64 *’ but argument is of type ‘long unsigned int’
     StgWord hs_cmpxchg64(volatile StgWord64 *x, StgWord64 old, StgWord64 new_);
             ^

In file included from /usr/local/lib/ghc-7.10.3/include/Stg.h:262:0:
    0,
                     from /tmp/ghc7100_0/ghc_18.hc:3:
/tmp/ghc7100_0/ghc_18.hc: In function ‘c1Ua_entry’:

/usr/local/lib/ghc-7.10.3/include/stg/Regs.h:445:28:
     warning: passing argument 1 of ‘hs_atomic_add64’ makes pointer from integer without a cast [enabled by default]
     #define BaseReg (&((struct PartCapability_ *)MainCapability)->r)
                                ^

/usr/local/lib/ghc-7.10.3/include/stg/Regs.h:452:13:
     note: in expansion of macro ‘BaseReg’
     #define Sp (BaseReg->rSp)
                 ^

/tmp/ghc7100_0/ghc_18.hc:59:93:
     note: in expansion of macro ‘Sp’
     _s1SN = hs_atomic_add64((((struct {W_ x;} __attribute__((packed))*) (R1.w+7))->x) + 0x10UL, Sp[1]);
                                                                                                 ^

In file included from /usr/local/lib/ghc-7.10.3/include/Stg.h:273:0:
    0,
                     from /tmp/ghc7100_0/ghc_18.hc:3:

/usr/local/lib/ghc-7.10.3/include/stg/Prim.h:21:11:
     note: expected ‘volatile StgWord64 *’ but argument is of type ‘long unsigned int’
     StgWord64 hs_atomic_add64(volatile StgWord64 *x, StgWord64 val);
               ^

In file included from /usr/local/lib/ghc-7.10.3/include/Stg.h:262:0:
    0,
                     from /tmp/ghc7100_0/ghc_18.hc:3:
/tmp/ghc7100_0/ghc_18.hc: In function ‘c1UQ_entry’:

/usr/local/lib/ghc-7.10.3/include/stg/Regs.h:445:28:
     warning: passing argument 1 of ‘hs_atomic_add64’ makes pointer from integer without a cast [enabled by default]
     #define BaseReg (&((struct PartCapability_ *)MainCapability)->r)
                                ^

/usr/local/lib/ghc-7.10.3/include/stg/Regs.h:162:14:
     note: in expansion of macro ‘BaseReg’
     # define R1 (BaseReg->rR1)
                  ^

/tmp/ghc7100_0/ghc_18.hc:143:70:
     note: in expansion of macro ‘R1’
     _s1SX = hs_atomic_add64((((struct {W_ x;} __attribute__((packed))*) (R1.w+7))->x) + 0x10UL, _s1SS);
                                                                          ^

In file included from /usr/local/lib/ghc-7.10.3/include/Stg.h:273:0:
    0,
                     from /tmp/ghc7100_0/ghc_18.hc:3:

/usr/local/lib/ghc-7.10.3/include/stg/Prim.h:21:11:
     note: expected ‘volatile StgWord64 *’ but argument is of type ‘long unsigned int’
     StgWord64 hs_atomic_add64(volatile StgWord64 *x, StgWord64 val);
               ^

In file included from /usr/local/lib/ghc-7.10.3/include/Stg.h:262:0:
    0,
                     from /tmp/ghc7100_0/ghc_18.hc:3:
/tmp/ghc7100_0/ghc_18.hc: In function ‘r1LH_entry’:

/usr/local/lib/ghc-7.10.3/include/stg/Regs.h:445:28:
     warning: passing argument 1 of ‘hs_cmpxchg64’ makes pointer from integer without a cast [enabled by default]
     #define BaseReg (&((struct PartCapability_ *)MainCapability)->r)
                                ^

/usr/local/lib/ghc-7.10.3/include/stg/Regs.h:452:13:
     note: in expansion of macro ‘BaseReg’
     #define Sp (BaseReg->rSp)
                 ^

/tmp/ghc7100_0/ghc_18.hc:466:45:
     note: in expansion of macro ‘Sp’
     _s1Tv = hs_cmpxchg64((*Sp) + 0x10UL, _s1Tq, Sp[2]);
                                                 ^

In file included from /usr/local/lib/ghc-7.10.3/include/Stg.h:273:0:
    0,
                     from /tmp/ghc7100_0/ghc_18.hc:3:

/usr/local/lib/ghc-7.10.3/include/stg/Prim.h:45:9:
     note: expected ‘volatile StgWord64 *’ but argument is of type ‘long unsigned int’
     StgWord hs_cmpxchg64(volatile StgWord64 *x, StgWord64 old, StgWord64 new_);
             ^
[3 of 3] Compiling Data.Atomics     ( Data/Atomics.hs, .stack-work/dist/aarch64-linux/Cabal-1.22.7.0/build/Data/Atomics.o )

In file included from /usr/local/lib/ghc-7.10.3/include/Stg.h:262:0:
    0,
                     from /tmp/ghc7100_0/ghc_23.hc:3:
/tmp/ghc7100_0/ghc_23.hc: In function ‘c3dY_entry’:

/usr/local/lib/ghc-7.10.3/include/stg/Regs.h:445:28:
     warning: passing argument 1 of ‘hs_atomic_add64’ makes pointer from integer without a cast [enabled by default]
     #define BaseReg (&((struct PartCapability_ *)MainCapability)->r)
                                ^

/usr/local/lib/ghc-7.10.3/include/stg/Regs.h:452:13:
     note: in expansion of macro ‘BaseReg’
     #define Sp (BaseReg->rSp)
                 ^

/tmp/ghc7100_0/ghc_23.hc:239:38:
     note: in expansion of macro ‘Sp’
     _s37V = hs_atomic_add64((Sp[1]) + (((Sp[2]) << 0x3UL) + 0x10UL), _s37S);
                                          ^

In file included from /usr/local/lib/ghc-7.10.3/include/Stg.h:273:0:
    0,
                     from /tmp/ghc7100_0/ghc_23.hc:3:

/usr/local/lib/ghc-7.10.3/include/stg/Prim.h:21:11:
     note: expected ‘volatile StgWord64 *’ but argument is of type ‘long unsigned int’
     StgWord64 hs_atomic_add64(volatile StgWord64 *x, StgWord64 val);
               ^

In file included from /usr/local/lib/ghc-7.10.3/include/Stg.h:262:0:
    0,
                     from /tmp/ghc7100_0/ghc_23.hc:3:
/tmp/ghc7100_0/ghc_23.hc: In function ‘c3eQ_entry’:

/usr/local/lib/ghc-7.10.3/include/stg/Regs.h:445:28:
     warning: passing argument 1 of ‘hs_atomic_xor64’ makes pointer from integer without a cast [enabled by default]
     #define BaseReg (&((struct PartCapability_ *)MainCapability)->r)
                                ^

/usr/local/lib/ghc-7.10.3/include/stg/Regs.h:162:14:
     note: in expansion of macro ‘BaseReg’
     # define R1 (BaseReg->rR1)
                  ^

/tmp/ghc7100_0/ghc_23.hc:349:110:
     note: in expansion of macro ‘R1’
     _s38a = hs_atomic_xor64((Sp[1]) + (((Sp[2]) << 0x3UL) + 0x10UL), ((struct {W_ x;} __attribute__((packed))*) (R1.w+7))->x);
                                                                                                                  ^

In file included from /usr/local/lib/ghc-7.10.3/include/Stg.h:273:0:
    0,
                     from /tmp/ghc7100_0/ghc_23.hc:3:

/usr/local/lib/ghc-7.10.3/include/stg/Prim.h:41:11:
     note: expected ‘volatile StgWord64 *’ but argument is of type ‘long unsigned int’
     StgWord64 hs_atomic_xor64(volatile StgWord64 *x, StgWord64 val);
               ^

In file included from /usr/local/lib/ghc-7.10.3/include/Stg.h:262:0:
    0,
                     from /tmp/ghc7100_0/ghc_23.hc:3:
/tmp/ghc7100_0/ghc_23.hc: In function ‘c3fF_entry’:

/usr/local/lib/ghc-7.10.3/include/stg/Regs.h:445:28:
     warning: passing argument 1 of ‘hs_atomic_or64’ makes pointer from integer without a cast [enabled by default]
     #define BaseReg (&((struct PartCapability_ *)MainCapability)->r)
                                ^

/usr/local/lib/ghc-7.10.3/include/stg/Regs.h:162:14:
     note: in expansion of macro ‘BaseReg’
     # define R1 (BaseReg->rR1)
                  ^

/tmp/ghc7100_0/ghc_23.hc:459:109:
     note: in expansion of macro ‘R1’
     _s38o = hs_atomic_or64((Sp[1]) + (((Sp[2]) << 0x3UL) + 0x10UL), ((struct {W_ x;} __attribute__((packed))*) (R1.w+7))->x);
                                                                                                                 ^

In file included from /usr/local/lib/ghc-7.10.3/include/Stg.h:273:0:
    0,
                     from /tmp/ghc7100_0/ghc_23.hc:3:

/usr/local/lib/ghc-7.10.3/include/stg/Prim.h:37:11:
     note: expected ‘volatile StgWord64 *’ but argument is of type ‘long unsigned int’
     StgWord64 hs_atomic_or64(volatile StgWord64 *x, StgWord64 val);
               ^

In file included from /usr/local/lib/ghc-7.10.3/include/Stg.h:262:0:
    0,
                     from /tmp/ghc7100_0/ghc_23.hc:3:
/tmp/ghc7100_0/ghc_23.hc: In function ‘c3gu_entry’:

/usr/local/lib/ghc-7.10.3/include/stg/Regs.h:445:28:
     warning: passing argument 1 of ‘hs_atomic_nand64’ makes pointer from integer without a cast [enabled by default]
     #define BaseReg (&((struct PartCapability_ *)MainCapability)->r)
                                ^

/usr/local/lib/ghc-7.10.3/include/stg/Regs.h:162:14:
     note: in expansion of macro ‘BaseReg’
     # define R1 (BaseReg->rR1)
                  ^

/tmp/ghc7100_0/ghc_23.hc:569:111:
     note: in expansion of macro ‘R1’
     _s38C = hs_atomic_nand64((Sp[1]) + (((Sp[2]) << 0x3UL) + 0x10UL), ((struct {W_ x;} __attribute__((packed))*) (R1.w+7))->x);
                                                                                                                   ^

In file included from /usr/local/lib/ghc-7.10.3/include/Stg.h:273:0:
    0,
                     from /tmp/ghc7100_0/ghc_23.hc:3:

/usr/local/lib/ghc-7.10.3/include/stg/Prim.h:33:11:
     note: expected ‘volatile StgWord64 *’ but argument is of type ‘long unsigned int’
     StgWord64 hs_atomic_nand64(volatile StgWord64 *x, StgWord64 val);
               ^

In file included from /usr/local/lib/ghc-7.10.3/include/Stg.h:262:0:
    0,
                     from /tmp/ghc7100_0/ghc_23.hc:3:
/tmp/ghc7100_0/ghc_23.hc: In function ‘c3hj_entry’:

/usr/local/lib/ghc-7.10.3/include/stg/Regs.h:445:28:
     warning: passing argument 1 of ‘hs_atomic_and64’ makes pointer from integer without a cast [enabled by default]
     #define BaseReg (&((struct PartCapability_ *)MainCapability)->r)
                                ^

/usr/local/lib/ghc-7.10.3/include/stg/Regs.h:162:14:
     note: in expansion of macro ‘BaseReg’
     # define R1 (BaseReg->rR1)
                  ^

/tmp/ghc7100_0/ghc_23.hc:679:110:
     note: in expansion of macro ‘R1’
     _s38Q = hs_atomic_and64((Sp[1]) + (((Sp[2]) << 0x3UL) + 0x10UL), ((struct {W_ x;} __attribute__((packed))*) (R1.w+7))->x);
                                                                                                                  ^

In file included from /usr/local/lib/ghc-7.10.3/include/Stg.h:273:0:
    0,
                     from /tmp/ghc7100_0/ghc_23.hc:3:

/usr/local/lib/ghc-7.10.3/include/stg/Prim.h:29:11:
     note: expected ‘volatile StgWord64 *’ but argument is of type ‘long unsigned int’
     StgWord64 hs_atomic_and64(volatile StgWord64 *x, StgWord64 val);
               ^

In file included from /usr/local/lib/ghc-7.10.3/include/Stg.h:262:0:
    0,
                     from /tmp/ghc7100_0/ghc_23.hc:3:
/tmp/ghc7100_0/ghc_23.hc: In function ‘c3i8_entry’:

/usr/local/lib/ghc-7.10.3/include/stg/Regs.h:445:28:
     warning: passing argument 1 of ‘hs_atomic_sub64’ makes pointer from integer without a cast [enabled by default]
     #define BaseReg (&((struct PartCapability_ *)MainCapability)->r)
                                ^

/usr/local/lib/ghc-7.10.3/include/stg/Regs.h:162:14:
     note: in expansion of macro ‘BaseReg’
     # define R1 (BaseReg->rR1)
                  ^

/tmp/ghc7100_0/ghc_23.hc:789:110:
     note: in expansion of macro ‘R1’
     _s394 = hs_atomic_sub64((Sp[1]) + (((Sp[2]) << 0x3UL) + 0x10UL), ((struct {W_ x;} __attribute__((packed))*) (R1.w+7))->x);
                                                                                                                  ^

In file included from /usr/local/lib/ghc-7.10.3/include/Stg.h:273:0:
    0,
                     from /tmp/ghc7100_0/ghc_23.hc:3:

/usr/local/lib/ghc-7.10.3/include/stg/Prim.h:25:11:
     note: expected ‘volatile StgWord64 *’ but argument is of type ‘long unsigned int’
     StgWord64 hs_atomic_sub64(volatile StgWord64 *x, StgWord64 val);
               ^

In file included from /usr/local/lib/ghc-7.10.3/include/Stg.h:262:0:
    0,
                     from /tmp/ghc7100_0/ghc_23.hc:3:
/tmp/ghc7100_0/ghc_23.hc: In function ‘c3iX_entry’:

/usr/local/lib/ghc-7.10.3/include/stg/Regs.h:445:28:
     warning: passing argument 1 of ‘hs_atomic_add64’ makes pointer from integer without a cast [enabled by default]
     #define BaseReg (&((struct PartCapability_ *)MainCapability)->r)
                                ^

/usr/local/lib/ghc-7.10.3/include/stg/Regs.h:162:14:
     note: in expansion of macro ‘BaseReg’
     # define R1 (BaseReg->rR1)
                  ^

/tmp/ghc7100_0/ghc_23.hc:899:110:
     note: in expansion of macro ‘R1’
     _s39i = hs_atomic_add64((Sp[1]) + (((Sp[2]) << 0x3UL) + 0x10UL), ((struct {W_ x;} __attribute__((packed))*) (R1.w+7))->x);
                                                                                                                  ^

In file included from /usr/local/lib/ghc-7.10.3/include/Stg.h:273:0:
    0,
                     from /tmp/ghc7100_0/ghc_23.hc:3:

/usr/local/lib/ghc-7.10.3/include/stg/Prim.h:21:11:
     note: expected ‘volatile StgWord64 *’ but argument is of type ‘long unsigned int’
     StgWord64 hs_atomic_add64(volatile StgWord64 *x, StgWord64 val);
               ^

In file included from /usr/local/lib/ghc-7.10.3/include/Stg.h:262:0:
    0,
                     from /tmp/ghc7100_0/ghc_23.hc:3:
/tmp/ghc7100_0/ghc_23.hc: In function ‘c3jU_entry’:

/usr/local/lib/ghc-7.10.3/include/stg/Regs.h:445:28:
     warning: passing argument 1 of ‘hs_cmpxchg64’ makes pointer from integer without a cast [enabled by default]
     #define BaseReg (&((struct PartCapability_ *)MainCapability)->r)
                                ^

/usr/local/lib/ghc-7.10.3/include/stg/Regs.h:162:14:
     note: in expansion of macro ‘BaseReg’
     # define R1 (BaseReg->rR1)
                  ^

/tmp/ghc7100_0/ghc_23.hc:1031:114:
     note: in expansion of macro ‘R1’
     _s39z = hs_cmpxchg64((Sp[1]) + (((Sp[2]) << 0x3UL) + 0x10UL), Sp[3], ((struct {W_ x;} __attribute__((packed))*) (R1.w+7))->x);
                                                                                                                      ^

In file included from /usr/local/lib/ghc-7.10.3/include/Stg.h:273:0:
    0,
                     from /tmp/ghc7100_0/ghc_23.hc:3:

/usr/local/lib/ghc-7.10.3/include/stg/Prim.h:45:9:
     note: expected ‘volatile StgWord64 *’ but argument is of type ‘long unsigned int’
     StgWord hs_cmpxchg64(volatile StgWord64 *x, StgWord64 old, StgWord64 new_);
             ^

In file included from /tmp/ghc7100_0/ghc_23.hc:3:0: 
/tmp/ghc7100_0/ghc_23.hc: At top level:

/tmp/ghc7100_0/ghc_23.hc:2704:5:
     error: conflicting types for ‘store_load_barrier’
     EF_(store_load_barrier);
         ^

/usr/local/lib/ghc-7.10.3/include/Stg.h:220:36:
     note: in definition of macro ‘EF_’
     #define EF_(f)    extern StgFunPtr f()   /* See Note [External function prototypes] */
                                        ^

In file included from /usr/local/lib/ghc-7.10.3/include/Stg.h:274:0:
    0,
                     from /tmp/ghc7100_0/ghc_23.hc:3:

/usr/local/lib/ghc-7.10.3/include/stg/SMP.h:422:20:
     note: previous definition of ‘store_load_barrier’ was here
     EXTERN_INLINE void store_load_barrier() {} /* nothing */
                        ^

In file included from /tmp/ghc7100_0/ghc_23.hc:3:0: 

/tmp/ghc7100_0/ghc_23.hc:2741:5:
     error: conflicting types for ‘load_load_barrier’
     EF_(load_load_barrier);
         ^

/usr/local/lib/ghc-7.10.3/include/Stg.h:220:36:
     note: in definition of macro ‘EF_’
     #define EF_(f)    extern StgFunPtr f()   /* See Note [External function prototypes] */
                                        ^

In file included from /usr/local/lib/ghc-7.10.3/include/Stg.h:274:0:
    0,
                     from /tmp/ghc7100_0/ghc_23.hc:3:

/usr/local/lib/ghc-7.10.3/include/stg/SMP.h:423:20:
     note: previous definition of ‘load_load_barrier’ was here
     EXTERN_INLINE void load_load_barrier () {} /* nothing */
                        ^

In file included from /tmp/ghc7100_0/ghc_23.hc:3:0: 

/tmp/ghc7100_0/ghc_23.hc:2778:5:
     error: conflicting types for ‘write_barrier’
     EF_(write_barrier);
         ^

/usr/local/lib/ghc-7.10.3/include/Stg.h:220:36:
     note: in definition of macro ‘EF_’
     #define EF_(f)    extern StgFunPtr f()   /* See Note [External function prototypes] */
                                        ^

In file included from /usr/local/lib/ghc-7.10.3/include/Stg.h:274:0:
    0,
                     from /tmp/ghc7100_0/ghc_23.hc:3:

/usr/local/lib/ghc-7.10.3/include/stg/SMP.h:421:20:
     note: previous definition of ‘write_barrier’ was here
     EXTERN_INLINE void write_barrier     () {} /* nothing */
                        ^

atomic-primops: ghc 8 support needed

I'm updating all my packages for ghc 8-rc1 support, and am stuck on all of them that depend on atomic-primops. This seems likely to just be a bump and push.

Provide loop wrapper for casArrayElem?

The casArrayElem provide a low-level atomic operations based on Ticket, Is there any possibilities to provide a loop wrapper similar to atomicModifyIORef? As an user i only care about swapping a new result into array and get the old value out rather than manually compare pointer and looping.

Missing load-store barrier

Data.Atomics has writeBarrier (store-store), storeLoadBarrier, and loadLoadBarrier, but seems to be missing a load-store barrier. This would be a no-op at the hardware level on x86, but it would still need to prevent compiler reordering, like writeBarrier and loadLoadBarrier.

(I know enough about memory models to be aware that my understanding could be completely wrong—please correct me if so.)

atomic-primops does not compile with ghc-7.4, problem with Any type

I've spotted this commit that suggests the Any type should not cause issues with GHC-7.4. However, at least on Linux, the following is me trying with 7.4 and failing, then 7.6 and succeeding:

$ export PATH=~/sw/ghc/7.4.1/x86_64/bin:$PATH
bash-4.1$ cabal clean
cleaning...
Error while removing dist/: dist/setup: removeDirectory: unsatisified constraints (Directory not empty)
bash-4.1$ cabal install
Resolving dependencies...
[1 of 1] Compiling Main             ( Setup.hs, dist/setup/Main.o )
Linking ./dist/setup/setup ...
Configuring atomic-primops-0.2.2.1...
Building atomic-primops-0.2.2.1...
Preprocessing library atomic-primops-0.2.2.1...
[1 of 6] Compiling Data.Atomics.Counter.Foreign ( Data/Atomics/Counter/Foreign.hs, dist/build/Data/Atomics/Counter/Foreign.o )
[2 of 6] Compiling Data.Atomics.Counter.Reference ( Data/Atomics/Counter/Reference.hs, dist/build/Data/Atomics/Counter/Reference.o )
[3 of 6] Compiling Data.Atomics.Internal ( Data/Atomics/Internal.hs, dist/build/Data/Atomics/Internal.o )

Data/Atomics/Internal.hs:115:1:
    Unacceptable argument type in foreign declaration: Any (* -> *) ()
    When checking declaration:
      foreign import prim safe "static stg_casArrayzh" casArrayTypeErased#
        :: MutableArray# RealWorld ()
           -> Int#
              -> Any ()
                 -> Any ()
                    -> State# RealWorld -> (# State# RealWorld, Int#, Any () #)

Data/Atomics/Internal.hs:115:1:
    Unacceptable argument type in foreign declaration: Any (* -> *) ()
    When checking declaration:                                                                                                                                                     
      foreign import prim safe "static stg_casArrayzh" casArrayTypeErased#
        :: MutableArray# RealWorld ()
           -> Int#
              -> Any ()
                 -> Any ()
                    -> State# RealWorld -> (# State# RealWorld, Int#, Any () #)

Data/Atomics/Internal.hs:123:1:
    Unacceptable argument type in foreign declaration: Any (* -> *) ()
    When checking declaration:
      foreign import prim safe "static stg_casMutVar2zh" casMutVar_TypeErased#
        :: MutVar# RealWorld ()
           -> Any ()
              -> Any ()
                 -> State# RealWorld -> (# State# RealWorld, Int#, Any () #)

Data/Atomics/Internal.hs:123:1:
    Unacceptable argument type in foreign declaration: Any (* -> *) ()
    When checking declaration:
      foreign import prim safe "static stg_casMutVar2zh" casMutVar_TypeErased#
        :: MutVar# RealWorld ()
           -> Any ()
              -> Any ()
                 -> State# RealWorld -> (# State# RealWorld, Int#, Any () #)
cabal: Error: some packages failed to install:
atomic-primops-0.2.2.1 failed during the building phase. The exception was:
ExitFailure 1

$ export PATH=~/sw/ghc/ghc-7.6.3-BUILD/bin:$PATH
bash-4.1$ cabal clean
cleaning...
Error while removing dist/: dist/setup: removeDirectory: unsatisified constraints (Directory not empty)
bash-4.1$ cabal install
Resolving dependencies...
[1 of 1] Compiling Main             ( /tmp/bits-atomic-0.1.3-19929/bits-atomic-0.1.3/Setup.hs, /tmp/bits-atomic-0.1.3-19929/bits-atomic-0.1.3/dist/setup/Main.o )

/tmp/bits-atomic-0.1.3-19929/bits-atomic-0.1.3/Setup.hs:15:35: Warning:
    In the use of `runTests'
    (imported from Distribution.Simple, but defined in Distribution.Simple.UserHooks):
    Deprecated: "Please use the new testing interface instead!"
Linking /tmp/bits-atomic-0.1.3-19929/bits-atomic-0.1.3/dist/setup/setup ...
Configuring bits-atomic-0.1.3...
Building bits-atomic-0.1.3...
Preprocessing library bits-atomic-0.1.3...
[1 of 1] Compiling Data.Bits.Atomic ( Data/Bits/Atomic.hs, dist/build/Data/Bits/Atomic.o )
cbits/atomic-bitops-gcc.c: In function ‘nand_and_fetch_word’:

cbits/atomic-bitops-gcc.c:260:0:
     note: ‘__sync_nand_and_fetch’ changed semantics in GCC 4.4
cbits/atomic-bitops-gcc.c: In function ‘fetch_and_nand_word’:

cbits/atomic-bitops-gcc.c:242:0:
     note: ‘__sync_fetch_and_nand’ changed semantics in GCC 4.4
In-place registering bits-atomic-0.1.3...
Installing library in ~/.cabal/lib/bits-atomic-0.1.3/ghc-7.6.3
Registering bits-atomic-0.1.3...
[1 of 1] Compiling Main             ( Setup.hs, dist/setup/Main.o )
Linking ./dist/setup/setup ...
Configuring atomic-primops-0.2.2.1...
Building atomic-primops-0.2.2.1...
Preprocessing library atomic-primops-0.2.2.1...
[1 of 6] Compiling Data.Atomics.Counter.Foreign ( Data/Atomics/Counter/Foreign.hs, dist/build/Data/Atomics/Counter/Foreign.o )
[2 of 6] Compiling Data.Atomics.Counter.Reference ( Data/Atomics/Counter/Reference.hs, dist/build/Data/Atomics/Counter/Reference.o )
[3 of 6] Compiling Data.Atomics.Internal ( Data/Atomics/Internal.hs, dist/build/Data/Atomics/Internal.o )
[4 of 6] Compiling Data.Atomics     ( Data/Atomics.hs, dist/build/Data/Atomics.o )
[5 of 6] Compiling Data.Atomics.Counter.IORef ( Data/Atomics/Counter/IORef.hs, dist/build/Data/Atomics/Counter/IORef.o )
[6 of 6] Compiling Data.Atomics.Counter ( Data/Atomics/Counter.hs, dist/build/Data/Atomics/Counter.o )
In-place registering atomic-primops-0.2.2.1...
Installing library in ~/.cabal/lib/atomic-primops-0.2.2.1/ghc-7.6.3
Registering atomic-primops-0.2.2.1...

Cabal install error - HSatomic-primops-0.6.0.6.o: unknown symbol `store_load_barrier'

When doing a cabal install on yesod-core the following error is thrown when linking atomic-primops:

$ cabal install -j
Resolving dependencies...
Notice: installing into a sandbox located at
X:\Projects\yesod\yesod-core\.cabal-sandbox
Configuring ansi-terminal-0.6.1.1...
Configuring auto-update-0.1.1.4...
Configuring atomic-primops-0.6.0.6...
Configuring byteable-0.1.1...
Configuring byteorder-1.0.4...
Configuring base64-bytestring-1.0.0.1...
Configuring blaze-builder-0.3.3.4...
Configuring cereal-0.4.0.1...
Building auto-update-0.1.1.4...
Building byteorder-1.0.4...
Building byteable-0.1.1...
Building blaze-builder-0.3.3.4...
Building ansi-terminal-0.6.1.1...
Building cereal-0.4.0.1...
Building base64-bytestring-1.0.0.1...
Installed byteable-0.1.1
Configuring data-default-class-0.0.1...
Building atomic-primops-0.6.0.6...
Configuring dlist-0.7.1...
Installed auto-update-0.1.1.4
Building data-default-class-0.0.1...
Installed byteorder-1.0.4
Configuring easy-file-0.2.0...
Building dlist-0.7.1...
Configuring entropy-0.3.3...
Installed base64-bytestring-1.0.0.1
Building easy-file-0.2.0...
Configuring exceptions-0.6.1...
Installed atomic-primops-0.6.0.6
Configuring mmorph-1.0.4...
Installed data-default-class-0.0.1
Building exceptions-0.6.1...
Configuring monad-loops-0.4.2.1...
Installed ansi-terminal-0.6.1.1
Building mmorph-1.0.4...
Building entropy-0.3.3...
Configuring nats-0.2...
Installed blaze-builder-0.3.3.4
Building monad-loops-0.4.2.1...
Configuring path-pieces-0.1.4...
Installed dlist-0.7.1
Building nats-0.2...
Configuring safe-0.3.8...
Installed easy-file-0.2.0
Building path-pieces-0.1.4...
Configuring scientific-0.2.0.2...
Installed cereal-0.4.0.1
Building safe-0.3.8...
Configuring setenv-0.1.1.1...
Installed exceptions-0.6.1
Building scientific-0.2.0.2...
Configuring stm-chans-3.0.0.2...
Installed mmorph-1.0.4
Building setenv-0.1.1.1...
Configuring stringsearch-0.3.6.5...
Installed entropy-0.3.3
Configuring system-filepath-0.4.12...
Installed monad-loops-0.4.2.1
Building stringsearch-0.3.6.5...
Configuring tagged-0.7.2...
Installed nats-0.2
Building stm-chans-3.0.0.2...
Configuring transformers-base-0.4.3...
Installed path-pieces-0.1.4
Building tagged-0.7.2...
Configuring unix-compat-0.4.1.3...
Installed safe-0.3.8
Building system-filepath-0.4.12...
Building transformers-base-0.4.3...
Configuring vault-0.3.0.3...
Installed setenv-0.1.1.1
Building unix-compat-0.4.1.3...
Configuring word8-0.1.1...
Installed scientific-0.2.0.2
Building vault-0.3.0.3...
Configuring securemem-0.1.3...
Installed stm-chans-3.0.0.2
Building word8-0.1.1...
Installed tagged-0.7.2
Configuring data-default-instances-base-0.0.1...
Building securemem-0.1.3...
Installed transformers-base-0.4.3
Configuring data-default-instances-containers-0.0.1...
Building data-default-instances-base-0.0.1...
Configuring data-default-instances-old-locale-0.0.1...
Installed word8-0.1.1
Building data-default-instances-containers-0.0.1...
Configuring blaze-markup-0.6.1.1...
Installed stringsearch-0.3.6.5
Building data-default-instances-old-locale-0.0.1...
Configuring fast-logger-2.2.0...
Installed vault-0.3.0.3
Building blaze-markup-0.6.1.1...
Configuring http-types-0.8.5...
Installed securemem-0.1.3
Building fast-logger-2.2.0...
Configuring streaming-commons-0.1.5...
Installed data-default-instances-base-0.0.1
Building http-types-0.8.5...
Configuring data-default-instances-dlist-0.0.1...
Installed unix-compat-0.4.1.3
Building streaming-commons-0.1.5...
Configuring semigroups-0.15.3...
Installed data-default-instances-containers-0.0.1
Building data-default-instances-dlist-0.0.1...
Configuring aeson-0.7.0.4...
Installed data-default-instances-old-locale-0.0.1
Building semigroups-0.15.3...
Configuring crypto-api-0.13.2...
Installed fast-logger-2.2.0
Building aeson-0.7.0.4...
Installed blaze-markup-0.6.1.1
Configuring monad-control-0.3.3.0...
Building crypto-api-0.13.2...
Configuring crypto-cipher-types-0.0.9...
Installed data-default-instances-dlist-0.0.1
Building monad-control-0.3.3.0...
Installed http-types-0.8.5
Configuring crypto-random-0.0.8...
Building crypto-cipher-types-0.0.9...
Building crypto-random-0.0.8...
Installed monad-control-0.3.3.0
Configuring blaze-html-0.7.0.3...
Configuring data-default-0.5.3...
Installed streaming-commons-0.1.5
Building blaze-html-0.7.0.3...
Installed crypto-cipher-types-0.0.9
Configuring wai-3.0.2...
Building data-default-0.5.3...
Installed semigroups-0.15.3
Configuring lifted-base-0.2.3.0...
Building wai-3.0.2...
Installed crypto-random-0.0.8
Configuring cipher-aes-0.2.8...
Building lifted-base-0.2.3.0...
Configuring void-0.6.1...
Installed crypto-api-0.13.2
Building cipher-aes-0.2.8...
Installed system-filepath-0.4.12
Configuring skein-1.0.9...
Building void-0.6.1...
Configuring system-fileio-0.3.14...
Installed data-default-0.5.3
Building skein-1.0.9...
Installed wai-3.0.2
Configuring cookie-0.4.1.4...
Building system-fileio-0.3.14...
Configuring wai-logger-2.2.3...
Installed lifted-base-0.2.3.0
Building cookie-0.4.1.4...
Configuring resourcet-1.1.2.3...
Installed void-0.6.1
Building wai-logger-2.2.3...
Installed cipher-aes-0.2.8
Configuring cprng-aes-0.5.2...
Building resourcet-1.1.2.3...
Installed system-fileio-0.3.14
Building cprng-aes-0.5.2...
Installed skein-1.0.9
Installed cookie-0.4.1.4
Installed wai-logger-2.2.3
Installed blaze-html-0.7.0.3
Installed cprng-aes-0.5.2
Configuring clientsession-0.9.1...
Installed resourcet-1.1.2.3
Configuring conduit-1.2.1...
Configuring wai-extra-3.0.2.1...
Building clientsession-0.9.1...
Installed aeson-0.7.0.4
Configuring shakespeare-2.0.1.1...
Building conduit-1.2.1...
Building wai-extra-3.0.2.1...
Building shakespeare-2.0.1.1...
Installed clientsession-0.9.1
Installed conduit-1.2.1
Configuring conduit-extra-1.1.4...
Installed wai-extra-3.0.2.1
Building conduit-extra-1.1.4...
Installed conduit-extra-1.1.4
Configuring monad-logger-0.3.7.2...
Configuring simple-sendfile-0.2.18...
Building simple-sendfile-0.2.18...
Building monad-logger-0.3.7.2...
Installed simple-sendfile-0.2.18
Configuring warp-3.0.2.2...
Installed monad-logger-0.3.7.2
Building warp-3.0.2.2...
Installed shakespeare-2.0.1.1
Installed warp-3.0.2.2
Configuring yesod-core-1.4.1.1...
Building yesod-core-1.4.1.1...
Failed to install yesod-core-1.4.1.1
Build log ( X:\Projects\yesod\yesod-core\.cabal-sandbox\logs\yesod-core-1.4.1.1.log ):
Building yesod-core-1.4.1.1...
Preprocessing library yesod-core-1.4.1.1...
[ 1 of 30] Compiling Yesod.Routes.TH.Types ( Yesod\Routes\TH\Types.hs, dist\dist-sandbox-ea28e1ab\build\Yesod\Routes\TH\Types.o )
[ 2 of 30] Compiling Yesod.Routes.TH.Dispatch ( Yesod\Routes\TH\Dispatch.hs, dist\dist-sandbox-ea28e1ab\build\Yesod\Routes\TH\Dispatch.o )
[ 3 of 30] Compiling Yesod.Routes.Overlap ( Yesod\Routes\Overlap.hs, dist\dist-sandbox-ea28e1ab\build\Yesod\Routes\Overlap.o )
[ 4 of 30] Compiling Yesod.Core.TypeCache ( Yesod\Core\TypeCache.hs, dist\dist-sandbox-ea28e1ab\build\Yesod\Core\TypeCache.o )
[ 5 of 30] Compiling Yesod.Routes.Class ( Yesod\Routes\Class.hs, dist\dist-sandbox-ea28e1ab\build\Yesod\Routes\Class.o )
[ 6 of 30] Compiling Yesod.Routes.TH.RenderRoute ( Yesod\Routes\TH\RenderRoute.hs, dist\dist-sandbox-ea28e1ab\build\Yesod\Routes\TH\RenderRoute.o )
[ 7 of 30] Compiling Yesod.Routes.TH.ParseRoute ( Yesod\Routes\TH\ParseRoute.hs, dist\dist-sandbox-ea28e1ab\build\Yesod\Routes\TH\ParseRoute.o )
[ 8 of 30] Compiling Yesod.Routes.TH.RouteAttrs ( Yesod\Routes\TH\RouteAttrs.hs, dist\dist-sandbox-ea28e1ab\build\Yesod\Routes\TH\RouteAttrs.o )
[ 9 of 30] Compiling Yesod.Routes.TH  ( Yesod\Routes\TH.hs, dist\dist-sandbox-ea28e1ab\build\Yesod\Routes\TH.o )
[10 of 30] Compiling Yesod.Routes.Parse ( Yesod\Routes\Parse.hs, dist\dist-sandbox-ea28e1ab\build\Yesod\Routes\Parse.o )
[11 of 30] Compiling Paths_yesod_core ( dist\dist-sandbox-ea28e1ab\build\autogen\Paths_yesod_core.hs, dist\dist-sandbox-ea28e1ab\build\Paths_yesod_core.o )
[12 of 30] Compiling Yesod.Core.Internal.Util ( Yesod\Core\Internal\Util.hs, dist\dist-sandbox-ea28e1ab\build\Yesod\Core\Internal\Util.o )
[13 of 30] Compiling Yesod.Core.Types ( Yesod\Core\Types.hs, dist\dist-sandbox-ea28e1ab\build\Yesod\Core\Types.o )
[14 of 30] Compiling Yesod.Core.Class.Handler ( Yesod\Core\Class\Handler.hs, dist\dist-sandbox-ea28e1ab\build\Yesod\Core\Class\Handler.o )
[15 of 30] Compiling Yesod.Core.Internal.Request ( Yesod\Core\Internal\Request.hs, dist\dist-sandbox-ea28e1ab\build\Yesod\Core\Internal\Request.o )
[16 of 30] Compiling Yesod.Core.Internal.Session ( Yesod\Core\Internal\Session.hs, dist\dist-sandbox-ea28e1ab\build\Yesod\Core\Internal\Session.o )
[17 of 30] Compiling Yesod.Core.Content ( Yesod\Core\Content.hs, dist\dist-sandbox-ea28e1ab\build\Yesod\Core\Content.o )
[18 of 30] Compiling Yesod.Core.Handler ( Yesod\Core\Handler.hs, dist\dist-sandbox-ea28e1ab\build\Yesod\Core\Handler.o )
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Loading package array-0.5.0.0 ... linking ... done.
Loading package primitive-0.5.2.1 ... linking ... done.
Loading package atomic-primops-0.6.0.6 ... linking ... ghc.exe: unable to load package `atomic-primops-0.6.0.6'
ghc.exe: X:\Projects\yesod\yesod-core\.cabal-sandbox\x86_64-windows-ghc-7.8.3\atomic-primops-0.6.0.6\HSatomic-primops-0.6.0.6.o: unknown symbol `store_load_barrier'
cabal.exe: Error: some packages failed to install:
yesod-core-1.4.1.1 failed during the building phase. The exception was:
ExitFailure 1

Version: atomic-primops-0.6.0.6, yesod-core 1.4.1.1

$ ghc --version
The Glorious Glasgow Haskell Compilation System, version 7.8.3

$ cabal --version
cabal-install version 1.20.0.3
using version 1.20.0.2 of the Cabal library

Operating system: Windows 8.1

Tests fail on GHC 7.4.2

Relevant log excerpts:

Final sum: 4999950000, producer/consumer/leftover sums: ([(98076,4949033504)],[(1924,50916496)],[(0,0)])
test-abstract-deque: internal error: setNumCapabilities: reducing the number of Capabilities is not currently supported.
    (GHC version 7.4.2 for x86_64_unknown_linux)
    Please report this as a GHC bug:  http://www.haskell.org/ghc/reportabug

This is affecting my 7.4.2 Stackage run. If this is not something you intend on resolving, I'll add abstract-deque to the expected failures list, please let me know what you'd prefer.

Feature request: get length of a ChaseLev deque

For implementing work stealing on networks of machines, a common technique is to use minimum watermarks. That is, on receiving a message from another PE to ask for work, the scheduler may want to know if it has a minimum number of sparks before they give some away.

The current ChaseLev implementation does not allow a scheduler to inspect the number of elements (sparks in this case). It might look like:

lengthQ :: ChaseLevDeque a -> IO Int

What are the costs of adding this function? Would it be lock-free?

The cited paper does report a size() method for the CircularArray class.

[atomic-primops] Bugs and build problems on 7.10 RC1

We need base 4.8 If we manually ignore the base constraint, we get:

jberryman /tmp/atomic-primops-0.6.1 » cabal install --only-dependencies -w /usr/local/bin/ghc-7.10.0.20141222 --allow-newer                                                                                                              1 ↵
Resolving dependencies...
Notice: installing into a sandbox located at
/tmp/atomic-primops-0.6.1/.cabal-sandbox
Configuring primitive-0.5.4.0...
Failed to install primitive-0.5.4.0
Build log ( /tmp/atomic-primops-0.6.1/.cabal-sandbox/logs/primitive-0.5.4.0.log ):
unrecognized 'configure' option `--disable-executable-profiling'
cabal: Error: some packages failed to install:
primitive-0.5.4.0 failed during the configure step. The exception was:
ExitFailure 1

I have no idea where the hell that --disable-executable-profiling is coming from or why it's unrecognized.

Triggered GHC gc bug during chaselev test?

The log from this run can be found here.

The error was:

Final sum: 4999950000, producer/consumer/leftover sums: ([(43142,3221214597)],[(56427,1739950903)],[(431,38784500)])
test-chaselev-deque: internal error: wakeup_gc_threads
    (GHC version 7.6.3 for x86_64_unknown_linux)
    Please report this as a GHC bug:  http://www.haskell.org/ghc/reportabug
Test suite test-chaselev-deque: FAIL

[lockfree-queue] Pad byte array with two cachelines to avoid false sharing in AtomicCounter

I played with a branch jberryman/haskell-lockfree@23497b4 that implements the atomic counter with a padding of 64bytes on either side, so that it always sits in its own cache line (at least hopefully on x86, where AtomicCounter is most useful anyway).

In criterion benchmarks of a counter-based queue I'm working on I get a 17 - 23% improvement in runtime on those benchmarks where we start to use the heap (maxing out at 1,000,000 Ints and 1,000 arrays of size 1,000... whatever that amounts to).

I modified the test slightly to run with perf, and some of the cache metrics do appear to be better (but others a bit worse, maybe that's just expected variance).

Here's the slow version with current counter:

 Performance counter stats for './multi_cache_slow' (100 runs):

        401.063542      task-clock (msec)         #    3.745 CPUs utilized            ( +-  0.64% )
               300      context-switches          #    0.747 K/sec                    ( +- 27.94% )
                20      cpu-migrations            #    0.049 K/sec                    ( +-  1.70% )
             2,999      page-faults               #    0.007 M/sec                    ( +-  0.01% )
       726,617,399      cycles                    #    1.812 GHz                      ( +-  1.11% ) [24.21%]
       623,872,915      stalled-cycles-frontend   #   85.86% frontend cycles idle     ( +-  0.94% ) [28.13%]
       427,867,935      instructions              #    0.59  insns per cycle        
                                                  #    1.46  stalled cycles per insn  ( +-  1.83% ) [37.28%]
           268,108      cache-misses              #    5.209 % of all cache refs      ( +-  0.99% ) [40.43%]
         5,146,579      cache-references          #   12.832 M/sec                    ( +-  1.08% ) [43.64%]
         5,616,736      L1-dcache-load-misses     #   14.005 M/sec                    ( +-  1.07% ) [43.16%]
           497,307      L1-dcache-store-misses    #    1.240 M/sec                    ( +-  1.03% ) [40.69%]
         1,470,803      L1-dcache-prefetch-misses #    3.667 M/sec                    ( +-  2.46% ) [29.46%]
           102,164      L1-icache-load-misses     #    0.255 M/sec                    ( +-  1.71% ) [27.00%]
         1,939,392      LLC-loads                 #    4.836 M/sec                    ( +-  1.74% ) [24.80%]
         2,696,163      LLC-stores                #    6.723 M/sec                    ( +-  1.81% ) [23.33%]
         6,026,990      LLC-prefetches            #   15.028 M/sec                    ( +-  2.52% ) [10.68%]
            12,353      iTLB-loads                #    0.031 M/sec                    ( +- 10.40% ) [25.89%]
             9,746      iTLB-load-misses          #   78.89% of all iTLB cache hits   ( +-  2.94% ) [25.01%]
        88,551,617      branch-loads              #  220.792 M/sec                    ( +-  2.43% ) [23.60%]
            89,617      branch-load-misses        #    0.223 M/sec                    ( +-  6.05% ) [22.22%]

       0.107099418 seconds time elapsed                                          ( +-  0.72% )

And fast version:

 Performance counter stats for './multi_cache_fast' (100 runs):

        333.044322      task-clock (msec)         #    3.701 CPUs utilized            ( +-  0.81% )
               221      context-switches          #    0.663 K/sec                    ( +- 16.25% )
                20      cpu-migrations            #    0.059 K/sec                    ( +-  1.70% )
             2,999      page-faults               #    0.009 M/sec                    ( +-  0.02% )
       748,219,452      cycles                    #    2.247 GHz                      ( +-  0.96% ) [23.82%]
       634,355,295      stalled-cycles-frontend   #   84.78% frontend cycles idle     ( +-  1.08% ) [27.57%]
       471,072,726      instructions              #    0.63  insns per cycle        
                                                  #    1.35  stalled cycles per insn  ( +-  1.15% ) [35.37%]
           301,361      cache-misses              #    6.418 % of all cache refs      ( +-  1.59% ) [37.17%]
*        4,695,679      cache-references          #   14.099 M/sec                    ( +-  1.19% ) [38.81%]
*        4,828,687      L1-dcache-load-misses     #   14.499 M/sec                    ( +-  1.38% ) [37.72%]
           654,043      L1-dcache-store-misses    #    1.964 M/sec                    ( +-  1.89% ) [35.95%]
*          592,677      L1-dcache-prefetch-misses #    1.780 M/sec                    ( +-  2.59% ) [29.03%]
*           66,387      L1-icache-load-misses     #    0.199 M/sec                    ( +-  3.89% ) [34.49%]
*          573,885      LLC-loads                 #    1.723 M/sec                    ( +-  4.69% ) [34.30%]
*        1,865,970      LLC-stores                #    5.603 M/sec                    ( +-  2.98% ) [32.93%]
         4,460,103      LLC-prefetches            #   13.392 M/sec                    ( +-  1.99% ) [15.90%]
            16,509      iTLB-loads                #    0.050 M/sec                    ( +-  9.41% ) [27.67%]
*            7,565      iTLB-load-misses          #   45.82% of all iTLB cache hits   ( +-  1.98% ) [25.46%]
        97,310,210      branch-loads              #  292.184 M/sec                    ( +-  2.42% ) [23.51%]
*           74,815      branch-load-misses        #    0.225 M/sec                    ( +-  7.71% ) [21.80%]

       0.089992717 seconds time elapsed                                          ( +-  0.91% )

I also have a version that uses a pinned, aligned MutableByteArray and has the same benefits at just 64 bytes, but I think that would be a mistake and could contribute to memory fragmentation.

If my benchmarks aren't deceiving me I think this change would probably be worth the wasted 127 bytes for most uses of the AtomicCounter that I can think of. Any interest in this sort of change? If not, it's no trouble for me to create my own fat counter.

Reference/Unboxed CAS does not return new ticket on success, up through 0.5

This was another API discrepancy between the different versions of the counter.

It's not totally clear which behavior we should standardize on here. The real implementation that you actually want to use is Unboxed. The others are there mostly for testing and benchmarking. For Unboxed, there's really no reason to have a CTicket type in the first place.

It would be unfortunate, therefore, to lose performance in the Unboxed casCounter, just to accommodate the implementation constraints of the other versions.

Precedent doesn't help very much because the precedent from the boxed CAS operations (IORef, Array) is to use the return-new-as-ticket interface, whereas for the unboxed ByteArray CAS, it's the usual "return-read-value" interface.

Are memory barriers compiler reordering barriers?

Do storeLoadBarrier and friends have the same compiler reordering guarantees described for the atomic operations in issue 39 (#39)? From what I've read it seems like "foreign import prim" prevents compiler reordering during C-- optimizations, but I have no idea whether "foreign import ccall" also does. Thanks!

unknown symbol `cas' when linking against atomic-primops

I'm experiencing a linking error, with ghc failing to find the cas symbol.

Prelude> :m Data.Atomics
Prelude Data.Atomics> writeBarrier
Loading package array-0.4.0.1 ... linking ... done.
Loading package deepseq-1.3.0.1 ... linking ... done.
Loading package containers-0.5.0.0 ... linking ... done.
Loading package filepath-1.3.0.1 ... linking ... done.
Loading package old-locale-1.0.0.5 ... linking ... done.
Loading package time-1.4.0.1 ... linking ... done.
Loading package bytestring-0.10.0.2 ... linking ... done.
Loading package unix-2.6.0.1 ... linking ... done.
Loading package directory-1.2.0.1 ... linking ... done.
Loading package old-time-1.1.0.1 ... linking ... done.
Loading package pretty-1.1.1.0 ... linking ... done.
Loading package process-1.1.0.2 ... linking ... done.
Loading package Cabal-1.16.0 ... linking ... done.
Loading package bits-atomic-0.1.3 ... linking ... done.
Loading package primitive-0.5.0.1 ... linking ... done.
Loading package atomic-primops-0.2.2 ... linking ... <interactive>: $HOME/.cabal/lib/atomic-primops-0.2.2/ghc-7.6.3/HSatomic-primops-0.2.2.o: unknown symbol `cas'

Having read this , I see that the cas symbol is defined on my Linux machine in $HOME/sw/ghc/ghc-7.6.3-BUILD/lib/ghc-7.6.3/include/stg/SMP.h . I've tried (to no avail) the --extra-include-dirs flag when compiling programs that uses Data.Atomic, which throws the same error. This is a ghc that I use on a regular basis for other business. How should I resolve this unknown symbol error?

PeekTicket needs to be INLINE and shouldn't be

Here is a standalone test

It can be reproduced with something like this:

GHC=ghc-7.6.3
cd ChaseLev
cabal-1.17.0_HEAD install --disable-executable-profiling --disable-library-profiling --disable-documentation --force-reinstalls ../AbstractDeque/ --with-ghc=$GHC
cabal-1.17.0_HEAD install --disable-executable-profiling --disable-library-profiling --disable-documentation --force-reinstalls ../AtomicPrimops/ --with-ghc=$GHC
$GHC -O2 --make RegressionTests/Issue5.hs -o Issue5.exe -main-is RegressionTests.Issue5.standalone_single_CAS
./Issue5.exe

The -O2 is required to make it fail (notice that --threaded is not). That's a big hint. (In fact, -O1 fails too.)

Saw a genuine nondeterministic test failure

Most of our failures are jenkins/cabal problems. But the 7.6.3/profiling/-O0/threads build in the matrix here is a genuine test failure:

  test_all_hammer_one_1_500000:: [Failed]
Runs [500000] (GCs 0), had enough successes?: [499999] >= 500000
  111111111111111111111111111111111111111111111111111111111111111111111111111111...

[atomic-primops] Expose and test new atomic primops in GHC 7.10

GHC 7.10 includes several new primops. You can see which by comparing these two interfaces:

Each one of these needs to be exposed in and end-user friendly way in the IO monad, and tested accordingly. @tibbe, do you have any interest in helping expose these?

I figure while we are making breaking changes to handle #41 and #42, that we should make these additions an the same time, and make one new major release to be timed with the official GHC 7.10 release -- it will be the greatest GHC yet for lock-free concurrency!

For at least GHC 7.6, replace CMM code with straight C code

Johan (@tibbe) pointed out something I didn't know, "MutableByteArray#" can be sent through the FFI. Thus it should be possible to move the logic we have in Cmm code into C code, and avoid a DOUBLE function call overhead.

Because the GHC 7.8 primops have this double funcall overhead, they may end up as useless from the perspective of this package. The hope was to at last avoid the fragility of foreign primops by including them in GHC. Still, that problem is eliminated just as well by eliminating the Cmm itself.

casIORef failing (i.e. returning False) for no apparent reason in GHCi 7.8 (rc2)

jberryman /tmp » cabal install atomic-primops
Resolving dependencies...
Configuring primitive-0.5.2.1...
Building primitive-0.5.2.1...
Installed primitive-0.5.2.1
Configuring atomic-primops-0.6...
Building atomic-primops-0.6...
Installed atomic-primops-0.6
jberryman /tmp » ghci
GHCi, version 7.8.20140130: http://www.haskell.org/ghc/  :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Prelude> import Data.Atomics
Prelude Data.Atomics> import Data.IORef 
Prelude Data.Atomics Data.IORef> r <- newIORef 'a'
Prelude Data.Atomics Data.IORef> t <- readForCAS r
Loading package array-0.5.0.0 ... linking ... done.
Loading package deepseq-1.3.0.2 ... linking ... done.
Loading package bytestring-0.10.4.0 ... linking ... done.
Loading package containers-0.5.4.0 ... linking ... done.
Loading package filepath-1.3.0.2 ... linking ... done.
Loading package old-locale-1.0.0.6 ... linking ... done.
Loading package time-1.4.1 ... linking ... done.
Loading package unix-2.7.0.0 ... linking ... done.
Loading package directory-1.2.0.2 ... linking ... done.
Loading package pretty-1.1.1.1 ... linking ... done.
Loading package process-1.2.0.0 ... linking ... done.
Loading package Cabal-1.18.1.3 ... linking ... done.
Loading package primitive-0.5.2.1 ... linking ... done.
Loading package atomic-primops-0.6 ... linking ... done.
Prelude Data.Atomics Data.IORef> (b,t') <- casIORef r t 'b'
Prelude Data.Atomics Data.IORef> b
False
Prelude Data.Atomics Data.IORef> peekTicket t'
'a'

I tried the same in 7.6.3 but get a linker error (I think that's documented). And when I load code (using cabal repl in my project) that uses casIORefinternally I'm seeing this same behavior, but intermittently; very strange.

I haven't yet checked correct behavior in compiled code.

Finally, a question: barring bugs, is it safe in my code to reason that if a casIORef returns False that another thread has beat us with a write? Or can casIORef be expected to fail nondeterministically?

[atomic-primops] Change in `fetchAddIntArray#` in GHC 7.10

Ok, it looks like maybe this is an intentional change in behavior for fetchAddIntArray#, @tibbe?

Following some precedent or existing code (I forgot which!), I'd made the original version return the AFTER value not the BEFORE value. Thus the code for incrCounter was:

{-# INLINE incrCounter #-}
-- | Increment the counter by a given amount.  Returns the value AFTER the increment
--   (in contrast with the behavior of the underlying instruction on architectures
--   like x86.)
--
--   Note that UNLIKE with boxed implementations of counters, where increment is
--   based on CAS, this increment is /O(1)/.  Fetch-and-add does not require a retry
--   loop like CAS.
incrCounter :: Int -> AtomicCounter -> IO Int
incrCounter (I# incr#) (AtomicCounter mba#) = IO $ \ s1# ->
  let (# s2#, res #) = fetchAddIntArray# mba# 0# incr# s1# in
  (# s2#, (I# res) #)

It looks like the 7.10+ version of fetchAddIntArray# returns the BEFORE value. GCC provides both, fetch_and_add and add_and_fetch. It's true that the primop we export matches the name of the former more closely, and it thus is fine for it to have that behavior.

Uh... it looks like we need another ifdef, eh, to support this change? Oh well, that's the goal of the atomic-primops package. To abstract over these varying levels of support in different GHC versions.

But I do think we should go ahead and bump the major version and change the interface for this Counter lib to return the BEFORE value (and support that behavior across the last 3 GHC versions), what do you think?

ChaseLev test_random_work_stealing can get a bad checksum

Either too low or too high. This has been the main bug that I've been investigating in the DEVLOG.

I was hopeful that it would have the same underlying cause as Issue #5, but it is closed and this bug remains. As mentioned in the DEVLOG, running this enough times will trigger it:

NUMELEMS=1000000 NOWRAPPER=1 NUMTHREADS=4 ./dist/build/test-chaselev-deque/test-chaselev-deque -t random_work_steal

An example revision where this fails is: 8050a58

[atomic-primops] Please clarify whether atomic operations are barriers or not

It would be nice to know whether or not casIORef, fetchAddByteArray, etc. represent memory barriers, or not, at the compiler level. In other words, may GHC reorder stores or loads across these operations, regardless of whether the underlying primop is a barrier on a particular architecture? Or like atomicModifyIORef do they guarantee some ordering?

There's mention of how the read operations don't imply any barriers, which suggests that maybe the atomic ops do. If this isn't defined in GHC then it would be nice to clarify that there, obviously. Thanks!

Libraries that use Template Haskell cannot use atomic-primops (cas symbol problem)

Libraries or programs that use Template Haskell will not be able to use the atomic-primops library. The root cause is a combination of two things. First, need to use -threaded for code that ultimately uses atomic-primops, as described in this issue. Second, Template Haskell runs at compile time, via a bytecode interpreter, GHCi. This does not invoke -threaded, so the error is thrown, once GHCI attempts to load packages:

Loading package atomic-primops-0.2.2.1 ... linking ... ghc: ~/.cabal/lib/atomic-primops-0.2.2.1/ghc-7.6.1/HSatomic-primops-0.2.2.1.o: unknown symbol `cas'

As a simply example, try compiling this demo library I put together: chaselev-user-libX-0.0.1.tar.gz. The case is straight forward: if you comment out remotable on line 17 of Foo.Bar, the library compiles. If you leave it in, the library does not compile.

Remove abstract-deque library dependency on test-framework

Does the library (not the included test suite) need to depend on test-framework? Right now test-framework doesn't build so neither does abstract-deque-0.2.2 and a few dependencies later criterion (which I need right now) doesn't build.

Aside: could you add a

bug-reports: https://github.com/rrnewton/haskell-lockfree/issues

section to the .cabal file so it's easier to find this page.

RtsDup.c was calling the wrong implementation of CAS due to a CPP problem. Downstream libs were therefore using non-atomic CAS.

They use the strategy of comparing against the "old" value to see if the CAS succeeded. Alas, this doesn't work. You have to actually read the zero flag with sete, which is what __sync_bool_compare_and_swap does.

For example if 100 threads attempt to change a counter from 0 to 1, only one can succeed, but with the current version more than one may think they succeeded.

This is ultimately the cause of Issue 70 in the lvars repo:
iu-parfunc/lvars#70

This is going to require significant changes to fix.

Travis CI, this project needs it

HVR and Brent Yorgey have some neat tooling to auto run test suites on several GHC versions, I think this should be adapted to this set of libs (though the fact that they're all in the same repo complicates the scripting I think...)

Various cabal issues.

First, there was the issue that lead to separating test-atomic-primops

(TODO)

More recently, there are various different problems w cabal 1.20 and 1.22

For example, this with --run-tests on a profiling build in either cabal 1.20 or 1.22:

Loading package atomic-primops-0.8 ... linking ... done.
ghci-test.hs:18:16:
    cannot find normal object file ‘dist/dist-sandbox-a2a4e32d/build/template-haskell-atomic-primops/template-haskell-atomic-primops-tmp/TemplateHaskellSplices.dyn_o’

Vs this with a discrete cabal-1.20 test:

++ cabal-1.20 test --show-details=always
cabal-1.20: dist/setup-config: invalid argument

On 1.22.3.0, I'm seeing it complain about lack of configure when it just ran configure. And somehow it thinks the version of GHC has changed, when it should pick it up from the configure.

++ cabal-1.22 configure --with-ghc=ghc-7.6.3 --enable-tests -O0 --disable-library-profiling --disable-profiling --disable-coverage -fthreaded --ghc-options=-threaded
Resolving dependencies...
[1 of 1] Compiling Main             ( dist/setup/setup.hs, dist/setup/Main.o )
Linking ./dist/setup/setup ...
Configuring atomic-primops-0.8...
++ cabal-1.22 test --show-details=streaming
cabal-1.22: You need to re-run the 'configure' command. The version of Cabal being used has changed (was Cabal-1.20.0.2, now Cabal-1.22.3.0). Additionally the compiler is different (was ghc-7.6, now ghc-7.8) which is probably the cause of the problem.

But specifying the GHC version to cabal test doesn't help either:

Configuring atomic-primops-0.8...
++ cabal-1.22 test --with-ghc=ghc-7.6.3 --show-details=streaming
cabal-1.22: You need to re-run the 'configure' command. The version of Cabal being used has changed (was Cabal-1.20.0.2, now Cabal-1.22.3.0). Additionally the compiler is different (was ghc-7.6, now ghc-7.8) which is probably the cause of the problem.

But even if I remove all uses of --with-ghc, I still get the exact same error message above.

After tweaking it a few times I get the same missing ".dyn_o" failure on ghci-test.hs above when using a discrete cabal configure / cabal test per package. It's possible that now in cabal 1.20+, recombining test-atomic-primops into the atomic-primops library could work around this bug....

Implement multi-item CAS (CASN)

Multi-item CAS or CASN is the basis for some interesting concurrent data structures. It would be nice if atomic-primops provides a CASN (or perhaps CAS2, CAS3 ... CAS10?).

I took a look A Practical Multi-Word Compare-And-Swap, but I was unable to implement it. Perhaps someone else can ... or maybe there is more modern method?

install_all.sh failure with ghc 7.6.3 and cabal-dev

On a mostly fresh ghc-7.6.3 Ubuntu 13.04 machine running the install_all script as CABAL=cabal-dev ./install_all.sh fails with:

cabal: Error: some packages failed to install:
test-atomic-primops-0.1.0.0 failed during the building phase. The exception
was:
ExitFailure 1

The specific error for test-atomic-primops was:

Configuring test-atomic-primops-0.1.0.0...
Building test-atomic-primops-0.1.0.0...
Preprocessing executable 'hello-world-atomic-primops' for
test-atomic-primops-0.1.0.0...
cabal: can't find source for hello in .
Failed to install test-atomic-primops-0.1.0.0

Non-deterministic failures in ChaseLev

Currently, cf85070, the ChaseLev implementation doesn't work reliably.

No leads at the moment on where the bug might be.

The implementation is a straightforward transcription of the psuedocode in the original paper:

http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.170.1097&rep=rep1&type=pdf

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.