From ef9286751d8346ecb803bfb5916581ee4dfc84db Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 13 Oct 2009 16:10:39 +0100 Subject: [atomic] Fallback to libatomic-ops-dev Use libatomic-ops-dev in preference to mutex-based atomics, if we do not have the builtin atomic intrinsics available. --- build/aclocal.cairo.m4 | 10 ++++++++++ src/cairo-atomic-private.h | 41 ++++++++++++++++++++++++++++++++++++----- src/cairo-surface.c | 4 ++-- src/cairo-xlib-private.h | 2 +- src/cairo-xlib-screen.c | 16 +++++++++------- src/cairo.c | 10 +++++----- 6 files changed, 63 insertions(+), 20 deletions(-) diff --git a/build/aclocal.cairo.m4 b/build/aclocal.cairo.m4 index 5eec262e..e03fa1c5 100644 --- a/build/aclocal.cairo.m4 +++ b/build/aclocal.cairo.m4 @@ -172,11 +172,21 @@ int atomic_cmpxchg(int i, int j, int k) { return __sync_val_compare_and_swap (&i ], [], cairo_cv_atomic_primitives="Intel" ) + + if test "x$cairo_cv_atomic_primitives" = "xnone"; then + AC_CHECK_HEADER([atomic_ops.h], + cairo_cv_atomic_primitives="libatomic-ops") + fi ]) if test "x$cairo_cv_atomic_primitives" = xIntel; then AC_DEFINE(HAVE_INTEL_ATOMIC_PRIMITIVES, 1, [Enable if your compiler supports the Intel __sync_* atomic primitives]) fi + + if test "x$cairo_cv_atomic_primitives" = "xlibatomic-ops"; then + AC_DEFINE(HAVE_LIB_ATOMIC_OPS, 1, + [Enable if you have libatomic-ops-dev installed]) + fi ]) dnl Usage: diff --git a/src/cairo-atomic-private.h b/src/cairo-atomic-private.h index bf79b7a9..d2583a17 100644 --- a/src/cairo-atomic-private.h +++ b/src/cairo-atomic-private.h @@ -57,6 +57,9 @@ 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) # define _cairo_atomic_int_cmpxchg(x, oldv, newv) __sync_val_compare_and_swap (x, oldv, newv) @@ -76,6 +79,35 @@ typedef long long cairo_atomic_intptr_t; #endif +#if HAVE_LIB_ATOMIC_OPS +#include + +#define HAS_ATOMIC_OPS 1 + +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) +# define _cairo_atomic_int_cmpxchg(x, oldv, newv) ((cairo_atomic_int_t) AO_compare_and_swap_full(x, oldv, newv)) + +#if SIZEOF_VOID_P==SIZEOF_INT +typedef unsigned int cairo_atomic_intptr_t; +#elif SIZEOF_VOID_P==SIZEOF_LONG +typedef unsigned long cairo_atomic_intptr_t; +#elif SIZEOF_VOID_P==SIZEOF_LONG_LONG +typedef unsigned long long cairo_atomic_intptr_t; +#else +#error No matching integer pointer type +#endif + +# 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) + +#endif + #ifndef HAS_ATOMIC_OPS @@ -93,9 +125,6 @@ _cairo_atomic_int_cmpxchg (int *x, int oldv, int newv); cairo_private void * _cairo_atomic_ptr_cmpxchg (void **x, void *oldv, void *newv); -#endif - - #ifdef ATOMIC_OP_NEEDS_MEMORY_BARRIER # include "cairo-compiler-private.h" @@ -113,14 +142,16 @@ _cairo_atomic_int_set (int *x, int value); #endif +#endif + #define _cairo_atomic_uint_get(x) _cairo_atomic_int_get(x) #define _cairo_atomic_uint_cmpxchg(x, oldv, newv) \ - _cairo_atomic_int_cmpxchg((int *)x, oldv, newv) + _cairo_atomic_int_cmpxchg((cairo_atomic_int_t *)x, oldv, newv) #define _cairo_status_set_error(status, err) do { \ /* hide compiler warnings about cairo_status_t != int (gcc treats its as \ * an unsigned integer instead, and about ignoring the return value. */ \ - int ret__ = _cairo_atomic_int_cmpxchg ((int *) status, CAIRO_STATUS_SUCCESS, err); \ + int ret__ = _cairo_atomic_int_cmpxchg ((cairo_atomic_int_t *) status, CAIRO_STATUS_SUCCESS, err); \ (void) ret__; \ } while (0) diff --git a/src/cairo-surface.c b/src/cairo-surface.c index fd4e01b0..ab84bbf8 100644 --- a/src/cairo-surface.c +++ b/src/cairo-surface.c @@ -193,14 +193,14 @@ slim_hidden_def (cairo_surface_status); static unsigned int _cairo_surface_allocate_unique_id (void) { - static unsigned int unique_id; + static cairo_atomic_int_t unique_id; #if CAIRO_NO_MUTEX if (++unique_id == 0) unique_id = 1; return unique_id; #else - unsigned int old, id; + cairo_atomic_int_t old, id; do { old = _cairo_atomic_uint_get (&unique_id); diff --git a/src/cairo-xlib-private.h b/src/cairo-xlib-private.h index 33601e89..afdf6a6b 100644 --- a/src/cairo-xlib-private.h +++ b/src/cairo-xlib-private.h @@ -85,7 +85,7 @@ struct _cairo_xlib_screen { cairo_font_options_t font_options; GC gc[4]; - int gc_depths; /* 4 x uint8_t */ + cairo_atomic_int_t gc_depths; /* 4 x uint8_t */ cairo_array_t visuals; }; diff --git a/src/cairo-xlib-screen.c b/src/cairo-xlib-screen.c index 79d8c0de..fc2535b9 100644 --- a/src/cairo-xlib-screen.c +++ b/src/cairo-xlib-screen.c @@ -269,7 +269,8 @@ _cairo_xlib_screen_close_display (cairo_xlib_screen_t *info) { cairo_xlib_visual_info_t **visuals; Display *dpy; - int i, old; + cairo_atomic_int_t old; + int i; CAIRO_MUTEX_LOCK (info->mutex); @@ -277,7 +278,7 @@ _cairo_xlib_screen_close_display (cairo_xlib_screen_t *info) #if HAS_ATOMIC_OPS do { - old = info->gc_depths; + old = _cairo_atomic_int_get (&info->gc_depths); } while (_cairo_atomic_int_cmpxchg (&info->gc_depths, old, 0) != old); #else old = info->gc_depths; @@ -384,7 +385,8 @@ _cairo_xlib_screen_get_gc (cairo_xlib_screen_t *info, Drawable drawable) { XGCValues gcv; - int i, new, old; + cairo_atomic_int_t old, new; + int i; GC gc; do { @@ -393,13 +395,13 @@ _cairo_xlib_screen_get_gc (cairo_xlib_screen_t *info, if (old == 0) break; - if (((old >> 0) & 0xff) == depth) + if (((old >> 0) & 0xff) == (unsigned) depth) i = 0; - else if (((old >> 8) & 0xff) == depth) + else if (((old >> 8) & 0xff) == (unsigned) depth) i = 1; - else if (((old >> 16) & 0xff) == depth) + else if (((old >> 16) & 0xff) == (unsigned) depth) i = 2; - else if (((old >> 24) & 0xff) == depth) + else if (((old >> 24) & 0xff) == (unsigned) depth) i = 3; else break; diff --git a/src/cairo.c b/src/cairo.c index 2470b0d6..383dc89e 100644 --- a/src/cairo.c +++ b/src/cairo.c @@ -124,16 +124,16 @@ _cairo_set_error (cairo_t *cr, cairo_status_t status) #define CAIRO_STASH_SIZE 4 static struct { cairo_t pool[CAIRO_STASH_SIZE]; - int occupied; + cairo_atomic_int_t occupied; } _context_stash; static cairo_t * _context_get (void) { - int avail, old, new; + cairo_atomic_int_t avail, old, new; do { - old = _context_stash.occupied; + old = _cairo_atomic_int_get (&_context_stash.occupied); avail = ffs (~old) - 1; if (avail >= CAIRO_STASH_SIZE) return malloc (sizeof (cairo_t)); @@ -147,7 +147,7 @@ _context_get (void) static void _context_put (cairo_t *cr) { - int old, new, avail; + cairo_atomic_int_t old, new, avail; if (cr < &_context_stash.pool[0] || cr >= &_context_stash.pool[CAIRO_STASH_SIZE]) @@ -158,7 +158,7 @@ _context_put (cairo_t *cr) avail = ~(1 << (cr - &_context_stash.pool[0])); do { - old = _context_stash.occupied; + old = _cairo_atomic_int_get (&_context_stash.occupied); new = old & avail; } while (_cairo_atomic_int_cmpxchg (&_context_stash.occupied, old, new) != old); } -- cgit v1.2.3