mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-05-15 19:38:04 +02:00
Merge branch 'atomics' into 'master'
Rework atomics configurations Closes #932 See merge request cairo/cairo!652
This commit is contained in:
commit
019e668e1b
2 changed files with 68 additions and 33 deletions
38
meson.build
38
meson.build
|
|
@ -766,22 +766,28 @@ endforeach
|
|||
|
||||
extra_link_args += pthread_link_args
|
||||
|
||||
# Atomics are an optional feature in C11. Also need to check that C11 atomics are lock free.
|
||||
# On Windows we use the Interlocked family of functions
|
||||
if host_machine.system() != 'windows'
|
||||
if 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)
|
||||
elif cc.links(files('meson-cc-tests/atomic-ops-gcc-legacy.c'), name: 'Atomic ops: gcc legacy')
|
||||
conf.set('HAVE_GCC_LEGACY_ATOMICS', 1)
|
||||
elif cc.has_header('atomic_ops.h')
|
||||
conf.set('HAVE_LIB_ATOMIC_OPS', 1)
|
||||
elif cc.has_header('libkern/OSAtomic.h')
|
||||
conf.set('HAVE_OS_ATOMIC_OPS', 1)
|
||||
else
|
||||
warning('Atomic ops not supported.')
|
||||
endif
|
||||
cpp_enabled = host_machine.system() == 'windows'
|
||||
|
||||
if not cpp_enabled and cc.links(files('meson-cc-tests/atomic-ops-c11.c'), name: 'Atomic ops: c11')
|
||||
# Currently we avoid C11 atomics when using both C and C++. The standards
|
||||
# do not guarantee compatibility between C11 atomics and C++11 std::atomic
|
||||
# (though effort is underway, see C++/N2741). We can enable this for selected
|
||||
# compilers over time.
|
||||
#
|
||||
# When not using C++, check if C11 atomics are available and whether atomic
|
||||
# ints and pointers are lock-free.
|
||||
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)
|
||||
elif cc.links(files('meson-cc-tests/atomic-ops-gcc-legacy.c'), name: 'Atomic ops: gcc legacy')
|
||||
conf.set('HAVE_GCC_LEGACY_ATOMICS', 1)
|
||||
elif host_machine.system() != 'windows' and dependency('atomic_ops', required: false).found()
|
||||
internal_deps += [dependency('atomic_ops')]
|
||||
conf.set('HAVE_LIB_ATOMIC_OPS', 1)
|
||||
elif host_machine.system() == 'darwin' and cc.has_header('libkern/OSAtomic.h')
|
||||
conf.set('HAVE_OS_ATOMIC_OPS', 1)
|
||||
elif not cc.has_define('_MSC_VER')
|
||||
warning('Atomic ops not supported.')
|
||||
endif
|
||||
|
||||
test_mkdir_c_args = []
|
||||
|
|
|
|||
|
|
@ -274,26 +274,35 @@ _cairo_atomic_ptr_get (cairo_atomic_intptr_t *x)
|
|||
#endif /* HAVE_GCC_LEGACY_ATOMICS */
|
||||
|
||||
#if HAVE_LIB_ATOMIC_OPS
|
||||
|
||||
#include <atomic_ops.h>
|
||||
#include <limits.h>
|
||||
|
||||
#define HAS_ATOMIC_OPS 1
|
||||
|
||||
typedef AO_t cairo_atomic_int_t;
|
||||
typedef int cairo_atomic_int_t;
|
||||
|
||||
# define _cairo_atomic_int_get(x) (AO_load_full (x))
|
||||
# define _cairo_atomic_int_get_relaxed(x) (AO_load_full (x))
|
||||
# define _cairo_atomic_int_set_relaxed(x, val) (AO_store_full ((x), (val)))
|
||||
/* Casts from signed to unsigned must not change representation */
|
||||
static_assert((unsigned)-1 == UINT_MAX,
|
||||
"We require two's complement representation of signed integrals");
|
||||
|
||||
# define _cairo_atomic_int_inc(x) ((void) AO_fetch_and_add1_full(x))
|
||||
# define _cairo_atomic_int_dec(x) ((void) AO_fetch_and_sub1_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) AO_compare_and_swap_full(x, oldv, newv)
|
||||
# define _cairo_atomic_int_get(x) ((int)AO_int_load_full ((unsigned *)(x)))
|
||||
# define _cairo_atomic_int_get_relaxed(x) ((int)AO_int_load ((unsigned *)(x)))
|
||||
# define _cairo_atomic_int_set_relaxed(x, val) (AO_int_store ((unsigned *)(x), (unsigned)(val)))
|
||||
|
||||
typedef intptr_t cairo_atomic_intptr_t;
|
||||
# define _cairo_atomic_int_inc(x) ((void) AO_int_fetch_and_add1_full((unsigned *)(x)))
|
||||
# define _cairo_atomic_int_dec(x) ((void) AO_int_fetch_and_sub1_full((unsigned *)(x)))
|
||||
# define _cairo_atomic_int_dec_and_test(x) (AO_int_fetch_and_sub1_full((unsigned *)(x)) == 1U)
|
||||
# define _cairo_atomic_int_cmpxchg(x, oldv, newv) AO_int_compare_and_swap_full((unsigned *)x, (unsigned)(oldv), (unsigned)(newv))
|
||||
# define _cairo_atomic_int_cmpxchg_return_old(x, oldv, newv) AO_int_fetch_compare_and_swap_full((unsigned *)x, (unsigned)(oldv), (unsigned)(newv))
|
||||
|
||||
typedef AO_t cairo_atomic_intptr_t;
|
||||
|
||||
static_assert (sizeof (AO_t) >= sizeof (void *), "AO_t cannot be used for pointers");
|
||||
|
||||
# define _cairo_atomic_ptr_get(x) _cairo_atomic_intptr_to_voidptr (AO_load_full (x))
|
||||
# define _cairo_atomic_ptr_cmpxchg(x, oldv, newv) \
|
||||
_cairo_atomic_int_cmpxchg ((cairo_atomic_intptr_t*)(x), (cairo_atomic_intptr_t)oldv, (cairo_atomic_intptr_t)newv)
|
||||
# define _cairo_atomic_ptr_cmpxchg(x, oldv, newv) AO_compare_and_swap_full(x, (AO_t)oldv, (AO_t)newv)
|
||||
# define _cairo_atomic_ptr_cmpxchg_return_old(x, oldv, newv) AO_fetch_compare_and_swap_full(x, (AO_t)oldv, (AO_t)newv)
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -330,7 +339,7 @@ typedef intptr_t cairo_atomic_intptr_t;
|
|||
|
||||
#endif /* HAVE_OS_ATOMIC_OPS */
|
||||
|
||||
#if !defined(HAS_ATOMIC_OPS) && defined(_WIN32)
|
||||
#if !defined(HAS_ATOMIC_OPS) && defined(_MSC_VER)
|
||||
#include <windows.h>
|
||||
|
||||
#define HAS_ATOMIC_OPS 1
|
||||
|
|
@ -353,13 +362,27 @@ _cairo_atomic_int_get (cairo_atomic_int_t *x)
|
|||
# define _cairo_atomic_int_dec_and_test(x) (InterlockedDecrement (x) == 0)
|
||||
|
||||
static cairo_always_inline cairo_bool_t
|
||||
_cairo_atomic_int_cmpxchg (cairo_atomic_int_t *x,
|
||||
int oldv,
|
||||
int newv)
|
||||
_cairo_atomic_int_cmpxchg_impl (cairo_atomic_int_t *x,
|
||||
int oldv,
|
||||
int newv)
|
||||
{
|
||||
return InterlockedCompareExchange (x, (LONG)newv, (LONG)oldv) == oldv;
|
||||
}
|
||||
|
||||
#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)
|
||||
{
|
||||
return (int) InterlockedCompareExchange (x, (LONG)newv, (LONG)oldv);
|
||||
}
|
||||
|
||||
#define _cairo_atomic_int_cmpxchg_return_old(x, oldv, newv) \
|
||||
_cairo_atomic_int_cmpxchg_return_old_impl(x, oldv, newv)
|
||||
|
||||
static cairo_always_inline void *
|
||||
_cairo_atomic_ptr_get (cairo_atomic_intptr_t *x)
|
||||
{
|
||||
|
|
@ -368,17 +391,23 @@ _cairo_atomic_ptr_get (cairo_atomic_intptr_t *x)
|
|||
}
|
||||
|
||||
static cairo_always_inline cairo_bool_t
|
||||
_cairo_atomic_ptr_cmpxchg (cairo_atomic_intptr_t *x, void *oldv, void *newv)
|
||||
_cairo_atomic_ptr_cmpxchg_impl (cairo_atomic_intptr_t *x, void *oldv, void *newv)
|
||||
{
|
||||
return InterlockedCompareExchangePointer (x, newv, oldv) == oldv;
|
||||
}
|
||||
|
||||
#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 (cairo_atomic_intptr_t *x, void *oldv, void *newv)
|
||||
_cairo_atomic_ptr_cmpxchg_return_old_impl (cairo_atomic_intptr_t *x, void *oldv, void *newv)
|
||||
{
|
||||
return InterlockedCompareExchangePointer (x, newv, oldv);
|
||||
}
|
||||
|
||||
#define _cairo_atomic_ptr_cmpxchg_return_old(x, oldv, newv) \
|
||||
_cairo_atomic_ptr_cmpxchg_return_old_impl(x, oldv, newv)
|
||||
|
||||
#endif /* !defined(HAS_ATOMIC_OPS) && defined(_WIN32) */
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue