[cairo-commit] 4 commits - build/aclocal.cairo.m4 src/cairo-atomic.c src/cairo-atomic-private.h src/cairo.c src/cairo-freed-pool-private.h src/cairo-image-surface.c src/cairo-reference-count-private.h src/drm

Andrea Canciani ranma42 at kemper.freedesktop.org
Thu Apr 29 01:54:04 PDT 2010


 build/aclocal.cairo.m4              |   10 +++
 src/cairo-atomic-private.h          |  104 +++++++++++++++++++++++++++++++-----
 src/cairo-atomic.c                  |   12 ----
 src/cairo-freed-pool-private.h      |   10 ++-
 src/cairo-image-surface.c           |    6 +-
 src/cairo-reference-count-private.h |    1 
 src/cairo.c                         |    4 -
 src/drm/cairo-drm.c                 |    2 
 8 files changed, 116 insertions(+), 33 deletions(-)

New commits:
commit 248af38b3efa3f96225eea43f4ba5b94baff34a6
Author: Andrea Canciani <ranma42 at gmail.com>
Date:   Wed Apr 28 17:23:47 2010 +0200

    atomic: Add MacOSX atomic implementation
    
    Enable atomic operation on MacOS X, using the functions provided by
    libkern/OSAtomic.h
    
    Reviewed-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/build/aclocal.cairo.m4 b/build/aclocal.cairo.m4
index 482763e..f271ccf 100644
--- a/build/aclocal.cairo.m4
+++ b/build/aclocal.cairo.m4
@@ -174,6 +174,11 @@ int atomic_cmpxchg(int i, int j, int k) { return __sync_val_compare_and_swap (&i
 			AC_CHECK_HEADER([atomic_ops.h],
 					cairo_cv_atomic_primitives="libatomic-ops")
 		fi
+
+		if test "x$cairo_cv_atomic_primitives" = "xnone"; then
+			AC_CHECK_HEADER([libkern/OSAtomic.h],
+					cairo_cv_atomic_primitives="OSAtomic")
+		fi
 	])
 	if test "x$cairo_cv_atomic_primitives" = xIntel; then
 		AC_DEFINE(HAVE_INTEL_ATOMIC_PRIMITIVES, 1,
@@ -184,6 +189,11 @@ int atomic_cmpxchg(int i, int j, int k) { return __sync_val_compare_and_swap (&i
 		AC_DEFINE(HAVE_LIB_ATOMIC_OPS, 1,
 			  [Enable if you have libatomic-ops-dev installed])
 	fi
+
+	if test "x$cairo_cv_atomic_primitives" = xOSAtomic; then
+		AC_DEFINE(HAVE_OS_ATOMIC_OPS, 1,
+			  [Enable if you have MacOS X atomic operations])
+	fi
 ])
 
 dnl Usage:
diff --git a/src/cairo-atomic-private.h b/src/cairo-atomic-private.h
index 7dd0254..4fcb188 100644
--- a/src/cairo-atomic-private.h
+++ b/src/cairo-atomic-private.h
@@ -111,6 +111,36 @@ typedef unsigned long long cairo_atomic_intptr_t;
 
 #endif
 
+#if HAVE_OS_ATOMIC_OPS
+#include <libkern/OSAtomic.h>
+
+#define HAS_ATOMIC_OPS 1
+
+typedef int32_t cairo_atomic_int_t;
+
+# define _cairo_atomic_int_get(x) (OSMemoryBarrier(), *(x))
+
+# define _cairo_atomic_int_inc(x) ((void) OSAtomicIncrement32Barrier (x))
+# define _cairo_atomic_int_dec_and_test(x) (OSAtomicDecrement32Barrier (x) == 0)
+# define _cairo_atomic_int_cmpxchg(x, oldv, newv) OSAtomicCompareAndSwap32Barrier(oldv, newv, x)
+
+#if SIZEOF_VOID_P==4
+typedef int32_t cairo_atomic_intptr_t;
+# define _cairo_atomic_ptr_cmpxchg(x, oldv, newv) \
+    OSAtomicCompareAndSwap32Barrier((cairo_atomic_intptr_t)oldv, (cairo_atomic_intptr_t)newv, (cairo_atomic_intptr_t *)x)
+
+#elif SIZEOF_VOID_P==8
+typedef int64_t cairo_atomic_intptr_t;
+# define _cairo_atomic_ptr_cmpxchg(x, oldv, newv) \
+    OSAtomicCompareAndSwap64Barrier((cairo_atomic_intptr_t)oldv, (cairo_atomic_intptr_t)newv, (cairo_atomic_intptr_t *)x)
+
+#else
+#error No matching integer pointer type
+#endif
+
+# define _cairo_atomic_ptr_get(x) (OSMemoryBarrier(), *(x))
+
+#endif
 
 #ifndef HAS_ATOMIC_OPS
 
commit 56a367a1626b2b7ec3d9e64e74f016867f294a34
Author: Andrea Canciani <ranma42 at gmail.com>
Date:   Wed Apr 28 19:17:10 2010 +0200

    atomic: Correct implementation of _atomic_fetch ()
    
    _atomic_fetch() was expected to replace the content of a slot with
    NULL and return the old content, but it incorrectly returned the
    previous content even if it was unable to perform the exchange
    (because of conflicts with other threads accessing the pool).
    
    Fix suggested by Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/cairo-freed-pool-private.h b/src/cairo-freed-pool-private.h
index 38aedce..08fdd94 100644
--- a/src/cairo-freed-pool-private.h
+++ b/src/cairo-freed-pool-private.h
@@ -53,7 +53,13 @@ typedef struct {
 static inline void *
 _atomic_fetch (void **slot)
 {
-    return _cairo_atomic_ptr_cmpxchg_return_old (slot, *slot, NULL);
+    void *ptr;
+
+    do {
+        ptr = _cairo_atomic_ptr_get (slot);
+    } while (! _cairo_atomic_ptr_cmpxchg (slot, ptr, NULL));
+
+    return ptr;
 }
 
 static inline cairo_bool_t
commit d66b1ca1cfda64088521581bc2bd494bff9f5d23
Author: Andrea Canciani <ranma42 at gmail.com>
Date:   Wed Apr 28 16:23:15 2010 +0200

    atomic: Separate bool and old-value compare-and-exchange
    
    Some implementations only offer one version of compare-and-exchange,
    thus we expose both through cairo-atomic, implementing what is missing
    through appropriate fallbacks.
    *_cmpxchg() now return a boolean (this unbreaks _cairo_atomic_uint_cmpxchg)
    *_cmpxchg_return_old() return the old value
    Code is updated everywhere to reflect this, by using *_cmpxchg()
    wherever the returned value was only tested to check if the exchange
    had really taken place.
    
    Reviewed-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/cairo-atomic-private.h b/src/cairo-atomic-private.h
index a0ca769..7dd0254 100644
--- a/src/cairo-atomic-private.h
+++ b/src/cairo-atomic-private.h
@@ -61,7 +61,8 @@ typedef int cairo_atomic_int_t;
 
 # define _cairo_atomic_int_inc(x) ((void) __sync_fetch_and_add(x, 1))
 # define _cairo_atomic_int_dec_and_test(x) (__sync_fetch_and_add(x, -1) == 1)
-# define _cairo_atomic_int_cmpxchg(x, oldv, newv) __sync_val_compare_and_swap (x, oldv, newv)
+# define _cairo_atomic_int_cmpxchg(x, oldv, newv) __sync_bool_compare_and_swap (x, oldv, newv)
+# define _cairo_atomic_int_cmpxchg_return_old(x, oldv, newv) __sync_val_compare_and_swap (x, oldv, newv)
 
 #if SIZEOF_VOID_P==SIZEOF_INT
 typedef int cairo_atomic_intptr_t;
@@ -74,7 +75,10 @@ typedef long long cairo_atomic_intptr_t;
 #endif
 
 # define _cairo_atomic_ptr_cmpxchg(x, oldv, newv) \
-    (void*)__sync_val_compare_and_swap ((cairo_atomic_intptr_t*)x, (cairo_atomic_intptr_t)oldv, (cairo_atomic_intptr_t)newv)
+    __sync_bool_compare_and_swap ((cairo_atomic_intptr_t*)x, (cairo_atomic_intptr_t)oldv, (cairo_atomic_intptr_t)newv)
+
+# define _cairo_atomic_ptr_cmpxchg_return_old(x, oldv, newv) \
+    _cairo_atomic_intptr_to_voidptr (__sync_val_compare_and_swap ((cairo_atomic_intptr_t*)x, (cairo_atomic_intptr_t)oldv, (cairo_atomic_intptr_t)newv))
 
 #endif
 
@@ -89,7 +93,7 @@ typedef  AO_t cairo_atomic_int_t;
 
 # define _cairo_atomic_int_inc(x) ((void) AO_fetch_and_add1_full(x))
 # define _cairo_atomic_int_dec_and_test(x) (AO_fetch_and_sub1_full(x) == 1)
-# define _cairo_atomic_int_cmpxchg(x, oldv, newv) ((cairo_atomic_int_t) AO_compare_and_swap_full(x, oldv, newv) ? oldv : *x)
+# define _cairo_atomic_int_cmpxchg(x, oldv, newv) AO_compare_and_swap_full(x, oldv, newv)
 
 #if SIZEOF_VOID_P==SIZEOF_INT
 typedef unsigned int cairo_atomic_intptr_t;
@@ -101,8 +105,9 @@ typedef unsigned long long cairo_atomic_intptr_t;
 #error No matching integer pointer type
 #endif
 
+# define _cairo_atomic_ptr_get(x) _cairo_atomic_intptr_to_voidptr (AO_load_full (x))
 # define _cairo_atomic_ptr_cmpxchg(x, oldv, newv) \
-    (void*) (cairo_atomic_intptr_t) _cairo_atomic_int_cmpxchg ((cairo_atomic_intptr_t*)(x), (cairo_atomic_intptr_t)oldv, (cairo_atomic_intptr_t)newv)
+    _cairo_atomic_int_cmpxchg ((cairo_atomic_intptr_t*)(x), (cairo_atomic_intptr_t)oldv, (cairo_atomic_intptr_t)newv)
 
 #endif
 
@@ -118,10 +123,13 @@ cairo_private cairo_bool_t
 _cairo_atomic_int_dec_and_test (int *x);
 
 cairo_private int
-_cairo_atomic_int_cmpxchg (int *x, int oldv, int newv);
+_cairo_atomic_int_cmpxchg_return_old_impl (int *x, int oldv, int newv);
 
 cairo_private void *
-_cairo_atomic_ptr_cmpxchg (void **x, void *oldv, void *newv);
+_cairo_atomic_ptr_cmpxchg_return_old_impl (void **x, void *oldv, void *newv);
+
+#define _cairo_atomic_int_cmpxchg_return_old(x, oldv, newv) _cairo_atomic_int_cmpxchg_return_old_impl (x, oldv, newv)
+#define _cairo_atomic_ptr_cmpxchg_return_old(x, oldv, newv) _cairo_atomic_ptr_cmpxchg_return_old_impl (x, oldv, newv)
 
 #ifdef ATOMIC_OP_NEEDS_MEMORY_BARRIER
 cairo_private int
@@ -130,6 +138,54 @@ _cairo_atomic_int_get (int *x);
 # define _cairo_atomic_int_get(x) (*x)
 #endif
 
+#else
+
+/* Workaround GCC complaining about casts */
+static cairo_always_inline void *
+_cairo_atomic_intptr_to_voidptr (cairo_atomic_intptr_t x)
+{
+  return (void *) x;
+}
+
+static cairo_always_inline cairo_atomic_int_t
+_cairo_atomic_int_cmpxchg_return_old_fallback(cairo_atomic_int_t *x, cairo_atomic_int_t oldv, cairo_atomic_int_t newv)
+{
+    cairo_atomic_int_t curr;
+
+    do {
+        curr = _cairo_atomic_int_get (x);
+    } while (curr == oldv && !_cairo_atomic_int_cmpxchg (x, oldv, newv));
+
+    return curr;
+}
+
+static cairo_always_inline void *
+_cairo_atomic_ptr_cmpxchg_return_old_fallback(void **x, void *oldv, void *newv)
+{
+    void *curr;
+
+    do {
+        curr = _cairo_atomic_ptr_get (x);
+    } while (curr == oldv && !_cairo_atomic_ptr_cmpxchg (x, oldv, newv));
+
+    return curr;
+}
+#endif
+
+#ifndef _cairo_atomic_int_cmpxchg_return_old
+#define _cairo_atomic_int_cmpxchg_return_old(x, oldv, newv) _cairo_atomic_int_cmpxchg_return_old_fallback (x, oldv, newv)
+#endif
+
+#ifndef _cairo_atomic_ptr_cmpxchg_return_old
+#define _cairo_atomic_ptr_cmpxchg_return_old(x, oldv, newv) _cairo_atomic_ptr_cmpxchg_return_old_fallback (x, oldv, newv)
+#endif
+
+#ifndef _cairo_atomic_int_cmpxchg
+#define _cairo_atomic_int_cmpxchg(x, oldv, newv) (_cairo_atomic_int_cmpxchg_return_old (x, oldv, newv) == oldv)
+#endif
+
+#ifndef _cairo_atomic_ptr_cmpxchg
+#define _cairo_atomic_ptr_cmpxchg(x, oldv, newv) (_cairo_atomic_ptr_cmpxchg_return_old (x, oldv, newv) == oldv)
 #endif
 
 #define _cairo_atomic_uint_get(x) _cairo_atomic_int_get(x)
diff --git a/src/cairo-atomic.c b/src/cairo-atomic.c
index 60d8f00..4347be1 100644
--- a/src/cairo-atomic.c
+++ b/src/cairo-atomic.c
@@ -62,7 +62,7 @@ _cairo_atomic_int_dec_and_test (int *x)
 }
 
 int
-_cairo_atomic_int_cmpxchg (int *x, int oldv, int newv)
+_cairo_atomic_int_cmpxchg_return_old_impl (int *x, int oldv, int newv)
 {
     int ret;
 
@@ -76,7 +76,7 @@ _cairo_atomic_int_cmpxchg (int *x, int oldv, int newv)
 }
 
 void *
-_cairo_atomic_ptr_cmpxchg (void **x, void *oldv, void *newv)
+_cairo_atomic_ptr_cmpxchg_return_old_impl (void **x, void *oldv, void *newv)
 {
     void *ret;
 
diff --git a/src/cairo-freed-pool-private.h b/src/cairo-freed-pool-private.h
index 6dcf1f5..38aedce 100644
--- a/src/cairo-freed-pool-private.h
+++ b/src/cairo-freed-pool-private.h
@@ -53,13 +53,13 @@ typedef struct {
 static inline void *
 _atomic_fetch (void **slot)
 {
-    return _cairo_atomic_ptr_cmpxchg (slot, *slot, NULL);
+    return _cairo_atomic_ptr_cmpxchg_return_old (slot, *slot, NULL);
 }
 
 static inline cairo_bool_t
 _atomic_store (void **slot, void *ptr)
 {
-    return _cairo_atomic_ptr_cmpxchg (slot, NULL, ptr) == NULL;
+    return _cairo_atomic_ptr_cmpxchg (slot, NULL, ptr);
 }
 
 cairo_private void *
diff --git a/src/cairo-image-surface.c b/src/cairo-image-surface.c
index 77f5ce7..82ab72f 100644
--- a/src/cairo-image-surface.c
+++ b/src/cairo-image-surface.c
@@ -873,7 +873,7 @@ _pixman_transparent_image (void)
 	image = pixman_image_create_solid_fill (&color);
 
 	if (_cairo_atomic_ptr_cmpxchg (&__pixman_transparent_image,
-				       NULL, image) == NULL)
+				       NULL, image))
 	{
 	    pixman_image_ref (image);
 	}
@@ -902,7 +902,7 @@ _pixman_black_image (void)
 	image = pixman_image_create_solid_fill (&color);
 
 	if (_cairo_atomic_ptr_cmpxchg (&__pixman_black_image,
-				       NULL, image) == NULL)
+				       NULL, image))
 	{
 	    pixman_image_ref (image);
 	}
@@ -931,7 +931,7 @@ _pixman_white_image (void)
 	image = pixman_image_create_solid_fill (&color);
 
 	if (_cairo_atomic_ptr_cmpxchg (&__pixman_white_image,
-				       NULL, image) == NULL)
+				       NULL, image))
 	{
 	    pixman_image_ref (image);
 	}
diff --git a/src/cairo.c b/src/cairo.c
index d93cc6f..4246ab7 100644
--- a/src/cairo.c
+++ b/src/cairo.c
@@ -142,7 +142,7 @@ _context_get (void)
 	    return malloc (sizeof (cairo_t));
 
 	new = old | (1 << avail);
-    } while (_cairo_atomic_int_cmpxchg (&_context_stash.occupied, old, new) != old);
+    } while (! _cairo_atomic_int_cmpxchg (&_context_stash.occupied, old, new));
 
     return &_context_stash.pool[avail];
 }
@@ -163,7 +163,7 @@ _context_put (cairo_t *cr)
     do {
 	old = _cairo_atomic_int_get (&_context_stash.occupied);
 	new = old & avail;
-    } while (_cairo_atomic_int_cmpxchg (&_context_stash.occupied, old, new) != old);
+    } while (! _cairo_atomic_int_cmpxchg (&_context_stash.occupied, old, new));
 }
 #else
 #define _context_get() malloc (sizeof (cairo_t))
diff --git a/src/drm/cairo-drm.c b/src/drm/cairo-drm.c
index 6da516d..051b79e 100644
--- a/src/drm/cairo-drm.c
+++ b/src/drm/cairo-drm.c
@@ -84,7 +84,7 @@ _device_finish (void *abstract_device)
     CAIRO_MUTEX_UNLOCK (_cairo_drm_device_mutex);
 
     if (_cairo_atomic_ptr_cmpxchg (&_cairo_drm_default_device,
-				   device, NULL) == device)
+				   device, NULL))
     {
 	cairo_device_destroy (&device->base);
     }
commit a0bf424b820b404947671b56f357a2cef71640fb
Author: Andrea Canciani <ranma42 at gmail.com>
Date:   Wed Apr 28 15:29:32 2010 +0200

    atomic: Remove unused function _cairo_atomic_int_set()
    
    _cairo_atomic_int_set() was only used in the definition of
    CAIRO_REFERENCE_SET_VALUE, which was never used.
    
    Reviewed-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/cairo-atomic-private.h b/src/cairo-atomic-private.h
index 7fbdedb..a0ca769 100644
--- a/src/cairo-atomic-private.h
+++ b/src/cairo-atomic-private.h
@@ -58,7 +58,6 @@ CAIRO_BEGIN_DECLS
 typedef int cairo_atomic_int_t;
 
 # define _cairo_atomic_int_get(x) (*x)
-# define _cairo_atomic_int_set(x, value) ((*x) = value)
 
 # define _cairo_atomic_int_inc(x) ((void) __sync_fetch_and_add(x, 1))
 # define _cairo_atomic_int_dec_and_test(x) (__sync_fetch_and_add(x, -1) == 1)
@@ -87,7 +86,6 @@ typedef long long cairo_atomic_intptr_t;
 typedef  AO_t cairo_atomic_int_t;
 
 # define _cairo_atomic_int_get(x) (AO_load_full (x))
-# define _cairo_atomic_int_set(x, value) (AO_store_full (x))
 
 # define _cairo_atomic_int_inc(x) ((void) AO_fetch_and_add1_full(x))
 # define _cairo_atomic_int_dec_and_test(x) (AO_fetch_and_sub1_full(x) == 1)
@@ -126,18 +124,10 @@ cairo_private void *
 _cairo_atomic_ptr_cmpxchg (void **x, void *oldv, void *newv);
 
 #ifdef ATOMIC_OP_NEEDS_MEMORY_BARRIER
-
 cairo_private int
 _cairo_atomic_int_get (int *x);
-
-cairo_private void
-_cairo_atomic_int_set (int *x, int value);
-
 #else
-
 # define _cairo_atomic_int_get(x) (*x)
-# define _cairo_atomic_int_set(x, value) ((*x) = value)
-
 #endif
 
 #endif
diff --git a/src/cairo-atomic.c b/src/cairo-atomic.c
index 5bc7d3a..60d8f00 100644
--- a/src/cairo-atomic.c
+++ b/src/cairo-atomic.c
@@ -101,14 +101,6 @@ _cairo_atomic_int_get (int *x)
 
     return ret;
 }
-
-void
-_cairo_atomic_int_set (int *x, int value)
-{
-    CAIRO_MUTEX_LOCK (_cairo_atomic_mutex);
-    *x = value;
-    CAIRO_MUTEX_UNLOCK (_cairo_atomic_mutex);
-}
 #endif
 
 #endif
diff --git a/src/cairo-reference-count-private.h b/src/cairo-reference-count-private.h
index 7c5c601..0cb5695 100644
--- a/src/cairo-reference-count-private.h
+++ b/src/cairo-reference-count-private.h
@@ -50,7 +50,6 @@ typedef struct {
 #define CAIRO_REFERENCE_COUNT_INIT(RC, VALUE) ((RC)->ref_count = (VALUE))
 
 #define CAIRO_REFERENCE_COUNT_GET_VALUE(RC) _cairo_atomic_int_get (&(RC)->ref_count)
-#define CAIRO_REFERENCE_COUNT_SET_VALUE(RC, VALUE) _cairo_atomic_int_set (&(RC)->ref_count, (VALUE))
 
 #define CAIRO_REFERENCE_COUNT_INVALID_VALUE ((cairo_atomic_int_t) -1)
 #define CAIRO_REFERENCE_COUNT_INVALID {CAIRO_REFERENCE_COUNT_INVALID_VALUE}


More information about the cairo-commit mailing list