Add support for C11 atomics

This commit is contained in:
Adrian Johnson 2023-05-27 21:21:47 +09:30
parent 8d0650bb60
commit 87f7c60bf7
13 changed files with 184 additions and 74 deletions

View file

@ -0,0 +1,12 @@
#include <assert.h>
#include <stdatomic.h>
/* We require lock free atomics for int and pointers as cairo assumes
* an int* can be cast to cairo_atomic_int_t*
*/
_Static_assert (ATOMIC_INT_LOCK_FREE == 2, "Lock free atomics not supported");
_Static_assert (ATOMIC_POINTER_LOCK_FREE == 2, "Lock free atomics not supported");
int atomic_add(atomic_int *i) { return atomic_fetch_add_explicit(i, 1, memory_order_seq_cst); }
int atomic_cmpxchg(atomic_int *i, int j, int k) { return atomic_compare_exchange_strong_explicit (i, &j, k, memory_order_seq_cst, memory_order_seq_cst); }
int main(void) { return 0; }

View file

@ -726,7 +726,11 @@ endforeach
extra_link_args += pthread_link_args extra_link_args += pthread_link_args
if cc.links(files('meson-cc-tests/atomic-ops-cxx11.c'), name: 'Atomic ops: cxx11') # Atomics are an optional feature in C11. Also need to check that C11 atomics are lock free.
# Windows can't use C11 atomics as some files are compiled with C++.
if host_machine.system() != 'windows' and cc.links(files('meson-cc-tests/atomic-ops-c11.c'), name: 'Atomic ops: c11')
conf.set('HAVE_C11_ATOMIC_PRIMITIVES', 1)
elif cc.links(files('meson-cc-tests/atomic-ops-cxx11.c'), name: 'Atomic ops: cxx11')
conf.set('HAVE_CXX11_ATOMIC_PRIMITIVES', 1) conf.set('HAVE_CXX11_ATOMIC_PRIMITIVES', 1)
elif cc.links(files('meson-cc-tests/atomic-ops-gcc-legacy.c'), name: 'Atomic ops: gcc legacy') elif cc.links(files('meson-cc-tests/atomic-ops-gcc-legacy.c'), name: 'Atomic ops: gcc legacy')
conf.set('HAVE_GCC_LEGACY_ATOMICS', 1) conf.set('HAVE_GCC_LEGACY_ATOMICS', 1)
@ -734,6 +738,8 @@ elif cc.has_header('atomic_ops.h')
conf.set('HAVE_LIB_ATOMIC_OPS', 1) conf.set('HAVE_LIB_ATOMIC_OPS', 1)
elif cc.has_header('libkern/OSAtomic.h') elif cc.has_header('libkern/OSAtomic.h')
conf.set('HAVE_OS_ATOMIC_OPS', 1) conf.set('HAVE_OS_ATOMIC_OPS', 1)
elif host_machine.system() != 'windows'
warning('Atomic ops not supported.')
endif endif
test_mkdir_c_args = [] test_mkdir_c_args = []

View file

@ -47,6 +47,92 @@
CAIRO_BEGIN_DECLS CAIRO_BEGIN_DECLS
#if HAVE_C11_ATOMIC_PRIMITIVES
#include <stdatomic.h>
#define HAS_ATOMIC_OPS 1
typedef atomic_int cairo_atomic_int_t;
typedef _Atomic(void *) cairo_atomic_intptr_t;
static cairo_always_inline int
_cairo_atomic_int_get (cairo_atomic_int_t *x)
{
return atomic_load_explicit (x, memory_order_seq_cst);
}
static cairo_always_inline int
_cairo_atomic_int_get_relaxed (cairo_atomic_int_t *x)
{
return atomic_load_explicit (x, memory_order_relaxed);
}
static cairo_always_inline void
_cairo_atomic_int_set_relaxed (cairo_atomic_int_t *x, int val)
{
atomic_store_explicit (x, val, memory_order_relaxed);
}
static cairo_always_inline void *
_cairo_atomic_ptr_get (cairo_atomic_intptr_t *x)
{
return atomic_load_explicit (x, memory_order_seq_cst);
}
# define _cairo_atomic_int_inc(x) ((void) atomic_fetch_add_explicit(x, 1, memory_order_seq_cst))
# define _cairo_atomic_int_dec(x) ((void) atomic_fetch_sub_explicit(x, 1, memory_order_seq_cst))
# define _cairo_atomic_int_dec_and_test(x) (atomic_fetch_sub_explicit(x, 1, memory_order_seq_cst) == 1)
static cairo_always_inline cairo_bool_t
_cairo_atomic_int_cmpxchg_impl(cairo_atomic_int_t *x,
int oldv,
int newv)
{
int expected = oldv;
return atomic_compare_exchange_strong_explicit (x, &expected, newv, memory_order_seq_cst, memory_order_seq_cst);
}
#define _cairo_atomic_int_cmpxchg(x, oldv, newv) \
_cairo_atomic_int_cmpxchg_impl(x, oldv, newv)
static cairo_always_inline int
_cairo_atomic_int_cmpxchg_return_old_impl(cairo_atomic_int_t *x,
int oldv,
int newv)
{
int expected = oldv;
(void) atomic_compare_exchange_strong_explicit (x, &expected, newv, memory_order_seq_cst, memory_order_seq_cst);
return expected;
}
#define _cairo_atomic_int_cmpxchg_return_old(x, oldv, newv) \
_cairo_atomic_int_cmpxchg_return_old_impl(x, oldv, newv)
static cairo_always_inline cairo_bool_t
_cairo_atomic_ptr_cmpxchg_impl(cairo_atomic_intptr_t *x, void *oldv, void *newv)
{
void *expected = oldv;
return atomic_compare_exchange_strong_explicit (x, &expected, newv, memory_order_seq_cst, memory_order_seq_cst);
}
#define _cairo_atomic_ptr_cmpxchg(x, oldv, newv) \
_cairo_atomic_ptr_cmpxchg_impl(x, oldv, newv)
static cairo_always_inline void *
_cairo_atomic_ptr_cmpxchg_return_old_impl(cairo_atomic_intptr_t *x, void *oldv, void *newv)
{
void *expected = oldv;
(void) atomic_compare_exchange_strong_explicit (x, &expected, newv, memory_order_seq_cst, memory_order_seq_cst);
return expected;
}
#define _cairo_atomic_ptr_cmpxchg_return_old(x, oldv, newv) \
_cairo_atomic_ptr_cmpxchg_return_old_impl(x, oldv, newv)
#endif /* HAVE_C11_ATOMIC_PRIMITIVES */
/* C++11 atomic primitives were designed to be more flexible than the /* C++11 atomic primitives were designed to be more flexible than the
* __sync_* family of primitives. Despite the name, they are available * __sync_* family of primitives. Despite the name, they are available
* in C as well as C++. The motivating reason for using them is that * in C as well as C++. The motivating reason for using them is that
@ -62,55 +148,54 @@ CAIRO_BEGIN_DECLS
#define HAS_ATOMIC_OPS 1 #define HAS_ATOMIC_OPS 1
typedef int cairo_atomic_int_t; typedef int cairo_atomic_int_t;
typedef intptr_t cairo_atomic_intptr_t;
static cairo_always_inline cairo_atomic_int_t static cairo_always_inline int
_cairo_atomic_int_get (cairo_atomic_int_t *x) _cairo_atomic_int_get (cairo_atomic_int_t *x)
{ {
return __atomic_load_n(x, __ATOMIC_SEQ_CST); return __atomic_load_n(x, __ATOMIC_SEQ_CST);
} }
static cairo_always_inline cairo_atomic_int_t static cairo_always_inline int
_cairo_atomic_int_get_relaxed (cairo_atomic_int_t *x) _cairo_atomic_int_get_relaxed (cairo_atomic_int_t *x)
{ {
return __atomic_load_n(x, __ATOMIC_RELAXED); return __atomic_load_n(x, __ATOMIC_RELAXED);
} }
static cairo_always_inline void static cairo_always_inline void
_cairo_atomic_int_set_relaxed (cairo_atomic_int_t *x, cairo_atomic_int_t val) _cairo_atomic_int_set_relaxed (cairo_atomic_int_t *x, int val)
{ {
__atomic_store_n(x, val, __ATOMIC_RELAXED); __atomic_store_n(x, val, __ATOMIC_RELAXED);
} }
static cairo_always_inline void * static cairo_always_inline void *
_cairo_atomic_ptr_get (void **x) _cairo_atomic_ptr_get (cairo_atomic_intptr_t *x)
{ {
return __atomic_load_n(x, __ATOMIC_SEQ_CST); return (void*)__atomic_load_n(x, __ATOMIC_SEQ_CST);
} }
# define _cairo_atomic_int_inc(x) ((void) __atomic_fetch_add(x, 1, __ATOMIC_SEQ_CST)) # define _cairo_atomic_int_inc(x) ((void) __atomic_fetch_add(x, 1, __ATOMIC_SEQ_CST))
# define _cairo_atomic_int_dec(x) ((void) __atomic_fetch_sub(x, 1, __ATOMIC_SEQ_CST)) # define _cairo_atomic_int_dec(x) ((void) __atomic_fetch_sub(x, 1, __ATOMIC_SEQ_CST))
# define _cairo_atomic_int_dec_and_test(x) (__atomic_fetch_sub(x, 1, __ATOMIC_SEQ_CST) == 1) # define _cairo_atomic_int_dec_and_test(x) (__atomic_fetch_sub(x, 1, __ATOMIC_SEQ_CST) == 1)
typedef intptr_t cairo_atomic_intptr_t;
static cairo_always_inline cairo_bool_t static cairo_always_inline cairo_bool_t
_cairo_atomic_int_cmpxchg_impl(cairo_atomic_int_t *x, _cairo_atomic_int_cmpxchg_impl(cairo_atomic_int_t *x,
cairo_atomic_int_t oldv, int oldv,
cairo_atomic_int_t newv) int newv)
{ {
cairo_atomic_int_t expected = oldv; int expected = oldv;
return __atomic_compare_exchange_n(x, &expected, newv, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); return __atomic_compare_exchange_n(x, &expected, newv, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
} }
#define _cairo_atomic_int_cmpxchg(x, oldv, newv) \ #define _cairo_atomic_int_cmpxchg(x, oldv, newv) \
_cairo_atomic_int_cmpxchg_impl(x, oldv, newv) _cairo_atomic_int_cmpxchg_impl(x, oldv, newv)
static cairo_always_inline cairo_atomic_int_t static cairo_always_inline int
_cairo_atomic_int_cmpxchg_return_old_impl(cairo_atomic_int_t *x, _cairo_atomic_int_cmpxchg_return_old_impl(cairo_atomic_int_t *x,
cairo_atomic_int_t oldv, int oldv,
cairo_atomic_int_t newv) int newv)
{ {
cairo_atomic_int_t expected = oldv; int expected = oldv;
(void) __atomic_compare_exchange_n(x, &expected, newv, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); (void) __atomic_compare_exchange_n(x, &expected, newv, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
return expected; return expected;
} }
@ -119,7 +204,7 @@ _cairo_atomic_int_cmpxchg_return_old_impl(cairo_atomic_int_t *x,
_cairo_atomic_int_cmpxchg_return_old_impl(x, oldv, newv) _cairo_atomic_int_cmpxchg_return_old_impl(x, oldv, newv)
static cairo_always_inline cairo_bool_t static cairo_always_inline cairo_bool_t
_cairo_atomic_ptr_cmpxchg_impl(void **x, void *oldv, void *newv) _cairo_atomic_ptr_cmpxchg_impl(cairo_atomic_intptr_t *x, void *oldv, void *newv)
{ {
void *expected = oldv; void *expected = oldv;
return __atomic_compare_exchange_n(x, &expected, newv, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); return __atomic_compare_exchange_n(x, &expected, newv, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
@ -129,7 +214,7 @@ _cairo_atomic_ptr_cmpxchg_impl(void **x, void *oldv, void *newv)
_cairo_atomic_ptr_cmpxchg_impl(x, oldv, newv) _cairo_atomic_ptr_cmpxchg_impl(x, oldv, newv)
static cairo_always_inline void * static cairo_always_inline void *
_cairo_atomic_ptr_cmpxchg_return_old_impl(void **x, void *oldv, void *newv) _cairo_atomic_ptr_cmpxchg_return_old_impl(cairo_atomic_intptr_t *x, void *oldv, void *newv)
{ {
void *expected = oldv; void *expected = oldv;
(void) __atomic_compare_exchange_n(x, &expected, newv, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); (void) __atomic_compare_exchange_n(x, &expected, newv, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
@ -139,38 +224,39 @@ _cairo_atomic_ptr_cmpxchg_return_old_impl(void **x, void *oldv, void *newv)
#define _cairo_atomic_ptr_cmpxchg_return_old(x, oldv, newv) \ #define _cairo_atomic_ptr_cmpxchg_return_old(x, oldv, newv) \
_cairo_atomic_ptr_cmpxchg_return_old_impl(x, oldv, newv) _cairo_atomic_ptr_cmpxchg_return_old_impl(x, oldv, newv)
#endif #endif /* HAVE_CXX11_ATOMIC_PRIMITIVES */
#if HAVE_GCC_LEGACY_ATOMICS #if HAVE_GCC_LEGACY_ATOMICS
#define HAS_ATOMIC_OPS 1 #define HAS_ATOMIC_OPS 1
typedef int cairo_atomic_int_t; typedef int cairo_atomic_int_t;
typedef intptr_t cairo_atomic_intptr_t;
static cairo_always_inline cairo_atomic_int_t static cairo_always_inline int
_cairo_atomic_int_get (cairo_atomic_int_t *x) _cairo_atomic_int_get (cairo_atomic_int_t *x)
{ {
__sync_synchronize (); __sync_synchronize ();
return *x; return *x;
} }
static cairo_always_inline cairo_atomic_int_t static cairo_always_inline int
_cairo_atomic_int_get_relaxed (cairo_atomic_int_t *x) _cairo_atomic_int_get_relaxed (cairo_atomic_int_t *x)
{ {
return *x; return *x;
} }
static cairo_always_inline void static cairo_always_inline void
_cairo_atomic_int_set_relaxed (cairo_atomic_int_t *x, cairo_atomic_int_t val) _cairo_atomic_int_set_relaxed (cairo_atomic_int_t *x, int val)
{ {
*x = val; *x = val;
} }
static cairo_always_inline void * static cairo_always_inline void *
_cairo_atomic_ptr_get (void **x) _cairo_atomic_ptr_get (cairo_atomic_intptr_t *x)
{ {
__sync_synchronize (); __sync_synchronize ();
return *x; return (void*)*x;
} }
# define _cairo_atomic_int_inc(x) ((void) __sync_fetch_and_add(x, 1)) # define _cairo_atomic_int_inc(x) ((void) __sync_fetch_and_add(x, 1))
@ -179,15 +265,13 @@ _cairo_atomic_ptr_get (void **x)
# define _cairo_atomic_int_cmpxchg(x, oldv, newv) __sync_bool_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) # define _cairo_atomic_int_cmpxchg_return_old(x, oldv, newv) __sync_val_compare_and_swap (x, oldv, newv)
typedef intptr_t cairo_atomic_intptr_t;
# define _cairo_atomic_ptr_cmpxchg(x, oldv, newv) \ # define _cairo_atomic_ptr_cmpxchg(x, oldv, newv) \
__sync_bool_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) \ # 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)) _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 #endif /* HAVE_GCC_LEGACY_ATOMICS */
#if HAVE_LIB_ATOMIC_OPS #if HAVE_LIB_ATOMIC_OPS
#include <atomic_ops.h> #include <atomic_ops.h>
@ -219,6 +303,7 @@ typedef intptr_t cairo_atomic_intptr_t;
#define HAS_ATOMIC_OPS 1 #define HAS_ATOMIC_OPS 1
typedef int32_t cairo_atomic_int_t; typedef int32_t cairo_atomic_int_t;
typedef intptr_t cairo_atomic_intptr_t;
# define _cairo_atomic_int_get(x) (OSMemoryBarrier(), *(x)) # define _cairo_atomic_int_get(x) (OSMemoryBarrier(), *(x))
# define _cairo_atomic_int_get_relaxed(x) *(x) # define _cairo_atomic_int_get_relaxed(x) *(x)
@ -229,8 +314,6 @@ typedef int32_t cairo_atomic_int_t;
# define _cairo_atomic_int_dec_and_test(x) (OSAtomicDecrement32Barrier (x) == 0) # define _cairo_atomic_int_dec_and_test(x) (OSAtomicDecrement32Barrier (x) == 0)
# define _cairo_atomic_int_cmpxchg(x, oldv, newv) OSAtomicCompareAndSwap32Barrier(oldv, newv, x) # define _cairo_atomic_int_cmpxchg(x, oldv, newv) OSAtomicCompareAndSwap32Barrier(oldv, newv, x)
typedef intptr_t cairo_atomic_intptr_t;
#if SIZEOF_VOID_P==4 #if SIZEOF_VOID_P==4
# define _cairo_atomic_ptr_cmpxchg(x, oldv, newv) \ # define _cairo_atomic_ptr_cmpxchg(x, oldv, newv) \
OSAtomicCompareAndSwap32Barrier((cairo_atomic_intptr_t)oldv, (cairo_atomic_intptr_t)newv, (cairo_atomic_intptr_t *)x) OSAtomicCompareAndSwap32Barrier((cairo_atomic_intptr_t)oldv, (cairo_atomic_intptr_t)newv, (cairo_atomic_intptr_t *)x)
@ -245,17 +328,17 @@ typedef intptr_t cairo_atomic_intptr_t;
# define _cairo_atomic_ptr_get(x) (OSMemoryBarrier(), *(x)) # define _cairo_atomic_ptr_get(x) (OSMemoryBarrier(), *(x))
#endif #endif /* HAVE_OS_ATOMIC_OPS */
#if !defined(HAS_ATOMIC_OPS) && defined(_WIN32) #if !defined(HAS_ATOMIC_OPS) && defined(_WIN32)
#include <windows.h> #include <windows.h>
#define HAS_ATOMIC_OPS 1 #define HAS_ATOMIC_OPS 1
typedef int32_t cairo_atomic_int_t; typedef LONG cairo_atomic_int_t;
typedef intptr_t cairo_atomic_intptr_t; typedef PVOID cairo_atomic_intptr_t;
static cairo_always_inline cairo_atomic_int_t static cairo_always_inline int
_cairo_atomic_int_get (cairo_atomic_int_t *x) _cairo_atomic_int_get (cairo_atomic_int_t *x)
{ {
MemoryBarrier (); MemoryBarrier ();
@ -265,33 +348,33 @@ _cairo_atomic_int_get (cairo_atomic_int_t *x)
# define _cairo_atomic_int_get_relaxed(x) *(x) # define _cairo_atomic_int_get_relaxed(x) *(x)
# define _cairo_atomic_int_set_relaxed(x, val) *(x) = (val) # define _cairo_atomic_int_set_relaxed(x, val) *(x) = (val)
# define _cairo_atomic_int_inc(x) ((void) InterlockedIncrement ((LONG*)x)) # define _cairo_atomic_int_inc(x) ((void) InterlockedIncrement (x))
# define _cairo_atomic_int_dec(x) ((void) InterlockedDecrement ((LONG*)x)) # define _cairo_atomic_int_dec(x) ((void) InterlockedDecrement (x))
# define _cairo_atomic_int_dec_and_test(x) (InterlockedDecrement ((LONG*)x) == 0) # define _cairo_atomic_int_dec_and_test(x) (InterlockedDecrement (x) == 0)
static cairo_always_inline cairo_bool_t static cairo_always_inline cairo_bool_t
_cairo_atomic_int_cmpxchg (cairo_atomic_int_t *x, _cairo_atomic_int_cmpxchg (cairo_atomic_int_t *x,
cairo_atomic_int_t oldv, int oldv,
cairo_atomic_int_t newv) int newv)
{ {
return InterlockedCompareExchange ((LONG*)x, (LONG)newv, (LONG)oldv) == oldv; return InterlockedCompareExchange (x, (LONG)newv, (LONG)oldv) == oldv;
} }
static cairo_always_inline void * static cairo_always_inline void *
_cairo_atomic_ptr_get (void **x) _cairo_atomic_ptr_get (cairo_atomic_intptr_t *x)
{ {
MemoryBarrier (); MemoryBarrier ();
return *x; return (void *) *x;
} }
static cairo_always_inline cairo_bool_t static cairo_always_inline cairo_bool_t
_cairo_atomic_ptr_cmpxchg (void **x, void *oldv, void *newv) _cairo_atomic_ptr_cmpxchg (cairo_atomic_intptr_t *x, void *oldv, void *newv)
{ {
return InterlockedCompareExchangePointer (x, newv, oldv) == oldv; return InterlockedCompareExchangePointer (x, newv, oldv) == oldv;
} }
static cairo_always_inline void * static cairo_always_inline void *
_cairo_atomic_ptr_cmpxchg_return_old (void **x, void *oldv, void *newv) _cairo_atomic_ptr_cmpxchg_return_old (cairo_atomic_intptr_t *x, void *oldv, void *newv)
{ {
return InterlockedCompareExchangePointer (x, newv, oldv); return InterlockedCompareExchangePointer (x, newv, oldv);
} }
@ -312,24 +395,24 @@ _cairo_atomic_int_inc (cairo_atomic_int_t *x);
cairo_private cairo_bool_t cairo_private cairo_bool_t
_cairo_atomic_int_dec_and_test (cairo_atomic_int_t *x); _cairo_atomic_int_dec_and_test (cairo_atomic_int_t *x);
cairo_private cairo_atomic_int_t cairo_private int
_cairo_atomic_int_cmpxchg_return_old_impl (cairo_atomic_int_t *x, cairo_atomic_int_t oldv, cairo_atomic_int_t newv); _cairo_atomic_int_cmpxchg_return_old_impl (cairo_atomic_int_t *x, int oldv, int newv);
cairo_private void * cairo_private void *
_cairo_atomic_ptr_cmpxchg_return_old_impl (void **x, void *oldv, void *newv); _cairo_atomic_ptr_cmpxchg_return_old_impl (cairo_atomic_intptr_t *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_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) #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 #ifdef ATOMIC_OP_NEEDS_MEMORY_BARRIER
cairo_private cairo_atomic_int_t cairo_private int
_cairo_atomic_int_get (cairo_atomic_int_t *x); _cairo_atomic_int_get (cairo_atomic_int_t *x);
cairo_private cairo_atomic_int_t cairo_private int
_cairo_atomic_int_get_relaxed (cairo_atomic_int_t *x); _cairo_atomic_int_get_relaxed (cairo_atomic_int_t *x);
void void
_cairo_atomic_int_set_relaxed (cairo_atomic_int_t *x, cairo_atomic_int_t val); _cairo_atomic_int_set_relaxed (cairo_atomic_int_t *x, int val);
cairo_private void* cairo_private void*
_cairo_atomic_ptr_get(void **x); _cairo_atomic_ptr_get(cairo_atomic_intptr_t *x);
#else #else
# define _cairo_atomic_int_get(x) (*x) # define _cairo_atomic_int_get(x) (*x)
# define _cairo_atomic_int_get_relaxed(x) (*x) # define _cairo_atomic_int_get_relaxed(x) (*x)
@ -346,10 +429,10 @@ _cairo_atomic_intptr_to_voidptr (cairo_atomic_intptr_t x)
return (void *) x; return (void *) x;
} }
static cairo_always_inline cairo_atomic_int_t static cairo_always_inline int
_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_cmpxchg_return_old_fallback(cairo_atomic_int_t *x, int oldv, int newv)
{ {
cairo_atomic_int_t curr; int curr;
do { do {
curr = _cairo_atomic_int_get (x); curr = _cairo_atomic_int_get (x);
@ -359,7 +442,7 @@ _cairo_atomic_int_cmpxchg_return_old_fallback(cairo_atomic_int_t *x, cairo_atomi
} }
static cairo_always_inline void * static cairo_always_inline void *
_cairo_atomic_ptr_cmpxchg_return_old_fallback(void **x, void *oldv, void *newv) _cairo_atomic_ptr_cmpxchg_return_old_fallback(cairo_atomic_intptr_t *x, void *oldv, void *newv)
{ {
void *curr; void *curr;

View file

@ -61,10 +61,10 @@ _cairo_atomic_int_dec_and_test (cairo_atomic_int_t *x)
return ret; return ret;
} }
cairo_atomic_int_t int
_cairo_atomic_int_cmpxchg_return_old_impl (cairo_atomic_int_t *x, cairo_atomic_int_t oldv, cairo_atomic_int_t newv) _cairo_atomic_int_cmpxchg_return_old_impl (cairo_atomic_int_t *x, int oldv, int newv)
{ {
cairo_atomic_int_t ret; int ret;
CAIRO_MUTEX_LOCK (_cairo_atomic_mutex); CAIRO_MUTEX_LOCK (_cairo_atomic_mutex);
ret = *x; ret = *x;
@ -76,24 +76,24 @@ _cairo_atomic_int_cmpxchg_return_old_impl (cairo_atomic_int_t *x, cairo_atomic_i
} }
void * void *
_cairo_atomic_ptr_cmpxchg_return_old_impl (void **x, void *oldv, void *newv) _cairo_atomic_ptr_cmpxchg_return_old_impl (cairo_atomic_intptr_t *x, void *oldv, void *newv)
{ {
void *ret; void *ret;
CAIRO_MUTEX_LOCK (_cairo_atomic_mutex); CAIRO_MUTEX_LOCK (_cairo_atomic_mutex);
ret = *x; ret = (void *) *x;
if (ret == oldv) if (ret == oldv)
*x = newv; *x = (cairo_atomic_intptr_t) newv;
CAIRO_MUTEX_UNLOCK (_cairo_atomic_mutex); CAIRO_MUTEX_UNLOCK (_cairo_atomic_mutex);
return ret; return ret;
} }
#ifdef ATOMIC_OP_NEEDS_MEMORY_BARRIER #ifdef ATOMIC_OP_NEEDS_MEMORY_BARRIER
cairo_atomic_int_t int
_cairo_atomic_int_get (cairo_atomic_int_t *x) _cairo_atomic_int_get (cairo_atomic_int_t *x)
{ {
cairo_atomic_int_t ret; int ret;
CAIRO_MUTEX_LOCK (_cairo_atomic_mutex); CAIRO_MUTEX_LOCK (_cairo_atomic_mutex);
ret = *x; ret = *x;
@ -102,14 +102,14 @@ _cairo_atomic_int_get (cairo_atomic_int_t *x)
return ret; return ret;
} }
cairo_atomic_int_t int
_cairo_atomic_int_get_relaxed (cairo_atomic_int_t *x) _cairo_atomic_int_get_relaxed (cairo_atomic_int_t *x)
{ {
return _cairo_atomic_int_get (x); return _cairo_atomic_int_get (x);
} }
void void
_cairo_atomic_int_set_relaxed (cairo_atomic_int_t *x, cairo_atomic_int_t val) _cairo_atomic_int_set_relaxed (cairo_atomic_int_t *x, int val)
{ {
CAIRO_MUTEX_LOCK (_cairo_atomic_mutex); CAIRO_MUTEX_LOCK (_cairo_atomic_mutex);
*x = val; *x = val;

View file

@ -50,12 +50,12 @@ CAIRO_BEGIN_DECLS
*/ */
#define MAX_FREED_POOL_SIZE 16 #define MAX_FREED_POOL_SIZE 16
typedef struct { typedef struct {
void *pool[MAX_FREED_POOL_SIZE]; cairo_atomic_intptr_t pool[MAX_FREED_POOL_SIZE];
cairo_atomic_int_t top; cairo_atomic_int_t top;
} freed_pool_t; } freed_pool_t;
static cairo_always_inline void * static cairo_always_inline void *
_atomic_fetch (void **slot) _atomic_fetch (cairo_atomic_intptr_t *slot)
{ {
void *ptr; void *ptr;
@ -67,7 +67,7 @@ _atomic_fetch (void **slot)
} }
static cairo_always_inline cairo_bool_t static cairo_always_inline cairo_bool_t
_atomic_store (void **slot, void *ptr) _atomic_store (cairo_atomic_intptr_t *slot, void *ptr)
{ {
return _cairo_atomic_ptr_cmpxchg (slot, NULL, ptr); return _cairo_atomic_ptr_cmpxchg (slot, NULL, ptr);
} }

View file

@ -83,8 +83,7 @@ _freed_pool_reset (freed_pool_t *pool)
int i; int i;
for (i = 0; i < ARRAY_LENGTH (pool->pool); i++) { for (i = 0; i < ARRAY_LENGTH (pool->pool); i++) {
free (pool->pool[i]); free (_atomic_fetch (&pool->pool[i]));
pool->pool[i] = NULL;
} }
_cairo_atomic_int_set_relaxed (&pool->top, 0); _cairo_atomic_int_set_relaxed (&pool->top, 0);

View file

@ -803,12 +803,12 @@ get_C_locale (void)
locale_t C; locale_t C;
retry: retry:
C = (locale_t) _cairo_atomic_ptr_get ((void **) &C_locale); C = (locale_t) _cairo_atomic_ptr_get ((cairo_atomic_intptr_t *) &C_locale);
if (unlikely (!C)) { if (unlikely (!C)) {
C = newlocale (LC_ALL_MASK, "C", NULL); C = newlocale (LC_ALL_MASK, "C", NULL);
if (!_cairo_atomic_ptr_cmpxchg ((void **) &C_locale, NULL, C)) { if (!_cairo_atomic_ptr_cmpxchg ((cairo_atomic_intptr_t *) &C_locale, NULL, C)) {
freelocale (C_locale); freelocale (C_locale);
goto retry; goto retry;
} }

View file

@ -53,9 +53,15 @@ cairo_private void _cairo_mutex_finalize (void);
#endif #endif
/* only if using static initializer and/or finalizer define the boolean */ /* only if using static initializer and/or finalizer define the boolean */
#if _CAIRO_MUTEX_IMPL_USE_STATIC_INITIALIZER || _CAIRO_MUTEX_IMPL_USE_STATIC_FINALIZER #if _CAIRO_MUTEX_IMPL_USE_STATIC_INITIALIZER || _CAIRO_MUTEX_IMPL_USE_STATIC_FINALIZER
#if HAS_ATOMIC_OPS
cairo_private extern cairo_atomic_int_t _cairo_mutex_initialized;
#else
cairo_private extern int _cairo_mutex_initialized; cairo_private extern int _cairo_mutex_initialized;
#endif #endif
#endif
/* Finally, extern the static mutexes and undef */ /* Finally, extern the static mutexes and undef */
#define CAIRO_MUTEX_DECLARE(mutex) cairo_private extern cairo_mutex_t mutex; #define CAIRO_MUTEX_DECLARE(mutex) cairo_private extern cairo_mutex_t mutex;

View file

@ -51,7 +51,11 @@
# define _CAIRO_MUTEX_IMPL_INITIALIZED_DEFAULT_VALUE _CAIRO_MUTEX_INITIALIZED # define _CAIRO_MUTEX_IMPL_INITIALIZED_DEFAULT_VALUE _CAIRO_MUTEX_INITIALIZED
# endif # endif
#if HAS_ATOMIC_OPS
cairo_atomic_int_t _cairo_mutex_initialized = _CAIRO_MUTEX_IMPL_INITIALIZED_DEFAULT_VALUE;
#else
int _cairo_mutex_initialized = _CAIRO_MUTEX_IMPL_INITIALIZED_DEFAULT_VALUE; int _cairo_mutex_initialized = _CAIRO_MUTEX_IMPL_INITIALIZED_DEFAULT_VALUE;
#endif
# undef _CAIRO_MUTEX_IMPL_INITIALIZED_DEFAULT_VALUE # undef _CAIRO_MUTEX_IMPL_INITIALIZED_DEFAULT_VALUE

View file

@ -1735,7 +1735,7 @@ _cairo_recording_surface_regions_allocate_unique_id (void)
unique_id = 1; unique_id = 1;
return unique_id; return unique_id;
#else #else
cairo_atomic_int_t old, id; int old, id;
do { do {
old = _cairo_atomic_uint_get (&unique_id); old = _cairo_atomic_uint_get (&unique_id);

View file

@ -52,7 +52,7 @@ typedef struct {
#define CAIRO_REFERENCE_COUNT_GET_VALUE(RC) _cairo_atomic_int_get (&(RC)->ref_count) #define CAIRO_REFERENCE_COUNT_GET_VALUE(RC) _cairo_atomic_int_get (&(RC)->ref_count)
#define CAIRO_REFERENCE_COUNT_INVALID_VALUE ((cairo_atomic_int_t) -1) #define CAIRO_REFERENCE_COUNT_INVALID_VALUE ((int) -1)
#define CAIRO_REFERENCE_COUNT_INVALID {CAIRO_REFERENCE_COUNT_INVALID_VALUE} #define CAIRO_REFERENCE_COUNT_INVALID {CAIRO_REFERENCE_COUNT_INVALID_VALUE}
#define CAIRO_REFERENCE_COUNT_IS_INVALID(RC) (CAIRO_REFERENCE_COUNT_GET_VALUE (RC) == CAIRO_REFERENCE_COUNT_INVALID_VALUE) #define CAIRO_REFERENCE_COUNT_IS_INVALID(RC) (CAIRO_REFERENCE_COUNT_GET_VALUE (RC) == CAIRO_REFERENCE_COUNT_INVALID_VALUE)

View file

@ -277,7 +277,7 @@ _cairo_surface_allocate_unique_id (void)
unique_id = 1; unique_id = 1;
return unique_id; return unique_id;
#else #else
cairo_atomic_int_t old, id; int old, id;
do { do {
old = _cairo_atomic_uint_get (&unique_id); old = _cairo_atomic_uint_get (&unique_id);

View file

@ -136,7 +136,7 @@ _cairo_win32_device_get (void)
device->msimg32_dll = NULL; device->msimg32_dll = NULL;
device->alpha_blend = _cairo_win32_device_get_alpha_blend (device); device->alpha_blend = _cairo_win32_device_get_alpha_blend (device);
if (_cairo_atomic_ptr_cmpxchg ((void **)&__cairo_win32_device, NULL, device)) if (_cairo_atomic_ptr_cmpxchg ((cairo_atomic_intptr_t *)&__cairo_win32_device, NULL, device))
return cairo_device_reference(&device->base); return cairo_device_reference(&device->base);
_cairo_win32_device_destroy (device); _cairo_win32_device_destroy (device);