diff --git a/Data/Bits/Atomic.hs b/Data/Bits/Atomic.hs
new file mode 100644
--- /dev/null
+++ b/Data/Bits/Atomic.hs
@@ -0,0 +1,730 @@
+{-# LANGUAGE ForeignFunctionInterface #-}
+-- | Atomic bit operations, using GCC's built-in atomic operations in small C
+-- wrapper functions called through the FFI. See
+-- <http://gcc.gnu.org/onlinedocs/gcc-4.5.0/gcc/Atomic-Builtins.html> or the
+-- version corresponding to your compiler for more detail.
+module Data.Bits.Atomic (
+    -- * Atomic bit operations on 'Word'-sized memory locations
+    AtomicBits(..),
+    -- * Utility
+    memoryBarrier
+) where
+import Data.Bits
+import Data.Word
+import Data.Int
+import Foreign.Ptr
+
+-- | Atomic bit operations on a memory location. 
+--
+-- Instances: 'Word', 'Word8', 'Word16', 'Word32', 'Word64', 'Int', 'Int8',
+-- 'Int16', 'Int32', 'Int64'.
+class Bits x => AtomicBits x where
+    -- | Atomic @(+)@, returning the original value.
+    fetchAndAdd :: Ptr x -> x -> IO x
+    -- | Atomic @(-)@, returning the originial value.
+    fetchAndSub :: Ptr x -> x -> IO x
+    -- | Atomic @(.|.)@, returning the original value.
+    fetchAndOr :: Ptr x -> x -> IO x
+    -- | Atomic @(.&.)@, returning the original value.
+    fetchAndAnd :: Ptr x -> x -> IO x
+    -- | Atomic @xor@, returning the original value.
+    fetchAndXor :: Ptr x -> x -> IO x
+    -- | Atomic @nand@, returning the original value.
+    fetchAndNand :: Ptr x -> x -> IO x
+    -- | Atomic @(+)@, returning the updated value.
+    addAndFetch :: Ptr x -> x -> IO x
+    -- | Atomic @(-)@, returning the updated value.
+    subAndFetch :: Ptr x -> x -> IO x
+    -- | Atomic @(.|.)@, returning the updated value.
+    orAndFetch :: Ptr x -> x -> IO x
+    -- | Atomic @(.&.)@, returning the updated value.
+    andAndFetch :: Ptr x -> x -> IO x
+    -- | Atomic @xor@, returning the updated value.
+    xorAndFetch :: Ptr x -> x -> IO x
+    -- | Atomic @nand@, returning the updated value.
+    nandAndFetch :: Ptr x -> x -> IO x
+    -- | Atomic @CAS@ with boolean return.
+    compareAndSwapBool :: Ptr x  -- ^ The memory location to update
+                       -> x  -- ^ Old value
+                       -> x  -- ^ Intended new value
+                       -> IO Bool -- ^ 'True' if swapped, 'False' otherwise
+
+    -- | Atomic @CAS@, returning the original value.
+    compareAndSwap :: Ptr x  -- ^ The memory location to update
+                   -> x  -- ^ Old value
+                   -> x  -- ^ Intended new value
+                   -> IO x -- ^ Original value
+
+    -- | Atomically update the memory location with the value 1 and return the
+    -- original value, 0 in case 'lockRelease' was previously called or @1@ if
+    -- another call to 'lockTestAndSet' aquired the lock earlier. Implies an
+    -- /aquire barrier/.
+    lockTestAndSet :: Ptr x -> IO x
+    -- | Release the lock by writing a @0@. Includes a /release barrier/.
+    lockRelease :: Ptr x -> IO ()
+
+
+-- | A full memory barrier.
+foreign import ccall unsafe "atomic-bitops-gcc.h mem_barrier"
+    memoryBarrier :: IO ()
+
+foreign import ccall unsafe "atomic-bitops-gcc.h fetch_and_add_8"
+    fetch_and_add_8 :: Ptr Word8 -> Word8 -> IO Word8
+foreign import ccall unsafe "atomic-bitops-gcc.h fetch_and_sub_8"
+    fetch_and_sub_8 :: Ptr Word8 -> Word8 -> IO Word8
+foreign import ccall unsafe "atomic-bitops-gcc.h fetch_and_or_8"
+    fetch_and_or_8 :: Ptr Word8 -> Word8 -> IO Word8
+foreign import ccall unsafe "atomic-bitops-gcc.h fetch_and_and_8"
+    fetch_and_and_8 :: Ptr Word8 -> Word8 -> IO Word8
+foreign import ccall unsafe "atomic-bitops-gcc.h fetch_and_xor_8"
+    fetch_and_xor_8 :: Ptr Word8 -> Word8 -> IO Word8
+foreign import ccall unsafe "atomic-bitops-gcc.h fetch_and_nand_8"
+    fetch_and_nand_8 :: Ptr Word8 -> Word8 -> IO Word8
+foreign import ccall unsafe "atomic-bitops-gcc.h add_and_fetch_8"
+    add_and_fetch_8 :: Ptr Word8 -> Word8 -> IO Word8
+foreign import ccall unsafe "atomic-bitops-gcc.h sub_and_fetch_8"
+    sub_and_fetch_8 :: Ptr Word8 -> Word8 -> IO Word8
+foreign import ccall unsafe "atomic-bitops-gcc.h or_and_fetch_8"
+    or_and_fetch_8 :: Ptr Word8 -> Word8 -> IO Word8
+foreign import ccall unsafe "atomic-bitops-gcc.h and_and_fetch_8"
+    and_and_fetch_8 :: Ptr Word8 -> Word8 -> IO Word8
+foreign import ccall unsafe "atomic-bitops-gcc.h xor_and_fetch_8"
+    xor_and_fetch_8 :: Ptr Word8 -> Word8 -> IO Word8
+foreign import ccall unsafe "atomic-bitops-gcc.h nand_and_fetch_8"
+    nand_and_fetch_8 :: Ptr Word8 -> Word8 -> IO Word8
+foreign import ccall unsafe "atomic-bitops-gcc.h bool_compare_and_swap_8"
+    bool_compare_and_swap_8 :: Ptr Word8 -> Word8 -> Word8 -> IO Bool
+foreign import ccall unsafe "atomic-bitops-gcc.h val_compare_and_swap_8"
+    val_compare_and_swap_8 :: Ptr Word8 -> Word8 -> Word8 -> IO Word8
+foreign import ccall unsafe "atomic-bitops-gcc.h lock_test_and_set_8"
+    lock_test_and_set_8 :: Ptr Word8 -> IO Word8
+foreign import ccall unsafe "atomic-bitops-gcc.h lock_release_8"
+    lock_release_8 :: Ptr Word8 -> IO ()
+
+instance AtomicBits Word8 where
+    fetchAndAdd = fetch_and_add_8
+    {-# INLINE fetchAndAdd #-}
+    fetchAndSub = fetch_and_sub_8
+    {-# INLINE fetchAndSub #-}
+    fetchAndOr = fetch_and_or_8
+    {-# INLINE fetchAndOr #-}
+    fetchAndAnd = fetch_and_and_8
+    {-# INLINE fetchAndAnd #-}
+    fetchAndXor = fetch_and_xor_8
+    {-# INLINE fetchAndXor #-}
+    fetchAndNand = fetch_and_nand_8
+    {-# INLINE fetchAndNand #-}
+    addAndFetch = add_and_fetch_8
+    {-# INLINE addAndFetch #-}
+    subAndFetch = sub_and_fetch_8
+    {-# INLINE subAndFetch #-}
+    orAndFetch = or_and_fetch_8
+    {-# INLINE orAndFetch #-}
+    andAndFetch = and_and_fetch_8
+    {-# INLINE andAndFetch #-}
+    xorAndFetch = xor_and_fetch_8
+    {-# INLINE xorAndFetch #-}
+    nandAndFetch = nand_and_fetch_8
+    {-# INLINE nandAndFetch #-}
+    compareAndSwapBool = bool_compare_and_swap_8
+    {-# INLINE compareAndSwapBool #-}
+    compareAndSwap = val_compare_and_swap_8
+    {-# INLINE compareAndSwap #-}
+    lockTestAndSet = lock_test_and_set_8
+    {-# INLINE lockTestAndSet #-}
+    lockRelease = lock_release_8
+    {-# INLINE lockRelease #-}
+    
+foreign import ccall unsafe "atomic-bitops-gcc.h fetch_and_add_16"
+    fetch_and_add_16 :: Ptr Word16 -> Word16 -> IO Word16
+foreign import ccall unsafe "atomic-bitops-gcc.h fetch_and_sub_16"
+    fetch_and_sub_16 :: Ptr Word16 -> Word16 -> IO Word16
+foreign import ccall unsafe "atomic-bitops-gcc.h fetch_and_or_16"
+    fetch_and_or_16 :: Ptr Word16 -> Word16 -> IO Word16
+foreign import ccall unsafe "atomic-bitops-gcc.h fetch_and_and_16"
+    fetch_and_and_16 :: Ptr Word16 -> Word16 -> IO Word16
+foreign import ccall unsafe "atomic-bitops-gcc.h fetch_and_xor_16"
+    fetch_and_xor_16 :: Ptr Word16 -> Word16 -> IO Word16
+foreign import ccall unsafe "atomic-bitops-gcc.h fetch_and_nand_16"
+    fetch_and_nand_16 :: Ptr Word16 -> Word16 -> IO Word16
+foreign import ccall unsafe "atomic-bitops-gcc.h add_and_fetch_16"
+    add_and_fetch_16 :: Ptr Word16 -> Word16 -> IO Word16
+foreign import ccall unsafe "atomic-bitops-gcc.h sub_and_fetch_16"
+    sub_and_fetch_16 :: Ptr Word16 -> Word16 -> IO Word16
+foreign import ccall unsafe "atomic-bitops-gcc.h or_and_fetch_16"
+    or_and_fetch_16 :: Ptr Word16 -> Word16 -> IO Word16
+foreign import ccall unsafe "atomic-bitops-gcc.h and_and_fetch_16"
+    and_and_fetch_16 :: Ptr Word16 -> Word16 -> IO Word16
+foreign import ccall unsafe "atomic-bitops-gcc.h xor_and_fetch_16"
+    xor_and_fetch_16 :: Ptr Word16 -> Word16 -> IO Word16
+foreign import ccall unsafe "atomic-bitops-gcc.h nand_and_fetch_16"
+    nand_and_fetch_16 :: Ptr Word16 -> Word16 -> IO Word16
+foreign import ccall unsafe "atomic-bitops-gcc.h bool_compare_and_swap_16"
+    bool_compare_and_swap_16 :: Ptr Word16 -> Word16 -> Word16 -> IO Bool
+foreign import ccall unsafe "atomic-bitops-gcc.h val_compare_and_swap_16"
+    val_compare_and_swap_16 :: Ptr Word16 -> Word16 -> Word16 -> IO Word16
+foreign import ccall unsafe "atomic-bitops-gcc.h lock_test_and_set_16"
+    lock_test_and_set_16 :: Ptr Word16 -> IO Word16
+foreign import ccall unsafe "atomic-bitops-gcc.h lock_release_16"
+    lock_release_16 :: Ptr Word16 -> IO ()
+
+instance AtomicBits Word16 where
+    fetchAndAdd = fetch_and_add_16
+    {-# INLINE fetchAndAdd #-}
+    fetchAndSub = fetch_and_sub_16
+    {-# INLINE fetchAndSub #-}
+    fetchAndOr = fetch_and_or_16
+    {-# INLINE fetchAndOr #-}
+    fetchAndAnd = fetch_and_and_16
+    {-# INLINE fetchAndAnd #-}
+    fetchAndXor = fetch_and_xor_16
+    {-# INLINE fetchAndXor #-}
+    fetchAndNand = fetch_and_nand_16
+    {-# INLINE fetchAndNand #-}
+    addAndFetch = add_and_fetch_16
+    {-# INLINE addAndFetch #-}
+    subAndFetch = sub_and_fetch_16
+    {-# INLINE subAndFetch #-}
+    orAndFetch = or_and_fetch_16
+    {-# INLINE orAndFetch #-}
+    andAndFetch = and_and_fetch_16
+    {-# INLINE andAndFetch #-}
+    xorAndFetch = xor_and_fetch_16
+    {-# INLINE xorAndFetch #-}
+    nandAndFetch = nand_and_fetch_16
+    {-# INLINE nandAndFetch #-}
+    compareAndSwapBool = bool_compare_and_swap_16
+    {-# INLINE compareAndSwapBool #-}
+    compareAndSwap = val_compare_and_swap_16
+    {-# INLINE compareAndSwap #-}
+    lockTestAndSet = lock_test_and_set_16
+    {-# INLINE lockTestAndSet #-}
+    lockRelease = lock_release_16
+    {-# INLINE lockRelease #-}
+    
+foreign import ccall unsafe "atomic-bitops-gcc.h fetch_and_add_32"
+    fetch_and_add_32 :: Ptr Word32 -> Word32 -> IO Word32
+foreign import ccall unsafe "atomic-bitops-gcc.h fetch_and_sub_32"
+    fetch_and_sub_32 :: Ptr Word32 -> Word32 -> IO Word32
+foreign import ccall unsafe "atomic-bitops-gcc.h fetch_and_or_32"
+    fetch_and_or_32 :: Ptr Word32 -> Word32 -> IO Word32
+foreign import ccall unsafe "atomic-bitops-gcc.h fetch_and_and_32"
+    fetch_and_and_32 :: Ptr Word32 -> Word32 -> IO Word32
+foreign import ccall unsafe "atomic-bitops-gcc.h fetch_and_xor_32"
+    fetch_and_xor_32 :: Ptr Word32 -> Word32 -> IO Word32
+foreign import ccall unsafe "atomic-bitops-gcc.h fetch_and_nand_32"
+    fetch_and_nand_32 :: Ptr Word32 -> Word32 -> IO Word32
+foreign import ccall unsafe "atomic-bitops-gcc.h add_and_fetch_32"
+    add_and_fetch_32 :: Ptr Word32 -> Word32 -> IO Word32
+foreign import ccall unsafe "atomic-bitops-gcc.h sub_and_fetch_32"
+    sub_and_fetch_32 :: Ptr Word32 -> Word32 -> IO Word32
+foreign import ccall unsafe "atomic-bitops-gcc.h or_and_fetch_32"
+    or_and_fetch_32 :: Ptr Word32 -> Word32 -> IO Word32
+foreign import ccall unsafe "atomic-bitops-gcc.h and_and_fetch_32"
+    and_and_fetch_32 :: Ptr Word32 -> Word32 -> IO Word32
+foreign import ccall unsafe "atomic-bitops-gcc.h xor_and_fetch_32"
+    xor_and_fetch_32 :: Ptr Word32 -> Word32 -> IO Word32
+foreign import ccall unsafe "atomic-bitops-gcc.h nand_and_fetch_32"
+    nand_and_fetch_32 :: Ptr Word32 -> Word32 -> IO Word32
+foreign import ccall unsafe "atomic-bitops-gcc.h bool_compare_and_swap_32"
+    bool_compare_and_swap_32 :: Ptr Word32 -> Word32 -> Word32 -> IO Bool
+foreign import ccall unsafe "atomic-bitops-gcc.h val_compare_and_swap_32"
+    val_compare_and_swap_32 :: Ptr Word32 -> Word32 -> Word32 -> IO Word32
+foreign import ccall unsafe "atomic-bitops-gcc.h lock_test_and_set_32"
+    lock_test_and_set_32 :: Ptr Word32 -> IO Word32
+foreign import ccall unsafe "atomic-bitops-gcc.h lock_release_32"
+    lock_release_32 :: Ptr Word32 -> IO ()
+
+instance AtomicBits Word32 where
+    fetchAndAdd = fetch_and_add_32
+    {-# INLINE fetchAndAdd #-}
+    fetchAndSub = fetch_and_sub_32
+    {-# INLINE fetchAndSub #-}
+    fetchAndOr = fetch_and_or_32
+    {-# INLINE fetchAndOr #-}
+    fetchAndAnd = fetch_and_and_32
+    {-# INLINE fetchAndAnd #-}
+    fetchAndXor = fetch_and_xor_32
+    {-# INLINE fetchAndXor #-}
+    fetchAndNand = fetch_and_nand_32
+    {-# INLINE fetchAndNand #-}
+    addAndFetch = add_and_fetch_32
+    {-# INLINE addAndFetch #-}
+    subAndFetch = sub_and_fetch_32
+    {-# INLINE subAndFetch #-}
+    orAndFetch = or_and_fetch_32
+    {-# INLINE orAndFetch #-}
+    andAndFetch = and_and_fetch_32
+    {-# INLINE andAndFetch #-}
+    xorAndFetch = xor_and_fetch_32
+    {-# INLINE xorAndFetch #-}
+    nandAndFetch = nand_and_fetch_32
+    {-# INLINE nandAndFetch #-}
+    compareAndSwapBool = bool_compare_and_swap_32
+    {-# INLINE compareAndSwapBool #-}
+    compareAndSwap = val_compare_and_swap_32
+    {-# INLINE compareAndSwap #-}
+    lockTestAndSet = lock_test_and_set_32
+    {-# INLINE lockTestAndSet #-}
+    lockRelease = lock_release_32
+    {-# INLINE lockRelease #-}
+    
+foreign import ccall unsafe "atomic-bitops-gcc.h fetch_and_add_64"
+    fetch_and_add_64 :: Ptr Word64 -> Word64 -> IO Word64
+foreign import ccall unsafe "atomic-bitops-gcc.h fetch_and_sub_64"
+    fetch_and_sub_64 :: Ptr Word64 -> Word64 -> IO Word64
+foreign import ccall unsafe "atomic-bitops-gcc.h fetch_and_or_64"
+    fetch_and_or_64 :: Ptr Word64 -> Word64 -> IO Word64
+foreign import ccall unsafe "atomic-bitops-gcc.h fetch_and_and_64"
+    fetch_and_and_64 :: Ptr Word64 -> Word64 -> IO Word64
+foreign import ccall unsafe "atomic-bitops-gcc.h fetch_and_xor_64"
+    fetch_and_xor_64 :: Ptr Word64 -> Word64 -> IO Word64
+foreign import ccall unsafe "atomic-bitops-gcc.h fetch_and_nand_64"
+    fetch_and_nand_64 :: Ptr Word64 -> Word64 -> IO Word64
+foreign import ccall unsafe "atomic-bitops-gcc.h add_and_fetch_64"
+    add_and_fetch_64 :: Ptr Word64 -> Word64 -> IO Word64
+foreign import ccall unsafe "atomic-bitops-gcc.h sub_and_fetch_64"
+    sub_and_fetch_64 :: Ptr Word64 -> Word64 -> IO Word64
+foreign import ccall unsafe "atomic-bitops-gcc.h or_and_fetch_64"
+    or_and_fetch_64 :: Ptr Word64 -> Word64 -> IO Word64
+foreign import ccall unsafe "atomic-bitops-gcc.h and_and_fetch_64"
+    and_and_fetch_64 :: Ptr Word64 -> Word64 -> IO Word64
+foreign import ccall unsafe "atomic-bitops-gcc.h xor_and_fetch_64"
+    xor_and_fetch_64 :: Ptr Word64 -> Word64 -> IO Word64
+foreign import ccall unsafe "atomic-bitops-gcc.h nand_and_fetch_64"
+    nand_and_fetch_64 :: Ptr Word64 -> Word64 -> IO Word64
+foreign import ccall unsafe "atomic-bitops-gcc.h bool_compare_and_swap_64"
+    bool_compare_and_swap_64 :: Ptr Word64 -> Word64 -> Word64 -> IO Bool
+foreign import ccall unsafe "atomic-bitops-gcc.h val_compare_and_swap_64"
+    val_compare_and_swap_64 :: Ptr Word64 -> Word64 -> Word64 -> IO Word64
+foreign import ccall unsafe "atomic-bitops-gcc.h lock_test_and_set_64"
+    lock_test_and_set_64 :: Ptr Word64 -> IO Word64
+foreign import ccall unsafe "atomic-bitops-gcc.h lock_release_64"
+    lock_release_64 :: Ptr Word64 -> IO ()
+
+instance AtomicBits Word64 where
+    fetchAndAdd = fetch_and_add_64
+    {-# INLINE fetchAndAdd #-}
+    fetchAndSub = fetch_and_sub_64
+    {-# INLINE fetchAndSub #-}
+    fetchAndOr = fetch_and_or_64
+    {-# INLINE fetchAndOr #-}
+    fetchAndAnd = fetch_and_and_64
+    {-# INLINE fetchAndAnd #-}
+    fetchAndXor = fetch_and_xor_64
+    {-# INLINE fetchAndXor #-}
+    fetchAndNand = fetch_and_nand_64
+    {-# INLINE fetchAndNand #-}
+    addAndFetch = add_and_fetch_64
+    {-# INLINE addAndFetch #-}
+    subAndFetch = sub_and_fetch_64
+    {-# INLINE subAndFetch #-}
+    orAndFetch = or_and_fetch_64
+    {-# INLINE orAndFetch #-}
+    andAndFetch = and_and_fetch_64
+    {-# INLINE andAndFetch #-}
+    xorAndFetch = xor_and_fetch_64
+    {-# INLINE xorAndFetch #-}
+    nandAndFetch = nand_and_fetch_64
+    {-# INLINE nandAndFetch #-}
+    compareAndSwapBool = bool_compare_and_swap_64
+    {-# INLINE compareAndSwapBool #-}
+    compareAndSwap = val_compare_and_swap_64
+    {-# INLINE compareAndSwap #-}
+    lockTestAndSet = lock_test_and_set_64
+    {-# INLINE lockTestAndSet #-}
+    lockRelease = lock_release_64
+    {-# INLINE lockRelease #-}
+    
+foreign import ccall unsafe "atomic-bitops-gcc.h fetch_and_add_word"
+    fetch_and_add_word :: Ptr Word -> Word -> IO Word
+foreign import ccall unsafe "atomic-bitops-gcc.h fetch_and_sub_word"
+    fetch_and_sub_word :: Ptr Word -> Word -> IO Word
+foreign import ccall unsafe "atomic-bitops-gcc.h fetch_and_or_word"
+    fetch_and_or_word :: Ptr Word -> Word -> IO Word
+foreign import ccall unsafe "atomic-bitops-gcc.h fetch_and_and_word"
+    fetch_and_and_word :: Ptr Word -> Word -> IO Word
+foreign import ccall unsafe "atomic-bitops-gcc.h fetch_and_xor_word"
+    fetch_and_xor_word :: Ptr Word -> Word -> IO Word
+foreign import ccall unsafe "atomic-bitops-gcc.h fetch_and_nand_word"
+    fetch_and_nand_word :: Ptr Word -> Word -> IO Word
+foreign import ccall unsafe "atomic-bitops-gcc.h add_and_fetch_word"
+    add_and_fetch_word :: Ptr Word -> Word -> IO Word
+foreign import ccall unsafe "atomic-bitops-gcc.h sub_and_fetch_word"
+    sub_and_fetch_word :: Ptr Word -> Word -> IO Word
+foreign import ccall unsafe "atomic-bitops-gcc.h or_and_fetch_word"
+    or_and_fetch_word :: Ptr Word -> Word -> IO Word
+foreign import ccall unsafe "atomic-bitops-gcc.h and_and_fetch_word"
+    and_and_fetch_word :: Ptr Word -> Word -> IO Word
+foreign import ccall unsafe "atomic-bitops-gcc.h xor_and_fetch_word"
+    xor_and_fetch_word :: Ptr Word -> Word -> IO Word
+foreign import ccall unsafe "atomic-bitops-gcc.h nand_and_fetch_word"
+    nand_and_fetch_word :: Ptr Word -> Word -> IO Word
+foreign import ccall unsafe "atomic-bitops-gcc.h bool_compare_and_swap_word"
+    bool_compare_and_swap_word :: Ptr Word -> Word -> Word -> IO Bool
+foreign import ccall unsafe "atomic-bitops-gcc.h val_compare_and_swap_word"
+    val_compare_and_swap_word :: Ptr Word -> Word -> Word -> IO Word
+foreign import ccall unsafe "atomic-bitops-gcc.h lock_test_and_set_word"
+    lock_test_and_set_word :: Ptr Word -> IO Word
+foreign import ccall unsafe "atomic-bitops-gcc.h lock_release_word"
+    lock_release_word :: Ptr Word -> IO ()
+
+instance AtomicBits Word where
+    fetchAndAdd = fetch_and_add_word
+    {-# INLINE fetchAndAdd #-}
+    fetchAndSub = fetch_and_sub_word
+    {-# INLINE fetchAndSub #-}
+    fetchAndOr = fetch_and_or_word
+    {-# INLINE fetchAndOr #-}
+    fetchAndAnd = fetch_and_and_word
+    {-# INLINE fetchAndAnd #-}
+    fetchAndXor = fetch_and_xor_word
+    {-# INLINE fetchAndXor #-}
+    fetchAndNand = fetch_and_nand_word
+    {-# INLINE fetchAndNand #-}
+    addAndFetch = add_and_fetch_word
+    {-# INLINE addAndFetch #-}
+    subAndFetch = sub_and_fetch_word
+    {-# INLINE subAndFetch #-}
+    orAndFetch = or_and_fetch_word
+    {-# INLINE orAndFetch #-}
+    andAndFetch = and_and_fetch_word
+    {-# INLINE andAndFetch #-}
+    xorAndFetch = xor_and_fetch_word
+    {-# INLINE xorAndFetch #-}
+    nandAndFetch = nand_and_fetch_word
+    {-# INLINE nandAndFetch #-}
+    compareAndSwapBool = bool_compare_and_swap_word
+    {-# INLINE compareAndSwapBool #-}
+    compareAndSwap = val_compare_and_swap_word
+    {-# INLINE compareAndSwap #-}
+    lockTestAndSet = lock_test_and_set_word
+    {-# INLINE lockTestAndSet #-}
+    lockRelease = lock_release_word
+    {-# INLINE lockRelease #-}
+
+
+instance AtomicBits Int where
+    fetchAndAdd p v = fmap fromIntegral $ fetch_and_add_word 
+                                        (castPtr p :: Ptr Word)
+                                        (fromIntegral v)
+    {-# INLINE fetchAndAdd #-}
+    fetchAndSub p v = fmap fromIntegral $ fetch_and_sub_word
+                                        (castPtr p :: Ptr Word)
+                                        (fromIntegral v)
+    {-# INLINE fetchAndSub #-}
+    fetchAndOr p v = fmap fromIntegral $ fetch_and_or_word
+                                        (castPtr p :: Ptr Word)
+                                        (fromIntegral v)
+    {-# INLINE fetchAndOr #-}
+    fetchAndAnd p v = fmap fromIntegral $ fetch_and_and_word
+                                        (castPtr p :: Ptr Word)
+                                        (fromIntegral v)
+    {-# INLINE fetchAndAnd #-}
+    fetchAndXor p v = fmap fromIntegral $ fetch_and_xor_word
+                                        (castPtr p :: Ptr Word)
+                                        (fromIntegral v)
+    {-# INLINE fetchAndXor #-}
+    fetchAndNand p v = fmap fromIntegral $ fetch_and_nand_word
+                                        (castPtr p :: Ptr Word)
+                                        (fromIntegral v)
+    {-# INLINE fetchAndNand #-}
+    addAndFetch p v = fmap fromIntegral $ add_and_fetch_word
+                                        (castPtr p :: Ptr Word)
+                                        (fromIntegral v)
+    {-# INLINE addAndFetch #-}
+    subAndFetch p v = fmap fromIntegral $ sub_and_fetch_word
+                                        (castPtr p :: Ptr Word)
+                                        (fromIntegral v)
+    {-# INLINE subAndFetch #-}
+    orAndFetch p v = fmap fromIntegral $ or_and_fetch_word
+                                        (castPtr p :: Ptr Word)
+                                        (fromIntegral v)
+    {-# INLINE orAndFetch #-}
+    andAndFetch p v = fmap fromIntegral $ and_and_fetch_word
+                                        (castPtr p :: Ptr Word)
+                                        (fromIntegral v)
+    {-# INLINE andAndFetch #-}
+    xorAndFetch p v = fmap fromIntegral $ xor_and_fetch_word
+                                        (castPtr p :: Ptr Word)
+                                        (fromIntegral v)
+    {-# INLINE xorAndFetch #-}
+    nandAndFetch p v = fmap fromIntegral $ nand_and_fetch_word
+                                        (castPtr p :: Ptr Word)
+                                        (fromIntegral v)
+    {-# INLINE nandAndFetch #-}
+    compareAndSwapBool p o n = bool_compare_and_swap_word
+                                        (castPtr p :: Ptr Word)
+                                        (fromIntegral o)
+                                        (fromIntegral n)
+    {-# INLINE compareAndSwapBool #-}
+    compareAndSwap p o n = fmap fromIntegral $ val_compare_and_swap_word
+                                        (castPtr p :: Ptr Word)
+                                        (fromIntegral o)
+                                        (fromIntegral n)
+    {-# INLINE compareAndSwap #-}
+    lockTestAndSet p = fmap fromIntegral $ lock_test_and_set_word 
+                                        (castPtr p :: Ptr Word)
+    {-# INLINE lockTestAndSet #-}
+    lockRelease p = lock_release_word (castPtr p :: Ptr Word)
+    {-# INLINE lockRelease #-}
+
+instance AtomicBits Int8 where
+    fetchAndAdd p v = fmap fromIntegral $ fetch_and_add_8 
+                                        (castPtr p :: Ptr Word8)
+                                        (fromIntegral v)
+    {-# INLINE fetchAndAdd #-}
+    fetchAndSub p v = fmap fromIntegral $ fetch_and_sub_8
+                                        (castPtr p :: Ptr Word8)
+                                        (fromIntegral v)
+    {-# INLINE fetchAndSub #-}
+    fetchAndOr p v = fmap fromIntegral $ fetch_and_or_8
+                                        (castPtr p :: Ptr Word8)
+                                        (fromIntegral v)
+    {-# INLINE fetchAndOr #-}
+    fetchAndAnd p v = fmap fromIntegral $ fetch_and_and_8
+                                        (castPtr p :: Ptr Word8)
+                                        (fromIntegral v)
+    {-# INLINE fetchAndAnd #-}
+    fetchAndXor p v = fmap fromIntegral $ fetch_and_xor_8
+                                        (castPtr p :: Ptr Word8)
+                                        (fromIntegral v)
+    {-# INLINE fetchAndXor #-}
+    fetchAndNand p v = fmap fromIntegral $ fetch_and_nand_8
+                                        (castPtr p :: Ptr Word8)
+                                        (fromIntegral v)
+    {-# INLINE fetchAndNand #-}
+    addAndFetch p v = fmap fromIntegral $ add_and_fetch_8
+                                        (castPtr p :: Ptr Word8)
+                                        (fromIntegral v)
+    {-# INLINE addAndFetch #-}
+    subAndFetch p v = fmap fromIntegral $ sub_and_fetch_8
+                                        (castPtr p :: Ptr Word8)
+                                        (fromIntegral v)
+    {-# INLINE subAndFetch #-}
+    orAndFetch p v = fmap fromIntegral $ or_and_fetch_8
+                                        (castPtr p :: Ptr Word8)
+                                        (fromIntegral v)
+    {-# INLINE orAndFetch #-}
+    andAndFetch p v = fmap fromIntegral $ and_and_fetch_8
+                                        (castPtr p :: Ptr Word8)
+                                        (fromIntegral v)
+    {-# INLINE andAndFetch #-}
+    xorAndFetch p v = fmap fromIntegral $ xor_and_fetch_8
+                                        (castPtr p :: Ptr Word8)
+                                        (fromIntegral v)
+    {-# INLINE xorAndFetch #-}
+    nandAndFetch p v = fmap fromIntegral $ nand_and_fetch_8
+                                        (castPtr p :: Ptr Word8)
+                                        (fromIntegral v)
+    {-# INLINE nandAndFetch #-}
+    compareAndSwapBool p o n = bool_compare_and_swap_8
+                                        (castPtr p :: Ptr Word8)
+                                        (fromIntegral o)
+                                        (fromIntegral n)
+    {-# INLINE compareAndSwapBool #-}
+    compareAndSwap p o n = fmap fromIntegral $ val_compare_and_swap_8
+                                        (castPtr p :: Ptr Word8)
+                                        (fromIntegral o)
+                                        (fromIntegral n)
+    {-# INLINE compareAndSwap #-}
+    lockTestAndSet p = fmap fromIntegral $ lock_test_and_set_8 
+                                        (castPtr p :: Ptr Word8)
+    {-# INLINE lockTestAndSet #-}
+    lockRelease p = lock_release_8 (castPtr p :: Ptr Word8)
+    {-# INLINE lockRelease #-}
+
+instance AtomicBits Int16 where
+    fetchAndAdd p v = fmap fromIntegral $ fetch_and_add_16 
+                                        (castPtr p :: Ptr Word16)
+                                        (fromIntegral v)
+    {-# INLINE fetchAndAdd #-}
+    fetchAndSub p v = fmap fromIntegral $ fetch_and_sub_16
+                                        (castPtr p :: Ptr Word16)
+                                        (fromIntegral v)
+    {-# INLINE fetchAndSub #-}
+    fetchAndOr p v = fmap fromIntegral $ fetch_and_or_16
+                                        (castPtr p :: Ptr Word16)
+                                        (fromIntegral v)
+    {-# INLINE fetchAndOr #-}
+    fetchAndAnd p v = fmap fromIntegral $ fetch_and_and_16
+                                        (castPtr p :: Ptr Word16)
+                                        (fromIntegral v)
+    {-# INLINE fetchAndAnd #-}
+    fetchAndXor p v = fmap fromIntegral $ fetch_and_xor_16
+                                        (castPtr p :: Ptr Word16)
+                                        (fromIntegral v)
+    {-# INLINE fetchAndXor #-}
+    fetchAndNand p v = fmap fromIntegral $ fetch_and_nand_16
+                                        (castPtr p :: Ptr Word16)
+                                        (fromIntegral v)
+    {-# INLINE fetchAndNand #-}
+    addAndFetch p v = fmap fromIntegral $ add_and_fetch_16
+                                        (castPtr p :: Ptr Word16)
+                                        (fromIntegral v)
+    {-# INLINE addAndFetch #-}
+    subAndFetch p v = fmap fromIntegral $ sub_and_fetch_16
+                                        (castPtr p :: Ptr Word16)
+                                        (fromIntegral v)
+    {-# INLINE subAndFetch #-}
+    orAndFetch p v = fmap fromIntegral $ or_and_fetch_16
+                                        (castPtr p :: Ptr Word16)
+                                        (fromIntegral v)
+    {-# INLINE orAndFetch #-}
+    andAndFetch p v = fmap fromIntegral $ and_and_fetch_16
+                                        (castPtr p :: Ptr Word16)
+                                        (fromIntegral v)
+    {-# INLINE andAndFetch #-}
+    xorAndFetch p v = fmap fromIntegral $ xor_and_fetch_16
+                                        (castPtr p :: Ptr Word16)
+                                        (fromIntegral v)
+    {-# INLINE xorAndFetch #-}
+    nandAndFetch p v = fmap fromIntegral $ nand_and_fetch_16
+                                        (castPtr p :: Ptr Word16)
+                                        (fromIntegral v)
+    {-# INLINE nandAndFetch #-}
+    compareAndSwapBool p o n = bool_compare_and_swap_16
+                                        (castPtr p :: Ptr Word16)
+                                        (fromIntegral o)
+                                        (fromIntegral n)
+    {-# INLINE compareAndSwapBool #-}
+    compareAndSwap p o n = fmap fromIntegral $ val_compare_and_swap_16
+                                        (castPtr p :: Ptr Word16)
+                                        (fromIntegral o)
+                                        (fromIntegral n)
+    {-# INLINE compareAndSwap #-}
+    lockTestAndSet p = fmap fromIntegral $ lock_test_and_set_16 
+                                        (castPtr p :: Ptr Word16)
+    {-# INLINE lockTestAndSet #-}
+    lockRelease p = lock_release_16 (castPtr p :: Ptr Word16)
+    {-# INLINE lockRelease #-}
+
+instance AtomicBits Int32 where
+    fetchAndAdd p v = fmap fromIntegral $ fetch_and_add_32 
+                                        (castPtr p :: Ptr Word32)
+                                        (fromIntegral v)
+    {-# INLINE fetchAndAdd #-}
+    fetchAndSub p v = fmap fromIntegral $ fetch_and_sub_32
+                                        (castPtr p :: Ptr Word32)
+                                        (fromIntegral v)
+    {-# INLINE fetchAndSub #-}
+    fetchAndOr p v = fmap fromIntegral $ fetch_and_or_32
+                                        (castPtr p :: Ptr Word32)
+                                        (fromIntegral v)
+    {-# INLINE fetchAndOr #-}
+    fetchAndAnd p v = fmap fromIntegral $ fetch_and_and_32
+                                        (castPtr p :: Ptr Word32)
+                                        (fromIntegral v)
+    {-# INLINE fetchAndAnd #-}
+    fetchAndXor p v = fmap fromIntegral $ fetch_and_xor_32
+                                        (castPtr p :: Ptr Word32)
+                                        (fromIntegral v)
+    {-# INLINE fetchAndXor #-}
+    fetchAndNand p v = fmap fromIntegral $ fetch_and_nand_32
+                                        (castPtr p :: Ptr Word32)
+                                        (fromIntegral v)
+    {-# INLINE fetchAndNand #-}
+    addAndFetch p v = fmap fromIntegral $ add_and_fetch_32
+                                        (castPtr p :: Ptr Word32)
+                                        (fromIntegral v)
+    {-# INLINE addAndFetch #-}
+    subAndFetch p v = fmap fromIntegral $ sub_and_fetch_32
+                                        (castPtr p :: Ptr Word32)
+                                        (fromIntegral v)
+    {-# INLINE subAndFetch #-}
+    orAndFetch p v = fmap fromIntegral $ or_and_fetch_32
+                                        (castPtr p :: Ptr Word32)
+                                        (fromIntegral v)
+    {-# INLINE orAndFetch #-}
+    andAndFetch p v = fmap fromIntegral $ and_and_fetch_32
+                                        (castPtr p :: Ptr Word32)
+                                        (fromIntegral v)
+    {-# INLINE andAndFetch #-}
+    xorAndFetch p v = fmap fromIntegral $ xor_and_fetch_32
+                                        (castPtr p :: Ptr Word32)
+                                        (fromIntegral v)
+    {-# INLINE xorAndFetch #-}
+    nandAndFetch p v = fmap fromIntegral $ nand_and_fetch_32
+                                        (castPtr p :: Ptr Word32)
+                                        (fromIntegral v)
+    {-# INLINE nandAndFetch #-}
+    compareAndSwapBool p o n = bool_compare_and_swap_32
+                                        (castPtr p :: Ptr Word32)
+                                        (fromIntegral o)
+                                        (fromIntegral n)
+    {-# INLINE compareAndSwapBool #-}
+    compareAndSwap p o n = fmap fromIntegral $ val_compare_and_swap_32
+                                        (castPtr p :: Ptr Word32)
+                                        (fromIntegral o)
+                                        (fromIntegral n)
+    {-# INLINE compareAndSwap #-}
+    lockTestAndSet p = fmap fromIntegral $ lock_test_and_set_32 
+                                        (castPtr p :: Ptr Word32)
+    {-# INLINE lockTestAndSet #-}
+    lockRelease p = lock_release_32 (castPtr p :: Ptr Word32)
+    {-# INLINE lockRelease #-}
+
+instance AtomicBits Int64 where
+    fetchAndAdd p v = fmap fromIntegral $ fetch_and_add_64 
+                                        (castPtr p :: Ptr Word64)
+                                        (fromIntegral v)
+    {-# INLINE fetchAndAdd #-}
+    fetchAndSub p v = fmap fromIntegral $ fetch_and_sub_64
+                                        (castPtr p :: Ptr Word64)
+                                        (fromIntegral v)
+    {-# INLINE fetchAndSub #-}
+    fetchAndOr p v = fmap fromIntegral $ fetch_and_or_64
+                                        (castPtr p :: Ptr Word64)
+                                        (fromIntegral v)
+    {-# INLINE fetchAndOr #-}
+    fetchAndAnd p v = fmap fromIntegral $ fetch_and_and_64
+                                        (castPtr p :: Ptr Word64)
+                                        (fromIntegral v)
+    {-# INLINE fetchAndAnd #-}
+    fetchAndXor p v = fmap fromIntegral $ fetch_and_xor_64
+                                        (castPtr p :: Ptr Word64)
+                                        (fromIntegral v)
+    {-# INLINE fetchAndXor #-}
+    fetchAndNand p v = fmap fromIntegral $ fetch_and_nand_64
+                                        (castPtr p :: Ptr Word64)
+                                        (fromIntegral v)
+    {-# INLINE fetchAndNand #-}
+    addAndFetch p v = fmap fromIntegral $ add_and_fetch_64
+                                        (castPtr p :: Ptr Word64)
+                                        (fromIntegral v)
+    {-# INLINE addAndFetch #-}
+    subAndFetch p v = fmap fromIntegral $ sub_and_fetch_64
+                                        (castPtr p :: Ptr Word64)
+                                        (fromIntegral v)
+    {-# INLINE subAndFetch #-}
+    orAndFetch p v = fmap fromIntegral $ or_and_fetch_64
+                                        (castPtr p :: Ptr Word64)
+                                        (fromIntegral v)
+    {-# INLINE orAndFetch #-}
+    andAndFetch p v = fmap fromIntegral $ and_and_fetch_64
+                                        (castPtr p :: Ptr Word64)
+                                        (fromIntegral v)
+    {-# INLINE andAndFetch #-}
+    xorAndFetch p v = fmap fromIntegral $ xor_and_fetch_64
+                                        (castPtr p :: Ptr Word64)
+                                        (fromIntegral v)
+    {-# INLINE xorAndFetch #-}
+    nandAndFetch p v = fmap fromIntegral $ nand_and_fetch_64
+                                        (castPtr p :: Ptr Word64)
+                                        (fromIntegral v)
+    {-# INLINE nandAndFetch #-}
+    compareAndSwapBool p o n = bool_compare_and_swap_64
+                                        (castPtr p :: Ptr Word64)
+                                        (fromIntegral o)
+                                        (fromIntegral n)
+    {-# INLINE compareAndSwapBool #-}
+    compareAndSwap p o n = fmap fromIntegral $ val_compare_and_swap_64
+                                        (castPtr p :: Ptr Word64)
+                                        (fromIntegral o)
+                                        (fromIntegral n)
+    {-# INLINE compareAndSwap #-}
+    lockTestAndSet p = fmap fromIntegral $ lock_test_and_set_64 
+                                        (castPtr p :: Ptr Word64)
+    {-# INLINE lockTestAndSet #-}
+    lockRelease p = lock_release_64 (castPtr p :: Ptr Word64)
+    {-# INLINE lockRelease #-}
diff --git a/License.txt b/License.txt
new file mode 100644
--- /dev/null
+++ b/License.txt
@@ -0,0 +1,26 @@
+Copyright (c) The Regents of the University of California.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+3. Neither the name of the University nor the names of its contributors
+   may be used to endorse or promote products derived from this software
+   without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,12 @@
+import Distribution.Simple
+import Distribution.PackageDescription
+import Distribution.Simple.LocalBuildInfo(LocalBuildInfo, buildDir)
+import System.Cmd(system)
+import System.FilePath
+
+main = defaultMainWithHooks hooks
+  where hooks = simpleUserHooks { runTests = runTests' }
+
+runTests' :: Args -> Bool -> PackageDescription -> LocalBuildInfo -> IO ()
+runTests' _ _ _ lbi = system testprog >> return ()
+  where testprog = (buildDir lbi) </> "test" </> "test"
diff --git a/bits-atomic.cabal b/bits-atomic.cabal
new file mode 100644
--- /dev/null
+++ b/bits-atomic.cabal
@@ -0,0 +1,64 @@
+Name:               bits-atomic
+Version:            0.1.0
+License:            BSD3
+License-File:       License.txt
+Maintainer:         Gabriel Wicke <wicke@wikidev.net>
+Author:             Gabriel Wicke <wicke@wikidev.net>
+Synopsis:       Atomic bit operations on memory locations 
+                for low-level synchronization
+Description:        
+ Atomic operations including CAS (compare-and-swap), lock and fetch & add
+ suitable for low-level shared-memory synchronization.
+ .
+ The implementation is using GCC's builtin atomic operations in C wrappers
+ called through the FFI.
+ .
+ /Testing:/ The following commands can be used to compile and run the test suite:
+ .
+    > cabal unpack bits-atomic && cd bits-atomic-* # if not yet locally available
+    > cabal configure -ftest
+    > cabal build
+    > cabal test
+Category:           Data, Concurrency, Foreign
+Stability:          experimental
+Build-Type:         Custom
+Cabal-Version: >= 1.6
+Extra-Source-Files: cbits/atomic-bitops-gcc.c cbits/atomic-bitops-gcc.h
+Source-Repository head
+    type: mercurial
+    location: http://dev.wikidev.net/hg/bits-atomic/
+
+library
+    Exposed-Modules:  Data.Bits.Atomic
+    Build-Depends:    base >= 4 && < 6
+    GHC-Options:      -Wall -O2 -funbox-strict-fields
+    GHC-Prof-Options: -auto-all
+    C-Sources:        cbits/atomic-bitops-gcc.c
+    CC-Options:       -Wall
+    if os (linux)
+        CC-Options: -fomit-frame-pointer -march=native
+    Include-Dirs:     cbits
+    Install-Includes: atomic-bitops-gcc.h
+    -- Try link-time optimization (inlining) with gcc 4.5:
+    -- CC-Options:       -fomit-frame-pointer -march=native -Wall -flto
+    --LD-Options:     -flto
+
+flag test
+    description: Build test program.
+    default:     False
+
+Executable test
+    if !flag(test)
+        buildable:     False
+    hs-source-dirs:  ., test
+    other-modules:   Data.Bits.Atomic
+    main-is:         test.hs
+    GHC-Options:      -O2 -funbox-strict-fields -threaded
+    GHC-Prof-Options: -auto-all
+
+    Include-Dirs:     cbits
+    C-Sources:        cbits/atomic-bitops-gcc.c
+    build-depends:   base >= 4 && < 6, QuickCheck, HUnit,
+                     test-framework-quickcheck2,
+                     test-framework-hunit,
+                     test-framework
diff --git a/cbits/atomic-bitops-gcc.c b/cbits/atomic-bitops-gcc.c
new file mode 100644
--- /dev/null
+++ b/cbits/atomic-bitops-gcc.c
@@ -0,0 +1,278 @@
+#include "atomic-bitops-gcc.h"
+
+void mem_barrier (void) {return __sync_synchronize ();}
+
+/* 8-bit */
+inline unsigned char fetch_and_add_8 (unsigned char *p, unsigned char v) {
+	return __sync_fetch_and_add (p, v);
+}
+inline unsigned char fetch_and_sub_8 (unsigned char *p, unsigned char v) {
+	return __sync_fetch_and_sub (p, v);
+}
+inline unsigned char fetch_and_or_8 (unsigned char *p, unsigned char v) {
+	return __sync_fetch_and_or (p, v);
+}
+inline unsigned char fetch_and_and_8 (unsigned char *p, unsigned char v) {
+	return __sync_fetch_and_and (p, v);
+}
+inline unsigned char fetch_and_xor_8 (unsigned char *p, unsigned char v) {
+	return __sync_fetch_and_xor (p, v);
+}
+inline unsigned char fetch_and_nand_8 (unsigned char *p, unsigned char v) {
+	return __sync_fetch_and_nand (p, v);
+}
+inline unsigned char add_and_fetch_8 (unsigned char *p, unsigned char v) {
+	return __sync_add_and_fetch (p, v);
+}
+inline unsigned char sub_and_fetch_8 (unsigned char *p, unsigned char v) {
+	return __sync_sub_and_fetch (p, v);
+}
+inline unsigned char or_and_fetch_8 (unsigned char *p, unsigned char v) {
+	return __sync_or_and_fetch (p, v);
+}
+inline unsigned char and_and_fetch_8 (unsigned char *p, unsigned char v) {
+	return __sync_and_and_fetch (p, v);
+}
+inline unsigned char xor_and_fetch_8 (unsigned char *p, unsigned char v) {
+	return __sync_xor_and_fetch (p, v);
+}
+inline unsigned char nand_and_fetch_8 (unsigned char *p, unsigned char v) {
+	return __sync_nand_and_fetch (p, v);
+}
+inline unsigned int
+bool_compare_and_swap_8 (unsigned char *p, unsigned char old, unsigned char new) {
+	return __sync_bool_compare_and_swap (p, old, new);
+}
+inline unsigned char
+val_compare_and_swap_8 (unsigned char *p, unsigned char old, unsigned char new) {
+	return __sync_val_compare_and_swap (p, old, new);
+}
+inline unsigned char lock_test_and_set_8 (unsigned char *p) {
+	// Only immediate 0/1 appear to be widely supported, so hardcode it
+	// here
+	return __sync_lock_test_and_set (p, 1);
+}
+void lock_release_8 (unsigned char *p) {
+	// Writes a 0 to *p
+	return __sync_lock_release (p);
+}
+
+/* 16-bit */
+inline unsigned short fetch_and_add_16 (unsigned short *p, unsigned short v) {
+	return __sync_fetch_and_add (p, v);
+}
+inline unsigned short fetch_and_sub_16 (unsigned short *p, unsigned short v) {
+	return __sync_fetch_and_sub (p, v);
+}
+inline unsigned short fetch_and_or_16 (unsigned short *p, unsigned short v) {
+	return __sync_fetch_and_or (p, v);
+}
+inline unsigned short fetch_and_and_16 (unsigned short *p, unsigned short v) {
+	return __sync_fetch_and_and (p, v);
+}
+inline unsigned short fetch_and_xor_16 (unsigned short *p, unsigned short v) {
+	return __sync_fetch_and_xor (p, v);
+}
+inline unsigned short fetch_and_nand_16 (unsigned short *p, unsigned short v) {
+	return __sync_fetch_and_nand (p, v);
+}
+inline unsigned short add_and_fetch_16 (unsigned short *p, unsigned short v) {
+	return __sync_add_and_fetch (p, v);
+}
+inline unsigned short sub_and_fetch_16 (unsigned short *p, unsigned short v) {
+	return __sync_sub_and_fetch (p, v);
+}
+inline unsigned short or_and_fetch_16 (unsigned short *p, unsigned short v) {
+	return __sync_or_and_fetch (p, v);
+}
+inline unsigned short and_and_fetch_16 (unsigned short *p, unsigned short v) {
+	return __sync_and_and_fetch (p, v);
+}
+inline unsigned short xor_and_fetch_16 (unsigned short *p, unsigned short v) {
+	return __sync_xor_and_fetch (p, v);
+}
+inline unsigned short nand_and_fetch_16 (unsigned short *p, unsigned short v) {
+	return __sync_nand_and_fetch (p, v);
+}
+inline unsigned int
+bool_compare_and_swap_16 (unsigned short *p, unsigned short old, unsigned short new) {
+	return __sync_bool_compare_and_swap (p, old, new);
+}
+inline unsigned short
+val_compare_and_swap_16 (unsigned short *p, unsigned short old, unsigned short new) {
+	return __sync_val_compare_and_swap (p, old, new);
+}
+inline unsigned short lock_test_and_set_16 (unsigned short *p) {
+	// Only immediate 0/1 appear to be widely supported, so hardcode it
+	// here
+	return __sync_lock_test_and_set (p, 1);
+}
+void lock_release_16 (unsigned short *p) {
+	// Writes a 0 to *p
+	return __sync_lock_release (p);
+}
+
+/* 32-bit */
+inline unsigned int fetch_and_add_32 (unsigned int *p, unsigned int v) {
+	return __sync_fetch_and_add (p, v);
+}
+inline unsigned int fetch_and_sub_32 (unsigned int *p, unsigned int v) {
+	return __sync_fetch_and_sub (p, v);
+}
+inline unsigned int fetch_and_or_32 (unsigned int *p, unsigned int v) {
+	return __sync_fetch_and_or (p, v);
+}
+inline unsigned int fetch_and_and_32 (unsigned int *p, unsigned int v) {
+	return __sync_fetch_and_and (p, v);
+}
+inline unsigned int fetch_and_xor_32 (unsigned int *p, unsigned int v) {
+	return __sync_fetch_and_xor (p, v);
+}
+inline unsigned int fetch_and_nand_32 (unsigned int *p, unsigned int v) {
+	return __sync_fetch_and_nand (p, v);
+}
+inline unsigned int add_and_fetch_32 (unsigned int *p, unsigned int v) {
+	return __sync_add_and_fetch (p, v);
+}
+inline unsigned int sub_and_fetch_32 (unsigned int *p, unsigned int v) {
+	return __sync_sub_and_fetch (p, v);
+}
+inline unsigned int or_and_fetch_32 (unsigned int *p, unsigned int v) {
+	return __sync_or_and_fetch (p, v);
+}
+inline unsigned int and_and_fetch_32 (unsigned int *p, unsigned int v) {
+	return __sync_and_and_fetch (p, v);
+}
+inline unsigned int xor_and_fetch_32 (unsigned int *p, unsigned int v) {
+	return __sync_xor_and_fetch (p, v);
+}
+inline unsigned int nand_and_fetch_32 (unsigned int *p, unsigned int v) {
+	return __sync_nand_and_fetch (p, v);
+}
+inline unsigned int
+bool_compare_and_swap_32 (unsigned int *p, unsigned int old, unsigned int new) {
+	return __sync_bool_compare_and_swap (p, old, new);
+}
+inline unsigned int
+val_compare_and_swap_32 (unsigned int *p, unsigned int old, unsigned int new) {
+	return __sync_val_compare_and_swap (p, old, new);
+}
+inline unsigned int lock_test_and_set_32 (unsigned int *p) {
+	// Only immediate 0/1 appear to be widely supported, so hardcode it
+	// here
+	return __sync_lock_test_and_set (p, 1);
+}
+void lock_release_32 (unsigned int *p) {
+	// Writes a 0 to *p
+	return __sync_lock_release (p);
+}
+
+/* 64-bit */
+inline unsigned long long fetch_and_add_64 (unsigned long long *p, unsigned long long v) {
+	return __sync_fetch_and_add (p, v);
+}
+inline unsigned long long fetch_and_sub_64 (unsigned long long *p, unsigned long long v) {
+	return __sync_fetch_and_sub (p, v);
+}
+inline unsigned long long fetch_and_or_64 (unsigned long long *p, unsigned long long v) {
+	return __sync_fetch_and_or (p, v);
+}
+inline unsigned long long fetch_and_and_64 (unsigned long long *p, unsigned long long v) {
+	return __sync_fetch_and_and (p, v);
+}
+inline unsigned long long fetch_and_xor_64 (unsigned long long *p, unsigned long long v) {
+	return __sync_fetch_and_xor (p, v);
+}
+inline unsigned long long fetch_and_nand_64 (unsigned long long *p, unsigned long long v) {
+	return __sync_fetch_and_nand (p, v);
+}
+inline unsigned long long add_and_fetch_64 (unsigned long long *p, unsigned long long v) {
+	return __sync_add_and_fetch (p, v);
+}
+inline unsigned long long sub_and_fetch_64 (unsigned long long *p, unsigned long long v) {
+	return __sync_sub_and_fetch (p, v);
+}
+inline unsigned long long or_and_fetch_64 (unsigned long long *p, unsigned long long v) {
+	return __sync_or_and_fetch (p, v);
+}
+inline unsigned long long and_and_fetch_64 (unsigned long long *p, unsigned long long v) {
+	return __sync_and_and_fetch (p, v);
+}
+inline unsigned long long xor_and_fetch_64 (unsigned long long *p, unsigned long long v) {
+	return __sync_xor_and_fetch (p, v);
+}
+inline unsigned long long nand_and_fetch_64 (unsigned long long *p, unsigned long long v) {
+	return __sync_nand_and_fetch (p, v);
+}
+inline unsigned int
+bool_compare_and_swap_64 (unsigned long long *p, unsigned long long old, unsigned long long new) {
+	return __sync_bool_compare_and_swap (p, old, new);
+}
+inline unsigned long long
+val_compare_and_swap_64 (unsigned long long *p, unsigned long long old, unsigned long long new) {
+	return __sync_val_compare_and_swap (p, old, new);
+}
+inline unsigned long long lock_test_and_set_64 (unsigned long long *p) {
+	// Only immediate 0/1 appear to be widely supported, so hardcode it
+	// here
+	return __sync_lock_test_and_set (p, 1);
+}
+void lock_release_64 (unsigned long long *p) {
+	// Writes a 0 to *p
+	return __sync_lock_release (p);
+}
+
+/* Word-sized */
+inline unsigned long fetch_and_add_word (unsigned long *p, unsigned long v) {
+	return __sync_fetch_and_add (p, v);
+}
+inline unsigned long fetch_and_sub_word (unsigned long *p, unsigned long v) {
+	return __sync_fetch_and_sub (p, v);
+}
+inline unsigned long fetch_and_or_word (unsigned long *p, unsigned long v) {
+	return __sync_fetch_and_or (p, v);
+}
+inline unsigned long fetch_and_and_word (unsigned long *p, unsigned long v) {
+	return __sync_fetch_and_and (p, v);
+}
+inline unsigned long fetch_and_xor_word (unsigned long *p, unsigned long v) {
+	return __sync_fetch_and_xor (p, v);
+}
+inline unsigned long fetch_and_nand_word (unsigned long *p, unsigned long v) {
+	return __sync_fetch_and_nand (p, v);
+}
+inline unsigned long add_and_fetch_word (unsigned long *p, unsigned long v) {
+	return __sync_add_and_fetch (p, v);
+}
+inline unsigned long sub_and_fetch_word (unsigned long *p, unsigned long v) {
+	return __sync_sub_and_fetch (p, v);
+}
+inline unsigned long or_and_fetch_word (unsigned long *p, unsigned long v) {
+	return __sync_or_and_fetch (p, v);
+}
+inline unsigned long and_and_fetch_word (unsigned long *p, unsigned long v) {
+	return __sync_and_and_fetch (p, v);
+}
+inline unsigned long xor_and_fetch_word (unsigned long *p, unsigned long v) {
+	return __sync_xor_and_fetch (p, v);
+}
+inline unsigned long nand_and_fetch_word (unsigned long *p, unsigned long v) {
+	return __sync_nand_and_fetch (p, v);
+}
+inline unsigned int
+bool_compare_and_swap_word (unsigned long *p, unsigned long old, unsigned long new) {
+	return __sync_bool_compare_and_swap (p, old, new);
+}
+inline unsigned long
+val_compare_and_swap_word (unsigned long *p, unsigned long old, unsigned long new) {
+	return __sync_val_compare_and_swap (p, old, new);
+}
+inline unsigned long lock_test_and_set_word (unsigned long *p) {
+	// Only immediate 0/1 appear to be widely supported, so hardcode it
+	// here
+	return __sync_lock_test_and_set (p, 1);
+}
+void lock_release_word (unsigned long *p) {
+	// Writes a 0 to *p
+	return __sync_lock_release (p);
+}
diff --git a/cbits/atomic-bitops-gcc.h b/cbits/atomic-bitops-gcc.h
new file mode 100644
--- /dev/null
+++ b/cbits/atomic-bitops-gcc.h
@@ -0,0 +1,105 @@
+// GCC atomic builtins, see http://gcc.gnu.org/onlinedocs/gcc-4.5.0/gcc/Atomic-Builtins.html
+
+/* No size */
+void mem_barrier (void);
+
+/* 8-bit */
+inline unsigned char fetch_and_add_8 (unsigned char *, unsigned char );
+inline unsigned char fetch_and_sub_8 (unsigned char *, unsigned char );
+inline unsigned char fetch_and_or_8 (unsigned char *, unsigned char );
+inline unsigned char fetch_and_and_8 (unsigned char *, unsigned char );
+inline unsigned char fetch_and_xor_8 (unsigned char *, unsigned char );
+inline unsigned char fetch_and_nand_8 (unsigned char *, unsigned char );
+inline unsigned char add_and_fetch_8 (unsigned char *, unsigned char );
+inline unsigned char sub_and_fetch_8 (unsigned char *, unsigned char );
+inline unsigned char or_and_fetch_8 (unsigned char *, unsigned char );
+inline unsigned char and_and_fetch_8 (unsigned char *, unsigned char );
+inline unsigned char xor_and_fetch_8 (unsigned char *, unsigned char );
+inline unsigned char nand_and_fetch_8 (unsigned char *, unsigned char );
+inline unsigned int
+bool_compare_and_swap_8 (unsigned char *, unsigned char, unsigned char);
+inline unsigned char
+val_compare_and_swap_8 (unsigned char *, unsigned char , unsigned char);
+inline unsigned char lock_test_and_set_8 (unsigned char *);
+void lock_release_8 (unsigned char *);
+
+/* 16-bit */
+inline unsigned short fetch_and_add_16 (unsigned short *, unsigned short );
+inline unsigned short fetch_and_sub_16 (unsigned short *, unsigned short );
+inline unsigned short fetch_and_or_16 (unsigned short *, unsigned short );
+inline unsigned short fetch_and_and_16 (unsigned short *, unsigned short );
+inline unsigned short fetch_and_xor_16 (unsigned short *, unsigned short );
+inline unsigned short fetch_and_nand_16 (unsigned short *, unsigned short );
+inline unsigned short add_and_fetch_16 (unsigned short *, unsigned short );
+inline unsigned short sub_and_fetch_16 (unsigned short *, unsigned short );
+inline unsigned short or_and_fetch_16 (unsigned short *, unsigned short );
+inline unsigned short and_and_fetch_16 (unsigned short *, unsigned short );
+inline unsigned short xor_and_fetch_16 (unsigned short *, unsigned short );
+inline unsigned short nand_and_fetch_16 (unsigned short *, unsigned short );
+inline unsigned int
+bool_compare_and_swap_16 (unsigned short *, unsigned short , unsigned short );
+inline unsigned short
+val_compare_and_swap_16 (unsigned short *, unsigned short , unsigned short );
+inline unsigned short lock_test_and_set_16 (unsigned short *);
+void lock_release_16 (unsigned short *);
+
+
+/* 32-bit */
+inline unsigned int fetch_and_add_32 (unsigned int *, unsigned int );
+inline unsigned int fetch_and_sub_32 (unsigned int *, unsigned int );
+inline unsigned int fetch_and_or_32 (unsigned int *, unsigned int );
+inline unsigned int fetch_and_and_32 (unsigned int *, unsigned int );
+inline unsigned int fetch_and_xor_32 (unsigned int *, unsigned int );
+inline unsigned int fetch_and_nand_32 (unsigned int *, unsigned int );
+inline unsigned int add_and_fetch_32 (unsigned int *, unsigned int );
+inline unsigned int sub_and_fetch_32 (unsigned int *, unsigned int );
+inline unsigned int or_and_fetch_32 (unsigned int *, unsigned int );
+inline unsigned int and_and_fetch_32 (unsigned int *, unsigned int );
+inline unsigned int xor_and_fetch_32 (unsigned int *, unsigned int );
+inline unsigned int nand_and_fetch_32 (unsigned int *, unsigned int );
+inline unsigned int
+bool_compare_and_swap_32 (unsigned int *, unsigned int , unsigned int );
+inline unsigned int
+val_compare_and_swap_32 (unsigned int *, unsigned int , unsigned int );
+inline unsigned int lock_test_and_set_32 (unsigned int *);
+void lock_release_32 (unsigned int *);
+
+/* 64-bit */
+inline unsigned long long fetch_and_add_64 (unsigned long long *, unsigned long long );
+inline unsigned long long fetch_and_sub_64 (unsigned long long *, unsigned long long );
+inline unsigned long long fetch_and_or_64 (unsigned long long *, unsigned long long );
+inline unsigned long long fetch_and_and_64 (unsigned long long *, unsigned long long );
+inline unsigned long long fetch_and_xor_64 (unsigned long long *, unsigned long long );
+inline unsigned long long fetch_and_nand_64 (unsigned long long *, unsigned long long );
+inline unsigned long long add_and_fetch_64 (unsigned long long *, unsigned long long );
+inline unsigned long long sub_and_fetch_64 (unsigned long long *, unsigned long long );
+inline unsigned long long or_and_fetch_64 (unsigned long long *, unsigned long long );
+inline unsigned long long and_and_fetch_64 (unsigned long long *, unsigned long long );
+inline unsigned long long xor_and_fetch_64 (unsigned long long *, unsigned long long );
+inline unsigned long long nand_and_fetch_64 (unsigned long long *, unsigned long long );
+inline unsigned int
+bool_compare_and_swap_64 (unsigned long long *, unsigned long long , unsigned long long );
+inline unsigned long long
+val_compare_and_swap_64 (unsigned long long *, unsigned long long , unsigned long long );
+inline unsigned long long lock_test_and_set_64 (unsigned long long *);
+void lock_release_64 (unsigned long long *);
+
+/* Word */
+inline unsigned long fetch_and_add_word (unsigned long *, unsigned long );
+inline unsigned long fetch_and_sub_word (unsigned long *, unsigned long );
+inline unsigned long fetch_and_or_word (unsigned long *, unsigned long );
+inline unsigned long fetch_and_and_word (unsigned long *, unsigned long );
+inline unsigned long fetch_and_xor_word (unsigned long *, unsigned long );
+inline unsigned long fetch_and_nand_word (unsigned long *, unsigned long );
+inline unsigned long add_and_fetch_word (unsigned long *, unsigned long );
+inline unsigned long sub_and_fetch_word (unsigned long *, unsigned long );
+inline unsigned long or_and_fetch_word (unsigned long *, unsigned long );
+inline unsigned long and_and_fetch_word (unsigned long *, unsigned long );
+inline unsigned long xor_and_fetch_word (unsigned long *, unsigned long );
+inline unsigned long nand_and_fetch_word (unsigned long *, unsigned long );
+inline unsigned int
+bool_compare_and_swap_word (unsigned long *, unsigned long , unsigned long );
+inline unsigned long
+val_compare_and_swap_word (unsigned long *, unsigned long , unsigned long );
+inline unsigned long lock_test_and_set_word (unsigned long *);
+void lock_release_word (unsigned long *);
diff --git a/test/test.hs b/test/test.hs
new file mode 100644
--- /dev/null
+++ b/test/test.hs
@@ -0,0 +1,152 @@
+{-# LANGUAGE ForeignFunctionInterface, RankNTypes, FlexibleContexts #-}
+-- Test framework imports
+import Test.Framework (defaultMain, testGroup, Test)
+import Test.Framework.Providers.HUnit
+import Test.HUnit hiding (Test, Testable)
+import Test.Framework.Providers.QuickCheck2
+import Test.QuickCheck
+
+-- Code to test
+import Data.Bits.Atomic
+import Foreign.Marshal.Alloc
+import Foreign.Storable
+import Data.Word
+import Data.Int
+import Data.Bits
+
+tests :: [Test]
+tests = [ testGroup "Test Cases" 
+          [ testCase "compareAndSwap" test_compareAndSwap_all
+          , testCase "compareAndSwapBool" test_compareAndSwapBool_all
+          , testCase "lockTestAndSet and lockRelease" test_lockTestRelease_all
+          , testCase "fetchAndAdd" test_fetchAndAdd_all
+          , testCase "fetchAndSub" test_fetchAndSub_all
+          , testCase "fetchAndXor" test_fetchAndXor_all
+          , testCase "subAndFetch" test_subAndFetch_all
+          ]
+        ]
+
+main :: IO ()
+main = defaultMain tests
+
+testPattern :: Integral a => a
+testPattern = 0xdeadbeef
+
+type PolyTest = (AtomicBits a, Storable a, Integral a, Bounded a) => a -> Assertion
+
+testTypes :: PolyTest -> Assertion
+testTypes _test = do
+    _test (1 :: Int)
+    _test (1 :: Word)
+    _test (1 :: Int8)
+    _test (1 :: Int16)
+    _test (1 :: Int32)
+    _test (1 :: Int64)
+    _test (1 :: Word8)
+    _test (1 :: Word16)
+    _test (1 :: Word32)
+    _test (1 :: Word64)
+
+test_compareAndSwap :: (AtomicBits a, Storable a, Integral a, Bounded a) => 
+             a -> Assertion
+test_compareAndSwap i = alloca $ \p -> do
+    poke p i
+    old1 <- compareAndSwap p i 2
+    old1 @?= i
+    old2 <- compareAndSwap p 3 3
+    old2 @?= 2
+    new <- peek p
+    new @?= 2
+    old3 <- compareAndSwap p 2 3
+    old3 @?= 2
+test_compareAndSwap_all :: Assertion
+test_compareAndSwap_all = testTypes test_compareAndSwap
+
+test_compareAndSwapBool :: (AtomicBits a, Storable a, Integral a, Bounded a) => 
+             a -> Assertion
+test_compareAndSwapBool i = alloca $ \p -> do
+    poke p i
+    swap0 <- compareAndSwapBool p i 2
+    swap0 @?= True
+    swap1 <- compareAndSwapBool p 3 3
+    swap1 @?= False
+    new <- peek p
+    new @?= 2
+    swap2 <- compareAndSwapBool p 2 3
+    swap2 @?= True
+test_compareAndSwapBool_all :: Assertion
+test_compareAndSwapBool_all = testTypes test_compareAndSwapBool
+
+test_fetchAndAdd :: (AtomicBits a, Storable a, Integral a, Bounded a) => 
+                 a -> Assertion
+test_fetchAndAdd i = alloca $ \p -> do
+    poke p i
+    old0 <- fetchAndAdd p 1
+    old0 @?= i
+    new <- peek p
+    new @?= i + 1
+    poke p (maxBound `asTypeOf` i)
+    old1 <- fetchAndAdd p 1
+    old1 @?= (maxBound  `asTypeOf` i)
+    new1 <- peek p
+    new1 @?= (minBound `asTypeOf` i)
+
+test_fetchAndAdd_all :: Assertion
+test_fetchAndAdd_all = testTypes test_fetchAndAdd
+
+
+test_fetchAndSub :: (AtomicBits a, Storable a, Integral a, Bounded a) => 
+                 a -> Assertion
+test_fetchAndSub i = alloca $ \p -> do
+    poke p i
+    old0 <- fetchAndSub p 1
+    old0 @?= i
+    new <- peek p
+    new @?= i - 1
+    poke p (minBound `asTypeOf` i)
+    old1 <- fetchAndSub p 1
+    old1 @?= (minBound  `asTypeOf` i)
+    new1 <- peek p
+    new1 @?= (maxBound `asTypeOf` i)
+test_fetchAndSub_all :: Assertion
+test_fetchAndSub_all = testTypes test_fetchAndSub
+
+
+test_fetchAndXor :: (AtomicBits a, Storable a, Integral a, Bounded a) => 
+                 a -> Assertion
+test_fetchAndXor i = alloca $ \p -> do
+    poke p i
+    old0 <- fetchAndXor p 1
+    old0 @?= i
+    new <- peek p
+    new @?= i `xor` 1
+test_fetchAndXor_all :: Assertion
+test_fetchAndXor_all = testTypes test_fetchAndXor
+
+
+test_subAndFetch :: (AtomicBits a, Storable a, Integral a, Bounded a) => 
+                 a -> Assertion
+test_subAndFetch i = alloca $ \p -> do
+    poke p i
+    new0 <- subAndFetch p 1
+    new0 @?= i - 1
+    poke p (minBound `asTypeOf` i)
+    new1 <- subAndFetch p 1
+    new1 @?= (maxBound  `asTypeOf` i)
+
+test_subAndFetch_all :: Assertion
+test_subAndFetch_all = testTypes test_subAndFetch
+
+test_lockTestRelease :: (AtomicBits a, Storable a, Integral a, Bounded a) => 
+                 a -> Assertion
+test_lockTestRelease i = alloca $ \p -> do
+    poke p i
+    new0 <- lockTestAndSet p
+    new0 @?= i
+    new1 <- peek p
+    new1 @?= 1
+    lockRelease p
+    new2 <- peek p
+    new2 @?= 0
+test_lockTestRelease_all :: Assertion
+test_lockTestRelease_all = testTypes test_lockTestRelease
