468663ddbb
Former-commit-id: 1d6753294b2993e1fbf92de9366bb9544db4189b
119 lines
4.0 KiB
C
119 lines
4.0 KiB
C
/*
|
|
* 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 C11 */
|
|
/* 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)
|
|
# 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
|
|
|
|
#elif !defined(NN_PLATFORM_CTR)
|
|
/* 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)
|
|
# error AO_load or AO_store is missing; probably old version of atomic_ops
|
|
# endif
|
|
|
|
#endif /* !GC_BUILTIN_ATOMIC */
|
|
|
|
#endif /* GC_ATOMIC_OPS_H */
|