gc_atomic_ops.h 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. /*
  2. * Copyright (c) 2017 Ivan Maidanski
  3. *
  4. * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
  5. * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
  6. *
  7. * Permission is hereby granted to use or copy this program
  8. * for any purpose, provided the above notices are retained on all copies.
  9. * Permission to modify the code and to distribute modified code is granted,
  10. * provided the above notices are retained, and a notice that the code was
  11. * modified is included with the above copyright notice.
  12. */
  13. /* This is a private GC header which provides an implementation of */
  14. /* libatomic_ops subset primitives sufficient for GC assuming that C11 */
  15. /* atomic intrinsics are available (and have correct implementation). */
  16. /* This is enabled by defining GC_BUILTIN_ATOMIC macro. Otherwise, */
  17. /* libatomic_ops library is used to define the primitives. */
  18. #ifndef GC_ATOMIC_OPS_H
  19. #define GC_ATOMIC_OPS_H
  20. #ifdef GC_BUILTIN_ATOMIC
  21. # include "gc.h" /* for GC_word */
  22. # ifdef __cplusplus
  23. extern "C" {
  24. # endif
  25. typedef GC_word AO_t;
  26. # ifdef GC_PRIVATE_H /* have GC_INLINE */
  27. # define AO_INLINE GC_INLINE
  28. # else
  29. # define AO_INLINE static __inline
  30. # endif
  31. typedef unsigned char AO_TS_t;
  32. # define AO_TS_CLEAR 0
  33. # define AO_TS_INITIALIZER (AO_TS_t)AO_TS_CLEAR
  34. # if defined(__GCC_ATOMIC_TEST_AND_SET_TRUEVAL) && !defined(CPPCHECK)
  35. # define AO_TS_SET __GCC_ATOMIC_TEST_AND_SET_TRUEVAL
  36. # else
  37. # define AO_TS_SET (AO_TS_t)1 /* true */
  38. # endif
  39. # define AO_CLEAR(p) __atomic_clear(p, __ATOMIC_RELEASE)
  40. # define AO_test_and_set_acquire(p) __atomic_test_and_set(p, __ATOMIC_ACQUIRE)
  41. # define AO_HAVE_test_and_set_acquire
  42. # define AO_compiler_barrier() __atomic_signal_fence(__ATOMIC_SEQ_CST)
  43. # define AO_nop_full() __atomic_thread_fence(__ATOMIC_SEQ_CST)
  44. # define AO_HAVE_nop_full
  45. # define AO_fetch_and_add(p, v) __atomic_fetch_add(p, v, __ATOMIC_RELAXED)
  46. # define AO_HAVE_fetch_and_add
  47. # define AO_fetch_and_add1(p) AO_fetch_and_add(p, 1)
  48. # define AO_HAVE_fetch_and_add1
  49. # define AO_or(p, v) (void)__atomic_or_fetch(p, v, __ATOMIC_RELAXED)
  50. # define AO_HAVE_or
  51. # define AO_load(p) __atomic_load_n(p, __ATOMIC_RELAXED)
  52. # define AO_HAVE_load
  53. # define AO_load_acquire(p) __atomic_load_n(p, __ATOMIC_ACQUIRE)
  54. # define AO_HAVE_load_acquire
  55. # define AO_load_acquire_read(p) AO_load_acquire(p)
  56. # define AO_HAVE_load_acquire_read
  57. # define AO_store(p, v) __atomic_store_n(p, v, __ATOMIC_RELAXED)
  58. # define AO_HAVE_store
  59. # define AO_store_release(p, v) __atomic_store_n(p, v, __ATOMIC_RELEASE)
  60. # define AO_HAVE_store_release
  61. # define AO_store_release_write(p, v) AO_store_release(p, v)
  62. # define AO_HAVE_store_release_write
  63. # define AO_char_load(p) __atomic_load_n(p, __ATOMIC_RELAXED)
  64. # define AO_HAVE_char_load
  65. # define AO_char_store(p, v) __atomic_store_n(p, v, __ATOMIC_RELAXED)
  66. # define AO_HAVE_char_store
  67. # ifdef AO_REQUIRE_CAS
  68. AO_INLINE int
  69. AO_compare_and_swap(volatile AO_t *p, AO_t ov, AO_t nv)
  70. {
  71. return (int)__atomic_compare_exchange_n(p, &ov, nv, 0,
  72. __ATOMIC_RELAXED, __ATOMIC_RELAXED);
  73. }
  74. AO_INLINE int
  75. AO_compare_and_swap_release(volatile AO_t *p, AO_t ov, AO_t nv)
  76. {
  77. return (int)__atomic_compare_exchange_n(p, &ov, nv, 0,
  78. __ATOMIC_RELEASE, __ATOMIC_RELAXED);
  79. }
  80. # define AO_HAVE_compare_and_swap_release
  81. # endif
  82. # ifdef __cplusplus
  83. } /* extern "C" */
  84. # endif
  85. #elif !defined(NN_PLATFORM_CTR)
  86. /* Fallback to libatomic_ops. */
  87. # include "atomic_ops.h"
  88. /* AO_compiler_barrier, AO_load and AO_store should be defined for */
  89. /* all targets; the rest of the primitives are guaranteed to exist */
  90. /* only if AO_REQUIRE_CAS is defined (or if the corresponding */
  91. /* AO_HAVE_x macro is defined). x86/x64 targets have AO_nop_full, */
  92. /* AO_load_acquire, AO_store_release, at least. */
  93. # if !defined(AO_HAVE_load) || !defined(AO_HAVE_store)
  94. # error AO_load or AO_store is missing; probably old version of atomic_ops
  95. # endif
  96. #endif /* !GC_BUILTIN_ATOMIC */
  97. #endif /* GC_ATOMIC_OPS_H */