diff --git a/Data/Mutex.hs b/Data/Mutex.hs
deleted file mode 100644
--- a/Data/Mutex.hs
+++ /dev/null
@@ -1,29 +0,0 @@
-module Data.Mutex
-    ( Mutex
-    , new
-    , lock
-    , unlock
-    ) where
-
-import Data.Int (Int64)
-import Foreign.ForeignPtr (ForeignPtr, mallocForeignPtr, withForeignPtr)
-import Foreign.Ptr (Ptr)
-import Foreign.Storable (poke)
-
-newtype Mutex = M { unM :: ForeignPtr Int64 }
-
-new :: IO Mutex
-new = do
-    fp <- mallocForeignPtr
-    withForeignPtr fp $ \ p -> poke p 0
-    return $ M fp
-
-lock :: Mutex -> IO ()
-lock m = withForeignPtr (unM m) cLock
-
-foreign import ccall unsafe "hs_lock" cLock :: Ptr Int64 -> IO ()
-
-unlock :: Mutex -> IO ()
-unlock m = withForeignPtr (unM m) cUnlock
-
-foreign import ccall unsafe "hs_unlock" cUnlock :: Ptr Int64 -> IO ()
diff --git a/System/Metrics/Distribution.hsc b/System/Metrics/Distribution.hsc
--- a/System/Metrics/Distribution.hsc
+++ b/System/Metrics/Distribution.hsc
@@ -37,7 +37,6 @@
 import Prelude hiding (max, min, read, sum)
 
 import Data.Array
-import qualified Data.Mutex as Mutex
 import System.Metrics.ThreadId
 
 -- | An metric for tracking events.
@@ -45,17 +44,8 @@
 
 data Stripe = Stripe
     { stripeFp    :: !(ForeignPtr CDistrib)
-    , stripeMutex :: !Mutex.Mutex
     }
 
--- | Perform action with lock held. Not exception safe.
-withMutex :: Mutex.Mutex -> IO a -> IO a
-withMutex lock m = do
-    Mutex.lock lock
-    a <- m
-    Mutex.unlock lock
-    return a
-
 data CDistrib = CDistrib
     { cCount      :: !Int64
     , cMean       :: !Double
@@ -63,6 +53,7 @@
     , cSum        :: !Double
     , cMin        :: !Double
     , cMax        :: !Double
+    , cLock       :: !Int64  -- ^ 0 - unlocked, 1 - locked
     }
 
 instance Storable CDistrib where
@@ -76,6 +67,7 @@
         cSum <- (#peek struct distrib, sum) p
         cMin <- (#peek struct distrib, min) p
         cMax <- (#peek struct distrib, max) p
+        cLock <- (#peek struct distrib, lock) p
         return $! CDistrib
             { cCount      = cCount
             , cMean       = cMean
@@ -83,6 +75,7 @@
             , cSum        = cSum
             , cMin        = cMin
             , cMax        = cMax
+            , cLock       = cLock
             }
 
     poke p CDistrib{..} = do
@@ -92,20 +85,27 @@
         (#poke struct distrib, sum) p cSum
         (#poke struct distrib, min) p cMin
         (#poke struct distrib, max) p cMax
+        (#poke struct distrib, lock) p cLock
 
 newCDistrib :: IO (ForeignPtr CDistrib)
 newCDistrib = do
     fp <- mallocForeignPtr
-    withForeignPtr fp $ \ p -> poke p $ CDistrib 0 0.0 0.0 0.0 0.0 0.0
+    withForeignPtr fp $ \ p -> poke p $ CDistrib
+        { cCount      = 0
+        , cMean       = 0.0
+        , cSumSqDelta = 0.0
+        , cSum        = 0.0
+        , cMin        = 0.0
+        , cMax        = 0.0
+        , cLock       = 0
+        }
     return fp
 
 newStripe :: IO Stripe
 newStripe = do
     fp <- newCDistrib
-    mutex <- Mutex.new
     return $! Stripe
         { stripeFp    = fp
-        , stripeMutex = mutex
         }
 
 -- | Number of lock stripes. Should be greater or equal to the number
@@ -139,7 +139,7 @@
 addN distrib val n = do
     stripe <- myStripe distrib
     withForeignPtr (stripeFp stripe) $ \ p ->
-        withMutex (stripeMutex stripe) $ cDistribAddN p val n
+        cDistribAddN p val n
 
 foreign import ccall unsafe "hs_distrib_combine" combine
     :: Ptr CDistrib -> Ptr CDistrib -> IO ()
@@ -151,7 +151,6 @@
     CDistrib{..} <- withForeignPtr result $ \ resultp -> do
         forM_ (toList $ unD distrib) $ \ stripe ->
             withForeignPtr (stripeFp stripe) $ \ p ->
-            withMutex (stripeMutex stripe) $
             combine p resultp
         peek resultp
     return $! Stats
diff --git a/cbits/distrib.c b/cbits/distrib.c
--- a/cbits/distrib.c
+++ b/cbits/distrib.c
@@ -1,9 +1,18 @@
 #include "HsFFI.h"
 #include "distrib.h"
 
+static void hs_lock(volatile StgInt64* lock) {
+  while(!__sync_bool_compare_and_swap(lock, 0, 1));
+}
+
+static void hs_unlock(volatile StgInt64* lock) {
+  *lock = 0;
+}
+
 // Mean and variance are computed according to
 // http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance#Online_algorithm
 void hs_distrib_add_n(struct distrib* distrib, StgDouble val, StgInt64 n) {
+  hs_lock(&distrib->lock);
   const StgInt64 count = distrib->count + n;
   const StgDouble delta = val - distrib->mean;
   const StgDouble mean = distrib->mean + n * delta / count;
@@ -14,10 +23,12 @@
   distrib->sum += val;
   distrib->min = val < distrib->min ? val : distrib->min;
   distrib->max = val > distrib->max ? val : distrib->max;
+  hs_unlock(&distrib->lock);
 }
 
 // http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance#Parallel_algorithm
-void hs_distrib_combine(const struct distrib* b, struct distrib* a) {
+void hs_distrib_combine(struct distrib* b, struct distrib* a) {
+  hs_lock(&b->lock);
   const StgInt64 count = a->count + b->count;
   const StgDouble delta = b->mean - a->mean;
   const StgDouble mean = (a->count * a->mean + b->count * b->mean) / count;
@@ -29,4 +40,5 @@
   a->sum = a->sum + b->sum;
   a->min = b->min < a->min ? b->min : a->min;
   a->max = b->max > a->max ? b->max : a->max;
+  hs_unlock(&b->lock);
 }
diff --git a/cbits/distrib.h b/cbits/distrib.h
--- a/cbits/distrib.h
+++ b/cbits/distrib.h
@@ -7,8 +7,14 @@
   StgDouble sum;
   StgDouble min;
   StgDouble max;
+  volatile StgInt64 lock;
 };
 
 void hs_distrib_add_n(struct distrib* distrib, StgDouble val, StgInt64 n);
 
-void hs_distrib_combine(const struct distrib* b, struct distrib* a);
+/*
+ * Combine 'b' with 'a', writing the result in 'a'. Takes the lock of
+ * 'b' while combining, but doesn't otherwise modify 'b'. 'a' is
+ * assumed to not be used concurrently.
+ */
+void hs_distrib_combine(struct distrib* b, struct distrib* a);
diff --git a/cbits/mutex.c b/cbits/mutex.c
deleted file mode 100644
--- a/cbits/mutex.c
+++ /dev/null
@@ -1,9 +0,0 @@
-#include "HsFFI.h"
-
-void hs_lock(volatile StgInt64* lock) {
-  while(!__sync_bool_compare_and_swap(lock, 0, 1));
-}
-
-void hs_unlock(volatile StgInt64* lock) {
-  *lock = 0;
-}
diff --git a/ekg-core.cabal b/ekg-core.cabal
--- a/ekg-core.cabal
+++ b/ekg-core.cabal
@@ -1,5 +1,5 @@
 name:                ekg-core
-version:             0.1.0.0
+version:             0.1.0.1
 synopsis:            Tracking of system metrics
 description:
   This library lets you defined and track system metrics.
@@ -25,7 +25,6 @@
   other-modules:
     Data.Array
     Data.Atomic
-    Data.Mutex
     System.Metrics.ThreadId
 
   build-depends:
@@ -41,7 +40,7 @@
   includes: distrib.h
   install-includes: distrib.h
   include-dirs: cbits
-  c-sources: cbits/atomic.c cbits/distrib.c cbits/mutex.c
+  c-sources: cbits/atomic.c cbits/distrib.c
 
 benchmark counter
   main-is: Counter.hs
