mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2025-12-20 05:50:10 +01:00
Add support for C11 atomics
This commit is contained in:
parent
8d0650bb60
commit
87f7c60bf7
13 changed files with 184 additions and 74 deletions
12
meson-cc-tests/atomic-ops-c11.c
Normal file
12
meson-cc-tests/atomic-ops-c11.c
Normal 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; }
|
||||||
|
|
@ -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 = []
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue