summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2009-10-13 16:10:39 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2009-10-15 13:05:46 +0100
commitef9286751d8346ecb803bfb5916581ee4dfc84db (patch)
tree2e78392a19f1a0a2d07fb8408b85e4f98ac58cfe
parentd85eda97dd9116f51e0255b29652f4b52ba4f8e9 (diff)
[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.
-rw-r--r--build/aclocal.cairo.m410
-rw-r--r--src/cairo-atomic-private.h41
-rw-r--r--src/cairo-surface.c4
-rw-r--r--src/cairo-xlib-private.h2
-rw-r--r--src/cairo-xlib-screen.c16
-rw-r--r--src/cairo.c10
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 <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)
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);
}