summaryrefslogtreecommitdiff
path: root/graphics/asymptote/gc/include/private/gc_atomic_ops.h
diff options
context:
space:
mode:
Diffstat (limited to 'graphics/asymptote/gc/include/private/gc_atomic_ops.h')
-rw-r--r--graphics/asymptote/gc/include/private/gc_atomic_ops.h124
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 */