mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-02-14 02:50:29 +01:00
[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:
parent
d85eda97dd
commit
ef9286751d
6 changed files with 63 additions and 20 deletions
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
10
src/cairo.c
10
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);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue