[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.
This commit is contained in:
Chris Wilson 2009-10-13 16:10:39 +01:00
parent d85eda97dd
commit ef9286751d
6 changed files with 63 additions and 20 deletions

View file

@ -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:

View file

@ -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 <atomic_ops.h>
#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)

View file

@ -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);

View file

@ -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;
};

View file

@ -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;

View file

@ -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);
}