mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-05-04 22:18:29 +02:00
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@chris-wilson.co.uk>
This commit is contained in:
parent
a0bf424b82
commit
d66b1ca1cf
6 changed files with 72 additions and 16 deletions
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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 *
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue