diff --git a/DEVLOG.md b/DEVLOG.md
--- a/DEVLOG.md
+++ b/DEVLOG.md
@@ -296,6 +296,7 @@
 
 
 [2013.08.02] {Just observed a failure}
+----------------------------------------
 
 On machine basalt, ghc 7.6.3.  But is it reproducible?
 
@@ -303,4 +304,38 @@
     n_threads_mutate: [Failed]
     Did the sum end up equal to 120?
     run_barriers: [OK]
+
+
+[2014.01.31] {Working on debugging CAS problems wiht n_threads_mutate test}
+---------------------------------------------------------------------------
+
+Now n_threads_mutate is failing consistently.  It seems that I'm
+getting false POSITIVES when attempting a CAS.
+
+    1 0: Fail when putting 1, was already 1
+    2 3 2: Fail when putting 2, was already 3
+    4 5 6 6: Fail when putting 6, was already 6
+    7 3: Fail when putting 4, was already 5
+    8 9 10 11 12 13 14 15 15 16 14: Fail when putting 11, was already 16
+    17 18 19 20 21 22 23 24 25 26 27 28 29 31 30 33 34 35 32 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 106 105 107 108 109 110 111 112 113 114 115 116 117 118 119
+    n_threads_mutate: [Failed]
+    Did the 120 threads CASing all succeed?
+    expected: 120
+     but got: 119
+
+Here are the "successes":
+
+    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 15 16 17 18 19 20 21 22 23 24
+    25 26 27 28 29 31 30 33 34 35 32 36 37 38 39 40 41 42 43 44 45 46
+    47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
+    69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
+    91 92 93 94 95 96 97 98 99 100 101 102 103 104 106 105 107 108 109
+    110 111 112 113 114 115 116 117 118 119
+
+Notice that 15 occurs TWICE.  Two threads think that they successfully
+incremented 14 into 15.
+
+Could that somehow happen if there were two different (boxed) objects
+representing 14?  
+
 
diff --git a/Data/Atomics.hs b/Data/Atomics.hs
--- a/Data/Atomics.hs
+++ b/Data/Atomics.hs
@@ -1,4 +1,5 @@
 {-# LANGUAGE  MagicHash, UnboxedTuples, BangPatterns, ScopedTypeVariables, CPP #-}
+{-# LANGUAGE ForeignFunctionInterface #-}
 
 -- | Provides atomic memory operations on IORefs and Mutable Arrays.
 --
@@ -14,16 +15,17 @@
    -- * Types for atomic operations
    Ticket, peekTicket, -- CASResult(..),
 
+   -- * Atomic operations on IORefs
+   readForCAS, casIORef, casIORef2, 
+   
    -- * Atomic operations on mutable arrays
    casArrayElem, casArrayElem2, readArrayElem, 
 
    -- * Atomic operations on byte arrays
    casByteArrayInt, fetchAddByteArrayInt,
-   
-   -- * Atomic operations on IORefs
-   readForCAS, casIORef, casIORef2, 
-   
+      
    -- * Atomic operations on raw MutVars
+   -- | A lower-level version of the IORef interface.
    readMutVarForCAS, casMutVar, casMutVar2,
 
    -- * Memory barriers
@@ -40,7 +42,12 @@
 import GHC.IORef
 import GHC.STRef
 import GHC.ST
+#if MIN_VERSION_base(4,7,0)
+import GHC.Prim hiding ((==#))
+import qualified GHC.PrimopWrappers as GPW
+#else
 import GHC.Prim
+#endif
 import GHC.Arr 
 import GHC.Base (Int(I#))
 import GHC.IO (IO(IO))
@@ -75,12 +82,13 @@
 -- GHC 7.8 changed some primops
 #if MIN_VERSION_base(4,7,0)
 (==#) :: Int# -> Int# -> Bool
-(==#) x y = case x ==$# y of { 0# -> False; _ -> True }
+(==#) x y = case x GPW.==# y of { 0# -> False; _ -> True }
 #endif
 
 --------------------------------------------------------------------------------
 
--- | Compare-and-swap 
+-- | Compare-and-swap.  Follows the same rules as `casIORef`, returning the ticket for
+--   then next operation.
 casArrayElem :: MutableArray RealWorld a -> Int -> Ticket a -> a -> IO (Bool, Ticket a)
 -- casArrayElem (MutableArray arr#) (I# i#) old new = IO$ \s1# ->
 --  case casArray# arr# i# old new s1# of 
@@ -94,6 +102,7 @@
  case casArrayTicketed# arr# i# old new s1# of 
    (# s2#, x#, res #) -> (# s2#, (x# ==# 0#, res) #)
 
+-- | Ordinary processor load instruction (non-atomic, not implying any memory barriers).
 readArrayElem :: forall a . MutableArray RealWorld a -> Int -> IO (Ticket a)
 -- readArrayElem = unsafeCoerce# readArray#
 readArrayElem (MutableArray arr#) (I# i#) = IO $ \ st -> unsafeCoerce# (fn st)
@@ -101,6 +110,13 @@
     fn :: State# RealWorld -> (# State# RealWorld, a #)
     fn = readArray# arr# i#
 
+-- | Compare and swap on word-sized chunks of a byte-array.  For indexing purposes
+-- the bytearray is treated as an array of words (`Int`s).  Note that UNLIKE
+-- `casIORef` and `casArrayTicketed`, this does not need to operate on tickets.
+--
+-- Further, this version always returns the /old value/, that was read from the array during
+-- the CAS operation.  That is, it follows the normal protocol for CAS operations
+-- (and matches the underlying instruction on most architectures).
 casByteArrayInt ::  MutableByteArray RealWorld -> Int -> Int -> Int -> IO Int
 casByteArrayInt (MutableByteArray mba#) (I# ix#) (I# old#) (I# new#) =
   IO$ \s1# ->
@@ -115,6 +131,11 @@
   (# s2#, (I# res) #)
   -- I don't know if a let will mak any difference here... hopefully not.
 
+-- | Atomically add to a word of memory within a `MutableByteArray`.
+-- 
+--   This function returns the NEW value of the location after the increment.
+--   Thus, it is a bit misnamed, and in other contexts might be called "add-and-fetch",
+--   such as in GCC's `__sync_add_and_fetch`.
 fetchAddByteArrayInt ::  MutableByteArray RealWorld -> Int -> Int -> IO Int
 fetchAddByteArrayInt (MutableByteArray mba#) (I# offset#) (I# incr#) = IO $ \ s1# -> 
   let (# s2#, res #) = fetchAddIntArray# mba# offset# incr# s1# in
@@ -122,19 +143,33 @@
 
 --------------------------------------------------------------------------------
 
+-- | Ordinary processor load instruction (non-atomic, not implying any memory barriers).
+-- 
+--   The difference between this function and `readIORef`, is that it returns a /ticket/,
+--   for use in future compare-and-swap operations.
 readForCAS :: IORef a -> IO ( Ticket a )
 readForCAS (IORef (STRef mv)) = readMutVarForCAS mv
 
--- | Performs a machine-level compare and swap operation on an
+-- | Performs a machine-level compare and swap (CAS) operation on an
 -- 'IORef'. Returns a tuple containing a 'Bool' which is 'True' when a
--- swap is performed, along with the 'current' value from the 'IORef'.
+-- swap is performed, along with the most 'current' value from the 'IORef'.
+-- Note that this differs from the more common CAS behavior, which is to
+-- return the /old/ value before the CAS occured.
+--
+-- The reason for the difference is the ticket API.  This function always returns the
+-- ticket that you should use in your next CAS attempt.  In case of success, this ticket
+-- corresponds to the `new` value which you yourself installed in the `IORef`, whereas
+-- in the case of failure it represents the preexisting value currently in the IORef. 
 -- 
 -- Note \"compare\" here means pointer equality in the sense of
--- 'GHC.Prim.reallyUnsafePtrEquality#'.
+-- 'GHC.Prim.reallyUnsafePtrEquality#'.  However, the ticket API absolves
+-- the user of this module from needing to worry about the pointer equality of their
+-- values, which in general requires reasoning about the details of the Haskell
+-- implementation (GHC).
 casIORef :: IORef a  -- ^ The 'IORef' containing a value 'current'
          -> Ticket a -- ^ A ticket for the 'old' value
          -> a        -- ^ The 'new' value to replace 'current' if @old == current@
-         -> IO (Bool, Ticket a)
+         -> IO (Bool, Ticket a) -- ^ Success flag, plus ticket for the NEXT operation.
 casIORef (IORef (STRef var)) old new = casMutVar var old new 
 
 -- | This variant takes two tickets, i.e. the 'new' value is a ticket rather than an
@@ -149,6 +184,7 @@
 --------------------------------------------------------------------------------
 
 -- | A ticket contains or can get the usable Haskell value.
+--   This function does just that.
 {-# NOINLINE peekTicket #-}
 -- At least this function MUST remain NOINLINE.  Issue5 is an example of a bug that
 -- ensues otherwise.
@@ -160,6 +196,7 @@
 seal :: a -> Ticket a 
 seal = unsafeCoerce#
 
+-- | Like `readForCAS`, but for `MutVar#`.
 readMutVarForCAS :: MutVar# RealWorld a -> IO ( Ticket a )
 readMutVarForCAS !mv = IO$ \ st -> readForCAS# mv st
 
@@ -182,21 +219,36 @@
 -- Memory barriers
 --------------------------------------------------------------------------------
 
-
--- | Memory barrier implemented by the GHC rts (SMP.h).
+-- | Memory barrier implemented by the GHC rts (see SMP.h).
 storeLoadBarrier :: IO ()
-storeLoadBarrier = IO$ \st ->
-  case stg_storeLoadBarrier# st of
-    (# st', _ #) -> (# st', () #)
 
--- | Memory barrier implemented by the GHC rts (SMP.h).
+-- | Memory barrier implemented by the GHC rts (see SMP.h).
 loadLoadBarrier :: IO ()
-loadLoadBarrier = IO$ \st ->
-  case stg_loadLoadBarrier# st of
-    (# st', _ #) -> (# st', () #)
 
--- | Memory barrier implemented by the GHC rts (SMP.h).
+-- | Memory barrier implemented by the GHC rts (see SMP.h).
 writeBarrier :: IO ()
-writeBarrier = IO$ \st ->
-  case stg_writeBarrier# st of
-    (# st', _ #) -> (# st', () #)
+
+-- GHC 7.8 consistently exposes these symbols while linking:
+#if MIN_VERSION_base(4,7,0) 
+foreign import ccall  unsafe "store_load_barrier" storeLoadBarrier
+  :: IO () 
+
+foreign import ccall unsafe "load_load_barrier" loadLoadBarrier
+  :: IO ()
+
+foreign import ccall unsafe "write_barrier" writeBarrier
+  :: IO ()
+
+#else
+-- GHC 7.6 did not consistently expose them (e.g. in the non-threaded RTS),
+-- so rather we grab this functionality from RtsDup.c:
+foreign import ccall  unsafe "DUP_store_load_barrier" storeLoadBarrier
+  :: IO () 
+
+foreign import ccall unsafe "DUP_load_load_barrier" loadLoadBarrier
+  :: IO ()
+
+foreign import ccall unsafe "DUP_write_barrier" writeBarrier
+  :: IO ()
+#endif
+
diff --git a/Data/Atomics/Counter.hs b/Data/Atomics/Counter.hs
--- a/Data/Atomics/Counter.hs
+++ b/Data/Atomics/Counter.hs
@@ -1,12 +1,36 @@
 
 
+-- | Integer counters providing thread-safe, lock-free mutation functions.
+--
+--   While this package provides multiple implementations, this module will always
+--   expose the default (best) implementation.  Atomic counters are represented by a
+--   single memory location, such that built-in processor instructions are sufficient
+--   to perform fetch-and-add or compare-and-swap.
+-- 
+--   Remember, contention on such counters should still be minimized!
+
 module Data.Atomics.Counter
+       -- Reexport to get all the docs.
        (
---         module Data.Atomics.Counter.IORef
---         module Data.Atomics.Counter.Foreign
-         module Data.Atomics.Counter.Unboxed
-       ) where
+         -- * Type of counters of counters and tickets
+         AtomicCounter, 
+         
+         -- * Creating counters
+         newCounter, 
 
--- import Data.Atomics.Counter.IORef
--- import Data.Atomics.Counter.Foreign
+         -- * Tickets, used for compare-and-swap         
+         -- | See the documentation for "Data.Atomics" for more explanation of the
+         -- ticket abstraction.  The same ideas apply here for counters as for
+         -- general mutable locations (IORefs).
+         CTicket, peekCTicket,
+
+         -- * Atomic memory operations
+         casCounter, incrCounter, incrCounter_,
+                                  
+         -- * Non-atomic operations
+         readCounter, readCounterForCAS,
+         writeCounter
+         )
+ where
+-- This module reexports the default implementation of atomic counters:
 import Data.Atomics.Counter.Unboxed
diff --git a/Data/Atomics/Counter/IORef.hs b/Data/Atomics/Counter/IORef.hs
--- a/Data/Atomics/Counter/IORef.hs
+++ b/Data/Atomics/Counter/IORef.hs
@@ -65,6 +65,6 @@
 writeCounter (AtomicCounter r) !new = writeIORef r new
 
 {-# INLINE casCounter #-}
--- | Compare and swap for the counter ADT.
+-- | Compare and swap for the counter ADT.  Similar behavior to `casIORef`.
 casCounter :: AtomicCounter -> CTicket -> Int -> IO (Bool, CTicket)
 casCounter (AtomicCounter r) tick !new = casIORef r tick new
diff --git a/Data/Atomics/Counter/Reference.hs b/Data/Atomics/Counter/Reference.hs
--- a/Data/Atomics/Counter/Reference.hs
+++ b/Data/Atomics/Counter/Reference.hs
@@ -64,31 +64,15 @@
 writeCounter (AtomicCounter r) !new = writeIORef r new
 
 {-# INLINE casCounter #-}
--- | Compare and swap for the counter ADT.
+-- | Compare and swap for the counter ADT.  Similar behavior to `casIORef`.
 casCounter :: AtomicCounter -> CTicket -> Int -> IO (Bool, CTicket)
 casCounter (AtomicCounter r) oldT !new =
-
-   -- This approach for faking it requires proper equality, it doesn't use pointer
-   -- equality at all.  That makes it not a true substitute but useful for some
-   -- debugging.
-   -- fakeCAS :: Eq a => IORef a -> Ticket a -> a -> IO (Bool,Ticket a)
-  
-  -- let old = peekTicket oldT
   let old = oldT in 
-  atomicModifyIORef r $ \val -> 
-{-
-    trace ("    DBG: INSIDE ATOMIC MODIFY, ptr eqs found/expected: " ++ 
-	   show [ptrEq val old, ptrEq val old, ptrEq val old] ++ 
-	   " ptr eq self: " ++ 
-	   show [ptrEq val val, ptrEq old old] ++
-	   " names: " ++ show (unsafeName old, unsafeName old, unsafeName val, unsafeName val)
-	  ) $
--}
+  atomicModifyIORef' r $ \val -> 
     if   (val == old)
-    then (new, (True, val))
+    then (new, (True, new))
     else (val, (False,val))
-    -- then (new, (True, unsafeCoerce# val))
-    -- else (val, (False,unsafeCoerce# val))
+
 
 {-
 {-# NOINLINE unsafeName #-}
diff --git a/Data/Atomics/Counter/Unboxed.hs b/Data/Atomics/Counter/Unboxed.hs
--- a/Data/Atomics/Counter/Unboxed.hs
+++ b/Data/Atomics/Counter/Unboxed.hs
@@ -1,18 +1,36 @@
 {-# LANGUAGE BangPatterns, MagicHash, UnboxedTuples, CPP #-}
 
+-- | This should be the most efficient implementation of atomic counters.
+--   You probably don't need the others!  (Except for testing/debugging.)
+
 module Data.Atomics.Counter.Unboxed
        (AtomicCounter, CTicket,
         newCounter, readCounterForCAS, readCounter, peekCTicket,
         writeCounter, casCounter, incrCounter, incrCounter_)
        where
 
-import GHC.Base
 import GHC.Ptr
 import Data.Atomics          (casByteArrayInt)
 -- import Data.Atomics.Internal (casIntArray#, fetchAddIntArray#)
 import Data.Atomics.Internal
+#if MIN_VERSION_base(4,7,0)
+import GHC.Base  hiding ((==#))
+import GHC.Prim hiding ((==#))
+import qualified GHC.PrimopWrappers as GPW
+#else
+import GHC.Base
 import GHC.Prim
+#endif
 
+
+-- GHC 7.8 changed some primops
+#if MIN_VERSION_base(4,7,0)
+(==#) :: Int# -> Int# -> Bool
+(==#) x y = case x GPW.==# y of { 0# -> False; _ -> True }
+#endif
+
+
+
 #ifndef __GLASGOW_HASKELL__
 #error "Unboxed Counter: this library is not portable to other Haskell's"
 #endif
@@ -22,15 +40,20 @@
 #define SIZEOF_HSINT  INT_SIZE_IN_BYTES
 #endif
 
+-- | The type of mutable atomic counters.
 data AtomicCounter = AtomicCounter (MutableByteArray# RealWorld)
+
+-- | You should not depend on this type.  It varies between different implementations
+-- of atomic counters.
 type CTicket = Int
+-- TODO: Could newtype this.
 
 -- | Create a new counter initialized to the given value.
 {-# INLINE newCounter #-}
 newCounter :: Int -> IO AtomicCounter
 newCounter n = do
   c <- newRawCounter
-  writeCounter c n
+  writeCounter c n -- Non-atomic is ok; it hasn't been released into the wild.
   return c
 
 -- | Create a new, uninitialized counter.
@@ -57,7 +80,8 @@
 
 {-# INLINE readCounterForCAS #-}
 -- | Just like the "Data.Atomics" CAS interface, this routine returns an opaque
--- ticket that can be used in CAS operations.
+-- ticket that can be used in CAS operations.  Except for the difference in return
+-- type, the semantics of this are the same as `readCounter`.
 readCounterForCAS :: AtomicCounter -> IO CTicket
 readCounterForCAS = readCounter
 
@@ -67,12 +91,18 @@
 peekCTicket !x = x
 
 {-# INLINE casCounter #-}
--- | Compare and swap for the counter ADT.
+-- | Compare and swap for the counter ADT.  Similar behavior to
+-- `Data.Atomics.casIORef`, in particular, in both success and failure cases it
+-- returns a ticket that you should use for the next attempt.  (That is, in the
+-- success case, it actually returns the new value that you provided as input, but in
+-- ticket form.)
 casCounter :: AtomicCounter -> CTicket -> Int -> IO (Bool, CTicket)
 -- casCounter (AtomicCounter barr) !old !new =
-casCounter (AtomicCounter mba#) (I# old#) (I# new#) = IO$ \s1# ->
+casCounter (AtomicCounter mba#) (I# old#) newBox@(I# new#) = IO$ \s1# ->
   let (# s2#, res# #) = casIntArray# mba# 0# old# new# s1# in
-  (# s2#, (res# ==# old#, I# res#) #)
+  case res# ==# old# of 
+    False -> (# s2#, (False, I# res# ) #) -- Failure
+    True  -> (# s2#, (True , newBox ) #) -- Success
 
 {-# INLINE sameCTicket #-}
 sameCTicket :: CTicket -> CTicket -> Bool
diff --git a/Data/Atomics/Internal.hs b/Data/Atomics/Internal.hs
--- a/Data/Atomics/Internal.hs
+++ b/Data/Atomics/Internal.hs
@@ -13,8 +13,8 @@
     casIntArray#, fetchAddIntArray#, 
 #endif
     readForCAS#, casMutVarTicketed#, casArrayTicketed#, 
-    Ticket,
-    stg_storeLoadBarrier#, stg_loadLoadBarrier#, stg_writeBarrier# )
+    Ticket
+   )
   where 
 
 import GHC.Base (Int(I#))
@@ -72,11 +72,16 @@
 -- that a thread observed a specific previous value of a mutable
 -- variable.  It is provided in lieu of the "old" value to
 -- compare-and-swap.
+--
+-- Design note: `Ticket`s exist to hide objects from the GHC compiler, which
+-- can normally perform many optimizations that change pointer equality.  A Ticket,
+-- on the other hand, is a first-class object that can be handled by the user,
+-- but will not have its pointer identity changed by compiler optimizations
+-- (but will of course, change addresses during garbage collection).
 type Ticket a = Any a
 -- If we allow tickets to be a pointer type, then the garbage collector will update
 -- the pointer when the object moves.
 
-
 instance Show (Ticket a) where
   show _ = "<CAS_ticket>"
 
@@ -112,18 +117,6 @@
   unsafeCoerce# casMutVar_TypeErased#
 #endif
 
---------------------------------------------------------------------------------
--- Memory barriers
---------------------------------------------------------------------------------
-
-foreign import prim "stg_store_load_barrier" stg_storeLoadBarrier#
-  :: State# RealWorld -> (# State# RealWorld, Int# #)
-
-foreign import prim "stg_load_load_barrier" stg_loadLoadBarrier#
-  :: State# RealWorld -> (# State# RealWorld, Int# #)
-
-foreign import prim "stg_write_barrier" stg_writeBarrier#
-  :: State# RealWorld -> (# State# RealWorld, Int# #)
 
 --------------------------------------------------------------------------------
 -- Type-erased versions that call the raw foreign primops:
diff --git a/atomic-primops.cabal b/atomic-primops.cabal
--- a/atomic-primops.cabal
+++ b/atomic-primops.cabal
@@ -1,5 +1,5 @@
 Name:                atomic-primops
-Version:             0.5
+Version:             0.5.0.2
 License:             BSD3
 License-file:        LICENSE
 Author:              Ryan Newton
@@ -22,6 +22,7 @@
 -- 0.4 -- Duplicate 'cas' as well as barriers.  Add fetchAdd on ByteArray, Counter.Unboxed.
 -- 0.4.1 -- Add advance support for GHC 7.8
 -- 0.5 -- Nix Data.Atomics.Counter.Foreign and the bits-atomic dependency.
+-- 0.5.0.2 -- IMPORTANT Bugfix release.
 
 Synopsis: A safe approach to CAS and other atomic ops in Haskell.
 
@@ -55,9 +56,9 @@
 
 
 Extra-Source-Files:  DEVLOG.md,
-                     testing/Test.hs, testing/test-atomic-primops.cabal,
-                     testing/Makefile, testing/CommonTesting.hs, testing/CounterTests.hs, testing/hello.hs
---                    Makefile, Test.hs, README.md
+                     testing/Test.hs, testing/test-atomic-primops.cabal, testing/ghci-test.hs
+                     testing/Makefile, testing/CommonTesting.hs, testing/CounterCommon.hs, testing/hello.hs
+                     testing/CounterReference.hs testing/CounterUnboxed.hs testing/CounterIORef.hs
 
 Flag debug
     Description: Enable extra internal checks.
@@ -94,7 +95,7 @@
   if impl(ghc < 7.7) {
      Include-Dirs:     cbits
      C-Sources:        cbits/primops.cmm
-     -- Duplicate RTS functionality: 
+     -- Duplicate RTS functionality for GHC 7.6:
      C-Sources:        cbits/RtsDup.c
   }
   CC-Options:       -Wall 
@@ -106,7 +107,7 @@
   -- }
 
   if flag(debug)
-    cpp-options: -DDEBUG_ATOMICS
+    cpp-options: -DDEBUG_ATOMICS 
 
 
 -- -- [2013.04.08] This isn't working presently:
diff --git a/cbits/RtsDup.c b/cbits/RtsDup.c
--- a/cbits/RtsDup.c
+++ b/cbits/RtsDup.c
@@ -3,28 +3,24 @@
 // NOTE: We only use this file for GHC < 7.8.
 // ============================================================
 
-// This file duplicates certain functionality from the GHC runtime system (SMP.h).
+// If I #include "stg/SMP.h", then in I get duplicated symbols.
+// Rather, instead this file duplicates certain functionality from the
+// GHC runtime system (SMP.h).
 
 #define THREADED_RTS
+#define WITHSMP
 #undef  KEEP_INLINES
 
-// Stg.h will pull in SMP.h:
-// #include "Stg.h"
-// Also having some problems with Regs.h.
-// This is probably too big a chunk to suck in.
-
 //--------------------------------------------------------------------------------
 // #define EXTERN_INLINE inline
 #define EXTERN_INLINE 
 
+// These are includes from the GHC implementation:
 #include "MachDeps.h"
 #include "stg/Types.h"
-
-// Force the GHC RTS code to provide the desired symbols:
-// #define IN_STGCRUN 1
+// Grab the HOST_ARCH from here:
+#include "ghcplatform.h"
 
-// If I pull this in I get duplicated symbols:
-// #include "stg/SMP.h"
 //--------------------------------------------------------------------------------
 
 /*
@@ -99,7 +95,6 @@
 // #define VOLATILE_LOAD(p) (*((StgVolatilePtr)(p)))
 
 
-
 /* 
  * CMPXCHG - the single-word atomic compare-and-exchange instruction.  Used 
  * in the STM implementation.
@@ -109,8 +104,8 @@
 {
 #if i386_HOST_ARCH || x86_64_HOST_ARCH
     __asm__ __volatile__ (
- 	  "lock\ncmpxchg %3,%1"
-          :"=a"(o), "=m" (*(volatile unsigned int *)p) 
+          "lock\ncmpxchg %3,%1"
+          :"=a"(o), "=m" (*(volatile unsigned int *)p)
           :"0" (o), "r" (n));
     return o;
 #elif powerpc_HOST_ARCH
@@ -173,7 +168,6 @@
 #error cas() unimplemented on this architecture
 #endif
 }
-
 
 
 // Copied from atomic_inc in the GHC RTS, except tweaked to allow
diff --git a/cbits/primops.cmm b/cbits/primops.cmm
--- a/cbits/primops.cmm
+++ b/cbits/primops.cmm
@@ -11,6 +11,7 @@
 #define WHICH_LLBARRIER DUP_load_load_barrier
 #define WHICH_WBARRIER  DUP_write_barrier
 
+// These versions are linked directly from the RTS:
 /* #define WHICH_CAS       cas */
 /* #define WHICH_SLBARRIER store_load_barrier */
 /* #define WHICH_LLBARRIER load_load_barrier */
@@ -38,7 +39,6 @@
 
     p = arr + SIZEOF_StgMutArrPtrs + WDS(ind);
     (h) = foreign "C" WHICH_CAS(p, old, new) [];
-    
     if (h != old) {
         // Failure, return what was there instead of 'old':
         RET_NP(1,h);
@@ -87,21 +87,22 @@
 stg_casMutVar2zh
  /* MutVar# s a -> Word# -> a -> State# s -> (# State#, Int#, a #) */
 {
-    W_ mv, old, new, h;
+    W_ mv, old, new, h, addr;
     // Calling convention: Up to 8 registers contain arguments.
     mv  = R1;
     old = R2;
     new = R3;
+    addr = mv + SIZEOF_StgHeader + OFFSET_StgMutVar_var;
 
     // The "cas" function from the C runtime abstracts over
-    // platform/architecture differences.  It returns the old value,
-    // which, if equal to "old", means success.
-    (h) = foreign "C" WHICH_CAS(mv + SIZEOF_StgHeader + OFFSET_StgMutVar_var,
-                          old, new) [];
+    // platform/architecture differences.  It returns the old value.
+    (h) = foreign "C" WHICH_CAS(addr, old, new) [];
     if (h != old) {
         // Failure:
-        RET_NP(1,h);
-    } else {
+        RET_NP(1, h);
+    }
+    else 
+    {
         // Success means a mutation and thus GC write barrier:
         if (GET_INFO(mv) == stg_MUT_VAR_CLEAN_info) {
            foreign "C" dirty_MUT_VAR(BaseReg "ptr", mv "ptr") [];
@@ -124,23 +125,4 @@
 }
 /* emitPrimOp [res] ReadMutVarOp [mutv] _ */
 /*    = stmtC (CmmAssign (CmmLocal res) (cmmLoadIndexW mutv fixedHdrSize gcWord)) */
-
-
-// This is already existing functionality in the RTS (SMP.h).  It
-// handles the complexity of architecture-portability.  We just need
-// to expose it here.
-stg_store_load_barrier {
-    foreign "C" WHICH_SLBARRIER();
-    RET_N(0);
-}
-
-stg_load_load_barrier {
-    foreign "C" WHICH_LLBARRIER();
-    RET_N(0);
-}
-
-stg_write_barrier {
-    foreign "C" WHICH_WBARRIER();
-    RET_N(0);
-}
 
diff --git a/testing/CommonTesting.hs b/testing/CommonTesting.hs
--- a/testing/CommonTesting.hs
+++ b/testing/CommonTesting.hs
@@ -1,5 +1,7 @@
 {-# LANGUAGE MagicHash, UnboxedTuples, BangPatterns, ScopedTypeVariables, NamedFieldPuns, CPP #-}
 
+-- Various utilities used during testing.
+
 module CommonTesting  where
 
 import Control.Monad
@@ -8,6 +10,7 @@
 import Data.Time.Clock
 import Text.Printf
 import GHC.IO (unsafePerformIO)
+import System.CPUTime
 import System.Mem.StableName (makeStableName, hashStableName)
 import System.Environment (getEnvironment)
 import System.IO        (stdout, stderr, hPutStrLn, hFlush)
@@ -57,7 +60,15 @@
                 | Sequence (Forkable a) (Forkable a) -- Sequential compositon, with barrier
 --                | Barrier Forkable
 
+-- | Grab a GC-invariant stable "address" for any value.
+{-# NOINLINE unsafeName #-}
+unsafeName :: a -> Int
+unsafeName x = unsafePerformIO $ do 
+   sn <- makeStableName x
+   return (hashStableName sn)
 
+
+-- | Measure realtime 
 timeit :: IO a -> IO a 
 timeit ioact = do 
    start <- getCurrentTime
@@ -66,14 +77,40 @@
    putStrLn$ "  Time elapsed: " ++ show (diffUTCTime end start)
    return res
 
-{-# NOINLINE unsafeName #-}
-unsafeName :: a -> Int
-unsafeName x = unsafePerformIO $ do 
-   sn <- makeStableName x
-   return (hashStableName sn)
 
+-- | Measure CPU time rather than realtime...
+cputime :: IO t -> IO t
+cputime a = do
+    start <- getCPUTime
+    v <- a
+    end   <- getCPUTime
+    let diff = (fromIntegral (end - start)) / (10^12)
+    printf "SELFTIMED: %0.3f sec\n" (diff :: Double)
+    return v
 
 
+-- | To make sure we get a simple loop...
+nTimes :: Int -> IO () -> IO ()
+-- nTimes :: Int -> IO a -> IO ()
+-- Note: starting out I would get 163Mb allocation for 10M sequential incrs (on unboxed).
+-- The problem was that the "Int" result from each incr was being allocated.
+-- Weird thing is that inlining nTimes reduces the allocation to 323Mb.
+-- But forcing it to take an (IO ()) gets rid of the allocation.
+-- Egad, wait, no, I have to NOT inline nTimes to get rid of the allocation!?!?
+-- Otherwise I'm still stuck with at least 163Mb of allocation.
+-- In fact... the allocation is still there even if we use incrCounter_ !!
+-- If we leave nTimes uninlined, we can get down to 3Mb allocation with either incrCounter or incrCounter_.
+-------------------------
+-- UPDATE:
+-- As per http://www.haskell.org/pipermail/glasgow-haskell-users/2011-June/020472.html
+--
+--  INLINE should not affect recursive functions.  But here it seems to have a
+--  deleterious effect!
+nTimes 0 !c = return ()
+nTimes !n !c = c >> nTimes (n-1) c
+
+
+
 ----------------------------------------------------------------------------------------------------
 -- DEBUGGING
 ----------------------------------------------------------------------------------------------------
@@ -94,7 +131,7 @@
 -- | How many elements or iterations should the test use?
 numElems :: Int
 numElems = case lookup "NUMELEMS" unsafeEnv of 
-             Nothing  -> 1000 * 1000 
+             Nothing  -> 1000 * 1000  -- A million by default.
              Just str -> warnUsing ("NUMELEMS = "++str) $ 
                          read str
 
@@ -122,3 +159,4 @@
   where
    loop !i | i == end  = return ()
 	   | otherwise = do fn i; loop (i+1)
+
diff --git a/testing/CounterCommon.hs b/testing/CounterCommon.hs
new file mode 100644
--- /dev/null
+++ b/testing/CounterCommon.hs
@@ -0,0 +1,139 @@
+
+-- Common tests to the different counter implementations.
+
+import Control.Monad
+import GHC.Conc
+import System.CPUTime
+import Test.Framework.Providers.HUnit (testCase)
+import Test.HUnit (Assertion, assertEqual, assertBool)
+import Text.Printf
+import Data.IORef  
+
+import Data.Atomics
+import CommonTesting (numElems, forkJoin, timeit, nTimes)
+
+--------------------------------------------------------------------------------
+-- Test the basics
+
+case_basic1 = do 
+  r <- C.newCounter 0
+  ret <- C.incrCounter 10 r
+  assertEqual "incrCounter returns the NEW value" 10 ret
+
+case_basic2 = do 
+  r <- C.newCounter 0
+  t <- C.readCounterForCAS r
+  (True,newt) <- C.casCounter r t 10
+  assertEqual "casCounter returns new val/ticket on success" 10 (C.peekCTicket newt)
+
+case_basic3 = do 
+  r <- C.newCounter 0
+  t <- C.readCounterForCAS r
+  _ <- C.incrCounter 1 r
+  (False,oldt) <- C.casCounter r t 10
+  assertEqual "casCounter returns read val on failure" 1 (C.peekCTicket oldt)
+
+case_basic4 = do 
+  let tries = numElems `quot` 100
+  r <- C.newCounter 0
+  nTimes tries $ do
+    t <- C.readCounterForCAS r
+    (True,_) <- C.casCounter r t (C.peekCTicket t + 1)
+    return ()
+  cnt <- C.readCounter r
+  assertEqual "Every CAS should succeed on one thread" tries cnt 
+
+--------------------------------------------------------------------------------
+-- Repeated increments
+
+incrloop tries = do r <- C.newCounter 0; nTimes tries $ void$ C.incrCounter 1 r
+                    C.readCounter r
+case_incrloop = do 
+   cnt <- incrloop default_seq_tries
+   assertEqual "incrloop sum" default_seq_tries cnt
+
+-- | Here we do a loop to test the unboxing of results from incrCounter:
+--   As of now [2013.07.19], it is successfully unboxing the results 
+--   for Data.Atomics.Counter.Unboxed.
+incrloop4B tries = do
+  putStrLn " [incrloop4B] A test where we use the result of each incr."
+  r <- C.newCounter 1
+  loop r tries 1
+ where
+   loop :: C.AtomicCounter -> Int -> Int -> IO ()
+   loop r 0 _ = do v <- C.readCounter r
+                   putStrLn$"Final value: "++show v
+                   return ()
+   loop r tries last = do
+     n <- C.incrCounter last r
+     if n == 2
+       then loop r (tries-1) 2
+       else loop r (tries-1) 1
+
+-- | Here we let the counter overflow, which seems to be causing problems.
+overflowTest tries = do
+  putStrLn " [incrloop4B] A test where we use the result of each incr."
+  r <- C.newCounter 1
+  loop r tries 1
+ where
+   loop :: C.AtomicCounter -> Int -> Int -> IO ()
+   loop r 0 _ = do v <- C.readCounter r
+                   putStrLn$"Final value: "++show v
+                   return ()
+   loop r tries last = do
+     putStrLn$ " [incrloop4B] Looping with tries left "++show tries 
+     n <- C.incrCounter last r
+     -- This is HANGING afer passing 2,147,483,648.  (using Unboxed)
+     -- Is there some defect wrt overflow?
+     putStrLn$ " [incrloop4B] Done incr, received "++show n
+     loop r (tries-1) n
+
+--------------------------------------------------------------------------------
+-- Parallel repeated increments
+
+
+{-# INLINE parIncrloop #-} 
+parIncrloop new incr iters = do
+  numcap <- getNumCapabilities
+  let (each,left) = iters `quotRem` numcap
+  putStrLn$ "Concurrently incrementing counter from all "++show numcap++" threads, incrs per thread: "++show each
+  r <- new 0
+  forkJoin numcap $ \ ix -> do
+    let mine = if ix==0 then each+left else each
+    nTimes mine $ void $ incr 1 r
+  C.readCounter r
+
+case_parincrloop = do 
+  cnt <- parIncrloop C.newCounter C.incrCounter default_conc_tries
+  assertEqual "incrloop sum" default_conc_tries cnt
+
+-- | Use CAS instead of the real incr so we can compare the overhead.
+case_parincrloop_wCAS = do 
+  cnt <- parIncrloop C.newCounter fakeIncr default_conc_tries
+  assertEqual "incrloop sum" default_conc_tries cnt
+ where
+  fakeIncr delt r = do tick <- C.readCounterForCAS r
+                       loop r delt tick
+  loop r delt tick = do x <- C.casCounter r tick (C.peekCTicket tick + delt)
+                        case x of 
+                          (True, newtick) -> return (C.peekCTicket newtick)
+                          (False,newtick) -> loop r delt newtick
+                   
+
+--------------------------------------------------------------------------------
+
+tests = 
+ [
+   testCase (name++"basic1_incrCounter") $ case_basic1
+ , testCase (name++"basic2_casCounter") $ case_basic2
+ , testCase (name++"basic3_casCounter") $ case_basic3
+ , testCase (name++"basic4_casCounter") $ case_basic4
+   ----------------------------------------
+ , testCase (name++"_single_thread_repeat_incr") $ timeit case_incrloop
+ , testCase (name++"_incr_with_result_feedback") $ timeit (incrloop4B default_seq_tries)
+   ----------------------------------------
+
+   -- Parallel versions:
+ , testCase (name++"_concurrent_repeat_incr") $ void$ timeit case_parincrloop
+ , testCase (name++"_concurrent_repeat_incrCAS") $ void$ timeit case_parincrloop_wCAS
+ ]
diff --git a/testing/CounterIORef.hs b/testing/CounterIORef.hs
new file mode 100644
--- /dev/null
+++ b/testing/CounterIORef.hs
@@ -0,0 +1,11 @@
+{-# LANGUAGE CPP, BangPatterns #-}
+module CounterIORef (tests) where
+import qualified Data.Atomics.Counter.IORef as C
+
+#include "CounterCommon.hs"
+
+name = "IORef"
+
+default_seq_tries  = 10 * numElems
+-- Things are MUCH slower with contention:
+default_conc_tries = numElems
diff --git a/testing/CounterReference.hs b/testing/CounterReference.hs
new file mode 100644
--- /dev/null
+++ b/testing/CounterReference.hs
@@ -0,0 +1,13 @@
+{-# LANGUAGE CPP, BangPatterns #-}
+module CounterReference (tests) where
+import qualified Data.Atomics.Counter.Reference as C
+
+#include "CounterCommon.hs"
+
+name = "Reference"
+
+-- This version is much slower than some of the others:
+default_seq_tries  = 10 * base 
+default_conc_tries = base
+
+base = numElems `quot` 15
diff --git a/testing/CounterTests.hs b/testing/CounterTests.hs
deleted file mode 100644
--- a/testing/CounterTests.hs
+++ /dev/null
@@ -1,184 +0,0 @@
-{-# LANGUAGE BangPatterns #-}
-
--- | Test the counter implementation alternatives.
-
-module CounterTests where
-
-import Control.Monad
-import GHC.Conc
-import System.CPUTime
-import Test.Framework.Providers.HUnit (testCase)
-import Text.Printf
-import Data.IORef  
-
-import Data.Atomics
-import qualified Data.Atomics.Counter.Reference as C1 
-import qualified Data.Atomics.Counter.IORef     as C2
-import qualified Data.Atomics.Counter.Foreign   as C3
-import qualified Data.Atomics.Counter.Unboxed   as C4
-
-import CommonTesting (numElems, forkJoin, timeit)
-
---------------------------------------------------------------------------------
-
--- {-# INLINE nTimes #-}
--- | To make sure we get a simple loop...
-nTimes :: Int -> IO () -> IO ()
--- nTimes :: Int -> IO a -> IO ()
--- Note: starting out I would get 163Mb allocation for 10M sequential incrs (on unboxed).
--- The problem was that the "Int" result from each incr was being allocated.
--- Weird thing is that inlining nTimes reduces the allocation to 323Mb.
--- But forcing it to take an (IO ()) gets rid of the allocation.
--- Egad, wait, no, I have to NOT inline nTimes to get rid of the allocation!?!?
--- Otherwise I'm still stuck with at least 163Mb of allocation.
--- In fact... the allocation is still there even if we use incrCounter_ !!
--- If we leave nTimes uninlined, we can get down to 3Mb allocation with either incrCounter or incrCounter_.
--------------------------
--- UPDATE:
--- As per http://www.haskell.org/pipermail/glasgow-haskell-users/2011-June/020472.html
---
---  INLINE should not affect recursive functions.  But here it seems to have a
---  deleterious effect!
-nTimes 0 !c = return ()
-nTimes !n !c = c >> nTimes (n-1) c
-
--- {-# INLINE vd #-}
--- vd = void
--- vd x = x
-
-cputime :: IO t -> IO t
-cputime a = do
-    start <- getCPUTime
-    v <- a
-    end   <- getCPUTime
-    let diff = (fromIntegral (end - start)) / (10^12)
-    printf "SELFTIMED: %0.3f sec\n" (diff :: Double)
-    return v
-
-normal tries = do
-  r <- newIORef True
-  nTimes tries $ do
-    x <- readIORef r
-    writeIORef r $! not x
-
--- This is not allocating per-iteration currently, which is rather amazing given what
--- casIORef returns.
-casBased tries = do    
-  r <- newIORef True
-  nTimes tries $ do
-    t <- readForCAS r
-    casIORef r t (not $ peekTicket t)
-    return ()
-  readIORef r
-
-normalIncr tries = do
-  r <- newIORef 0
-  nTimes tries $ do
-    x <- readIORef r
-    writeIORef r $! 1 + x
-  readIORef r
-
-casBasedIncr tries = do    
-  r <- newIORef 0
-  nTimes tries $ do
-    t <- readForCAS r
-    casIORef r t $! (1 + peekTicket t)
-    return ()
-  readIORef r
-
-incrloop1 tries = do r <- C1.newCounter 0; nTimes tries $ void$ C1.incrCounter 1 r
-incrloop2 tries = do r <- C2.newCounter 0; nTimes tries $ void$ C2.incrCounter 1 r
-incrloop3 tries = do r <- C3.newCounter 0; nTimes tries $ void$ C3.incrCounter 1 r
-incrloop4 tries = do r <- C4.newCounter 0; nTimes tries $ C4.incrCounter_ 1 r
-
--- | Here we do a loop to test the unboxing of results from incrCounter:
---   As of now [2013.07.19], it is successfully unboxing the results.
-incrloop4B tries = do
-  putStrLn " [incrloop4B] A test where we use the result of each incr."
-  r <- C4.newCounter 1
-  loop r tries 1
- where
-   loop :: C4.AtomicCounter -> Int -> Int -> IO ()
-   loop r 0 _ = do v <- C4.readCounter r
-                   putStrLn$"Final value: "++show v
-                   return ()
-   loop r tries last = do
-     n <- C4.incrCounter last r
-     if n == 2
-       then loop r (tries-1) 2
-       else loop r (tries-1) 1
-
--- | Here we let the counter overflow, which seems to be causing problems.
-overflowTest tries = do
-  putStrLn " [incrloop4B] A test where we use the result of each incr."
-  r <- C4.newCounter 1
-  loop r tries 1
- where
-   loop :: C4.AtomicCounter -> Int -> Int -> IO ()
-   loop r 0 _ = do v <- C4.readCounter r
-                   putStrLn$"Final value: "++show v
-                   return ()
-   loop r tries last = do
-     putStrLn$ " [incrloop4B] Looping with tries left "++show tries 
-     n <- C4.incrCounter last r
-     -- This is HANGING afer passing 2,147,483,648.
-     -- Is there some defect wrt overflow?
-     putStrLn$ " [incrloop4B] Done incr, received "++show n
-     loop r (tries-1) n
-
-
-
-{-# INLINE parIncrloop #-} 
-parIncrloop new incr iters = do
-  numcap <- getNumCapabilities
-  let each = iters `quot` numcap
-  putStrLn$ "Concurrently incrementing counter from all "++show numcap++" threads, incrs per thread: "++show each
-  r <- new 0
-  forkJoin numcap $ \ _ ->    
-    nTimes each $ void $ incr 1 r
-  return r
-
-parIncrloop1 = parIncrloop C1.newCounter C1.incrCounter
-parIncrloop2 = parIncrloop C2.newCounter C2.incrCounter
-parIncrloop3 = parIncrloop C3.newCounter C3.incrCounter
-parIncrloop4 = parIncrloop C4.newCounter C4.incrCounter
-
---------------------------------------------------------------------------------
-
-default_seq_tries  = 10 * numElems
--- Things are MUCH slower with contention:
-default_conc_tries = numElems
-
-counterTests = 
- [
-   ----------------------------------------
-   testCase "RAW_single_thread_repeat_flip" $ do 
-     putStrLn "Timing readIORef/writeIORef on one thread"
-     timeit (normal default_seq_tries)   
- , testCase "CAS_single_thread_repeat_flip" $ do 
-     putStrLn "Timing CAS boolean flips on one thread without retries"
-     fin <- timeit (casBased default_seq_tries)
-     putStrLn$"Final value: "++show fin
-   ----------------------------------------
- , testCase "RAW_single_thread_repeat_incr" $ do 
-     putStrLn "Timing readIORef/writeIORef on one thread"
-     fin <- timeit (normalIncr default_seq_tries)
-     putStrLn$"Final value: "++show fin      
- , testCase "CAS_single_thread_repeat_incr" $ do 
-     putStrLn "Timing CAS increments on one thread without retries"
-     fin <- timeit (casBasedIncr default_seq_tries)
-     putStrLn$"Final value: "++show fin 
-   ----------------------------------------
- , testCase "CounterReference_single_thread_repeat_incr" $ timeit (incrloop1 default_seq_tries)
- , testCase "CounterIORef_single_thread_repeat_incr"     $ timeit (incrloop2 default_seq_tries)   
- , testCase "CounterForeign_single_thread_repeat_incr"   $ timeit (incrloop3 default_seq_tries)
- , testCase "CounterUnboxed_single_thread_repeat_incr"   $ timeit (incrloop4 default_seq_tries)
- , testCase "CounterUnboxed_incr_with_result_feedback"   $ timeit (incrloop4B default_seq_tries)
-   ----------------------------------------
-
-   -- Parallel versions:
- , testCase "CounterReference_concurrent_repeat_incr" $ void$ timeit (parIncrloop1 default_conc_tries)
- , testCase "CounterIORef_concurrent_repeat_incr"     $ void$ timeit (parIncrloop2 default_conc_tries)
- , testCase "CounterForeign_concurrent_repeat_incr"   $ void$ timeit (parIncrloop3 default_conc_tries)
- , testCase "CounterUnboxed_concurrent_repeat_incr"   $ void$ timeit (parIncrloop4 default_conc_tries)
- ]
diff --git a/testing/CounterUnboxed.hs b/testing/CounterUnboxed.hs
new file mode 100644
--- /dev/null
+++ b/testing/CounterUnboxed.hs
@@ -0,0 +1,11 @@
+{-# LANGUAGE CPP, BangPatterns #-}
+module CounterUnboxed (tests) where
+import qualified Data.Atomics.Counter.Unboxed as C
+
+#include "CounterCommon.hs"
+
+name = "Unboxed"
+
+default_seq_tries  = 10 * numElems
+-- Things are MUCH slower with contention:
+default_conc_tries = numElems
diff --git a/testing/Test.hs b/testing/Test.hs
--- a/testing/Test.hs
+++ b/testing/Test.hs
@@ -7,35 +7,37 @@
 -- import Control.Monad.ST (stToIO)
 import Control.Exception (evaluate)
 import Control.Concurrent.MVar
-import GHC.Conc
 import Data.IORef (modifyIORef')
 import Data.Int
 import Data.Time.Clock
+import Data.Primitive.Array
+import Data.Word
+import qualified Data.Set as S
+import Data.List ((\\))
 import Text.Printf
+import GHC.Conc
 import GHC.STRef
 import GHC.IORef
 import GHC.Stats (getGCStats, GCStats(..))
-import Data.Primitive.Array
-import Data.Word
-import qualified Data.Set as S
+import GHC.IO (unsafePerformIO)
 import System.Random (randomIO, randomRIO)
-
-import Data.Atomics as A
-import Data.Atomics (casArrayElem, readArrayElem)
-
 import Test.HUnit (Assertion, assertEqual, assertBool)
 import Test.Framework  (Test, defaultMain, testGroup)
 import Test.Framework.Providers.HUnit (testCase)
-
-import GHC.IO (unsafePerformIO)
 import System.Mem (performGC)
-import System.Mem.StableName (makeStableName, hashStableName)
+import System.Mem.StableName (makeStableName, hashStableName, StableName)
 import System.Environment (getEnvironment)
 import System.IO        (stdout, stderr, hPutStrLn, hFlush)
 import Debug.Trace      (trace)
 
+----------------------------------------
+import Data.Atomics as A
+import Data.Atomics (casArrayElem, readArrayElem)
+
 import CommonTesting 
-import CounterTests (counterTests)
+import qualified CounterReference 
+import qualified CounterUnboxed
+import qualified CounterIORef
 
 ------------------------------------------------------------------------
 
@@ -54,7 +56,7 @@
        -- It does 248 test cases and takes 55s at -N16...
        -- numcap <- getNumProcessors
        let numcap = 4
-       setNumCapabilities numcap
+       when (numCapabilities /= numcap) $ setNumCapabilities numcap
        
        defaultMain $ 
          [ testCase "casTicket1"              case_casTicket1
@@ -87,8 +89,11 @@
                       [1, numcap `quot` 2, numcap, 2*numcap]
          , size    <- [1, 10, 100]
          , iters   <- [10000]]
-         ++ counterTests
 
+         ++ CounterReference.tests
+         ++ CounterUnboxed.tests
+         ++ CounterIORef.tests
+
 setify :: [Int] -> [Int]
 setify = S.toList . S.fromList
 
@@ -247,18 +252,38 @@
 
 
 -- [2013.07.19] I just saw an isolated failure of this one:
+-- [2014.01.31] I saw another failure of this on -N1 (0e0d64c3d7), observing 118 sum.
 case_n_threads_mutate :: Assertion
 case_n_threads_mutate = do
   dbgPrint 1$ "   Creating 120 threads and having each increment a counter value."
   counter <- newIORef (0::Int)
-  let work :: IORef Int -> IO ()
-      work = (\counter -> do
-                        tick <- A.readForCAS(counter)
-                        (b,_) <- A.casIORef counter tick (peekTicket tick + 1)
-                        unless b $ work counter)
-  arr <- forkJoin 120 (\_ -> work counter) 
+--  let work :: Int -> IORef Int -> IO (Int,StableName Int,Int,StableName Int,Int)
+  let work :: Int -> IORef Int -> IO (Int,Int,Int,Int,Int)
+      work ix counter = do
+        tick <- A.readForCAS(counter)
+        let nxt = peekTicket tick + 1
+        (b,was) <- A.casIORef counter tick nxt
+        if b then do 
+          putStr $ show (peekTicket was) ++ "_"
+          assertEqual "Check that the value written was the one we put in." nxt (peekTicket was)
+          return (ix, unsafeName tick, unsafeName was, peekTicket tick, nxt)
+         else do 
+          when (peekTicket was == peekTicket tick) $ 
+             putStrLn ("(Spoofed by boxing, old val was indeed "++show was++")")
+          putStr "!"
+--          putStrLn $ "("++ show ix ++ ": Fail when putting "++show nxt
+--                     ++", was already "++show (peekTicket was) ++")"
+          work ix counter
+  arr <- forkJoin 120 (\i -> work i counter) 
   ans <- readIORef counter
-  assertBool "Did the sum end up equal to 120?" (ans == 120)
+
+  let dups = [ n | (_,_,_,_,n) <- arr] \\ [1..120]
+  putStrLn $ "\n Duplicates were "++show dups++", Array:"
+  print arr
+
+  -- assertBool "Did the 120 threads CASing yield a valid sum" (1 <= ans && ans <= 120)
+  -- The retry loop should ensure that each thread increments ONCE:
+  assertEqual "Did the 120 threads CASing all succeed?" 120 ans
 
 -- | Just make sure these link and run properly:
 case_run_barriers :: Assertion
diff --git a/testing/ghci-test.hs b/testing/ghci-test.hs
new file mode 100644
--- /dev/null
+++ b/testing/ghci-test.hs
@@ -0,0 +1,20 @@
+{-# LANGUAGE TemplateHaskell #-}
+
+-- | Test the invocation of the GHCi bytecode intepreter with atomic-primops.
+
+module Main where
+
+import Data.Atomics -- import needed to test whether ghci linking error occurs
+import TemplateHaskellSplices (tmap)
+import Test.Framework  (defaultMain)
+import Test.Framework.Providers.HUnit (testCase)
+
+main :: IO ()
+main = defaultMain
+ [
+   ----------------------------------------
+   testCase "Template_Haskell_invocation" $ do
+     putStrLn "Attempting Template Haskell implementation of map operation"
+     print $ $(tmap 3 4) (+ 1) (1,2,3,4) -- comment out for compilation to succeed
+   ----------------------------------------
+ ]
diff --git a/testing/test-atomic-primops.cabal b/testing/test-atomic-primops.cabal
--- a/testing/test-atomic-primops.cabal
+++ b/testing/test-atomic-primops.cabal
@@ -2,7 +2,7 @@
 -- Trying a completely separate .cabal for testing.
 
 Name:                test-atomic-primops
-Version:             0.1.0.0
+Version:             0.5.0.2
 Build-type:          Simple
 Cabal-version:       >=1.8
 
@@ -27,25 +27,33 @@
        ghc-options: -O2 -funbox-strict-fields
     if flag(threaded)
        ghc-options: -threaded 
+
+    -- Set it to always run with some parallelism.
+    ghc-options: -rtsopts -with-rtsopts=-N4
        
-    build-depends: base, ghc-prim, primitive, containers, random, atomic-primops >= 0.4,
+    build-depends: base, ghc-prim, primitive, containers, random, atomic-primops >= 0.5,
                    -- For Testing:
                    time, HUnit, test-framework, test-framework-hunit
 
-    -- Debugging generated code:
---    ghc-options: -keep-tmp-files -dsuppress-module-prefixes -ddump-to-file -ddump-core-stats -ddump-simpl-stats -dcore-lint -dcmm-lint
---    ghc-options: -ddump-ds -ddump-simpl -ddump-stg -ddump-asm -ddump-bcos -ddump-cmm -ddump-opt-cmm -ddump-inlinings
+    -- Optional: Debugging generated code:
+    --    ghc-options: -keep-tmp-files -dsuppress-module-prefixes -ddump-to-file -ddump-core-stats -ddump-simpl-stats -dcore-lint -dcmm-lint
+    --    ghc-options: -ddump-ds -ddump-simpl -ddump-stg -ddump-asm -ddump-bcos -ddump-cmm -ddump-opt-cmm -ddump-inlinings
 
+-- Cabal can get confused if there is no executable or library... so here's a dummy executable.
+-- Also it provides a good test of compile/link issues, apart from everything else.
 Executable hello-world-atomic-primops
   main-is: hello.hs
   build-depends: base >= 4.5, atomic-primops
 
-Executable template-haskell-atomic-primops
+-- This is separated out, because a bug in GHC 7.6 make this fail on Linux.
+Test-suite template-haskell-atomic-primops
+  type:       exitcode-stdio-1.0
   main-is: ghci-test.hs
-  if flag(withTH)
+  if flag(withTH) {
     Buildable: True
-  else
+    build-depends: base >= 4.5, atomic-primops >= 0.5, template-haskell,
+                   -- For Testing:
+                   test-framework, test-framework-hunit
+  } else {
     Buildable: False
-  build-depends: base >= 4.5, atomic-primops >= 0.4, template-haskell,
-                 -- For Testing:
-                 test-framework, test-framework-hunit
+  }
