diff options
Diffstat (limited to 'graphics/asymptote/gc/include/private/gc_atomic_ops.h')
-rw-r--r-- | graphics/asymptote/gc/include/private/gc_atomic_ops.h | 124 |
1 files changed, 124 insertions, 0 deletions
diff --git a/graphics/asymptote/gc/include/private/gc_atomic_ops.h b/graphics/asymptote/gc/include/private/gc_atomic_ops.h new file mode 100644 index 0000000000..eaa28cb191 --- /dev/null +++ b/graphics/asymptote/gc/include/private/gc_atomic_ops.h @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2017 Ivan Maidanski + * + * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED + * OR IMPLIED. ANY USE IS AT YOUR OWN RISK. + * + * Permission is hereby granted to use or copy this program + * for any purpose, provided the above notices are retained on all copies. + * Permission to modify the code and to distribute modified code is granted, + * provided the above notices are retained, and a notice that the code was + * modified is included with the above copyright notice. + */ + +/* This is a private GC header which provides an implementation of */ +/* libatomic_ops subset primitives sufficient for GC assuming that GCC */ +/* atomic intrinsics are available (and have correct implementation). */ +/* This is enabled by defining GC_BUILTIN_ATOMIC macro. Otherwise, */ +/* libatomic_ops library is used to define the primitives. */ + +#ifndef GC_ATOMIC_OPS_H +#define GC_ATOMIC_OPS_H + +#ifdef GC_BUILTIN_ATOMIC + +# include "gc.h" /* for GC_word */ + +# ifdef __cplusplus + extern "C" { +# endif + + typedef GC_word AO_t; + +# ifdef GC_PRIVATE_H /* have GC_INLINE */ +# define AO_INLINE GC_INLINE +# else +# define AO_INLINE static __inline +# endif + + typedef unsigned char AO_TS_t; +# define AO_TS_CLEAR 0 +# define AO_TS_INITIALIZER (AO_TS_t)AO_TS_CLEAR +# if defined(__GCC_ATOMIC_TEST_AND_SET_TRUEVAL) && !defined(CPPCHECK) +# define AO_TS_SET __GCC_ATOMIC_TEST_AND_SET_TRUEVAL +# else +# define AO_TS_SET (AO_TS_t)1 /* true */ +# endif +# define AO_CLEAR(p) __atomic_clear(p, __ATOMIC_RELEASE) +# define AO_test_and_set_acquire(p) \ + (__atomic_test_and_set(p, __ATOMIC_ACQUIRE) ? AO_TS_SET : AO_TS_CLEAR) +# define AO_HAVE_test_and_set_acquire + +# define AO_compiler_barrier() __atomic_signal_fence(__ATOMIC_SEQ_CST) +# define AO_nop_full() __atomic_thread_fence(__ATOMIC_SEQ_CST) +# define AO_HAVE_nop_full + +# define AO_fetch_and_add(p, v) __atomic_fetch_add(p, v, __ATOMIC_RELAXED) +# define AO_HAVE_fetch_and_add +# define AO_fetch_and_add1(p) AO_fetch_and_add(p, 1) +# define AO_HAVE_fetch_and_add1 + +# define AO_or(p, v) (void)__atomic_or_fetch(p, v, __ATOMIC_RELAXED) +# define AO_HAVE_or + +# define AO_load(p) __atomic_load_n(p, __ATOMIC_RELAXED) +# define AO_HAVE_load +# define AO_load_acquire(p) __atomic_load_n(p, __ATOMIC_ACQUIRE) +# define AO_HAVE_load_acquire +# define AO_load_acquire_read(p) AO_load_acquire(p) +# define AO_HAVE_load_acquire_read + +# define AO_store(p, v) __atomic_store_n(p, v, __ATOMIC_RELAXED) +# define AO_HAVE_store +# define AO_store_release(p, v) __atomic_store_n(p, v, __ATOMIC_RELEASE) +# define AO_HAVE_store_release +# define AO_store_release_write(p, v) AO_store_release(p, v) +# define AO_HAVE_store_release_write + +# define AO_char_load(p) __atomic_load_n(p, __ATOMIC_RELAXED) +# define AO_HAVE_char_load +# define AO_char_store(p, v) __atomic_store_n(p, v, __ATOMIC_RELAXED) +# define AO_HAVE_char_store + +# ifdef AO_REQUIRE_CAS + AO_INLINE int + AO_compare_and_swap(volatile AO_t *p, AO_t ov, AO_t nv) + { + return (int)__atomic_compare_exchange_n(p, &ov, nv, 0, + __ATOMIC_RELAXED, __ATOMIC_RELAXED); + } + + AO_INLINE int + AO_compare_and_swap_release(volatile AO_t *p, AO_t ov, AO_t nv) + { + return (int)__atomic_compare_exchange_n(p, &ov, nv, 0, + __ATOMIC_RELEASE, __ATOMIC_RELAXED); + } +# define AO_HAVE_compare_and_swap_release +# endif + +# ifdef __cplusplus + } /* extern "C" */ +# endif + +# ifndef NO_LOCKFREE_AO_OR + /* __atomic_or_fetch is assumed to be lock-free. */ +# define HAVE_LOCKFREE_AO_OR 1 +# endif + +#else + /* Fallback to libatomic_ops. */ +# include "atomic_ops.h" + + /* AO_compiler_barrier, AO_load and AO_store should be defined for */ + /* all targets; the rest of the primitives are guaranteed to exist */ + /* only if AO_REQUIRE_CAS is defined (or if the corresponding */ + /* AO_HAVE_x macro is defined). x86/x64 targets have AO_nop_full, */ + /* AO_load_acquire, AO_store_release, at least. */ +# if (!defined(AO_HAVE_load) || !defined(AO_HAVE_store)) && !defined(CPPCHECK) +# error AO_load or AO_store is missing; probably old version of atomic_ops +# endif + +#endif /* !GC_BUILTIN_ATOMIC */ + +#endif /* GC_ATOMIC_OPS_H */ |