generic.h 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. /*
  2. * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved.
  3. * Copyright (c) 1996-1999 by Silicon Graphics. All rights reserved.
  4. * Copyright (c) 2003-2011 Hewlett-Packard Development Company, L.P.
  5. *
  6. *
  7. * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
  8. * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
  9. *
  10. * Permission is hereby granted to use or copy this program
  11. * for any purpose, provided the above notices are retained on all copies.
  12. * Permission to modify the code and to distribute modified code is granted,
  13. * provided the above notices are retained, and a notice that the code was
  14. * modified is included with the above copyright notice.
  15. *
  16. */
  17. /* The following implementation assumes GCC 4.7 or later. */
  18. /* For the details, see GNU Manual, chapter 6.52 (Built-in functions */
  19. /* for memory model aware atomic operations). */
  20. /* TODO: Include this file for other targets if gcc 4.7+ */
  21. #ifdef AO_UNIPROCESSOR
  22. /* If only a single processor (core) is used, AO_UNIPROCESSOR could */
  23. /* be defined by the client to avoid unnecessary memory barrier. */
  24. AO_INLINE void
  25. AO_nop_full(void)
  26. {
  27. AO_compiler_barrier();
  28. }
  29. # define AO_HAVE_nop_full
  30. #else
  31. AO_INLINE void
  32. AO_nop_read(void)
  33. {
  34. __atomic_thread_fence(__ATOMIC_ACQUIRE);
  35. }
  36. # define AO_HAVE_nop_read
  37. # ifndef AO_HAVE_nop_write
  38. AO_INLINE void
  39. AO_nop_write(void)
  40. {
  41. __atomic_thread_fence(__ATOMIC_RELEASE);
  42. }
  43. # define AO_HAVE_nop_write
  44. # endif
  45. AO_INLINE void
  46. AO_nop_full(void)
  47. {
  48. /* __sync_synchronize() could be used instead. */
  49. __atomic_thread_fence(__ATOMIC_SEQ_CST);
  50. }
  51. # define AO_HAVE_nop_full
  52. #endif /* !AO_UNIPROCESSOR */
  53. #include "generic-small.h"
  54. #ifndef AO_PREFER_GENERALIZED
  55. # include "generic-arithm.h"
  56. AO_INLINE AO_TS_VAL_t
  57. AO_test_and_set(volatile AO_TS_t *addr)
  58. {
  59. return (AO_TS_VAL_t)__atomic_test_and_set(addr, __ATOMIC_RELAXED);
  60. }
  61. # define AO_HAVE_test_and_set
  62. AO_INLINE AO_TS_VAL_t
  63. AO_test_and_set_acquire(volatile AO_TS_t *addr)
  64. {
  65. return (AO_TS_VAL_t)__atomic_test_and_set(addr, __ATOMIC_ACQUIRE);
  66. }
  67. # define AO_HAVE_test_and_set_acquire
  68. AO_INLINE AO_TS_VAL_t
  69. AO_test_and_set_release(volatile AO_TS_t *addr)
  70. {
  71. return (AO_TS_VAL_t)__atomic_test_and_set(addr, __ATOMIC_RELEASE);
  72. }
  73. # define AO_HAVE_test_and_set_release
  74. AO_INLINE AO_TS_VAL_t
  75. AO_test_and_set_full(volatile AO_TS_t *addr)
  76. {
  77. return (AO_TS_VAL_t)__atomic_test_and_set(addr, __ATOMIC_SEQ_CST);
  78. }
  79. # define AO_HAVE_test_and_set_full
  80. #endif /* !AO_PREFER_GENERALIZED */
  81. #ifdef AO_HAVE_DOUBLE_PTR_STORAGE
  82. # ifndef AO_HAVE_double_load
  83. AO_INLINE AO_double_t
  84. AO_double_load(const volatile AO_double_t *addr)
  85. {
  86. AO_double_t result;
  87. result.AO_whole = __atomic_load_n(&addr->AO_whole, __ATOMIC_RELAXED);
  88. return result;
  89. }
  90. # define AO_HAVE_double_load
  91. # endif
  92. # ifndef AO_HAVE_double_load_acquire
  93. AO_INLINE AO_double_t
  94. AO_double_load_acquire(const volatile AO_double_t *addr)
  95. {
  96. AO_double_t result;
  97. result.AO_whole = __atomic_load_n(&addr->AO_whole, __ATOMIC_ACQUIRE);
  98. return result;
  99. }
  100. # define AO_HAVE_double_load_acquire
  101. # endif
  102. # ifndef AO_HAVE_double_store
  103. AO_INLINE void
  104. AO_double_store(volatile AO_double_t *addr, AO_double_t value)
  105. {
  106. __atomic_store_n(&addr->AO_whole, value.AO_whole, __ATOMIC_RELAXED);
  107. }
  108. # define AO_HAVE_double_store
  109. # endif
  110. # ifndef AO_HAVE_double_store_release
  111. AO_INLINE void
  112. AO_double_store_release(volatile AO_double_t *addr, AO_double_t value)
  113. {
  114. __atomic_store_n(&addr->AO_whole, value.AO_whole, __ATOMIC_RELEASE);
  115. }
  116. # define AO_HAVE_double_store_release
  117. # endif
  118. # ifndef AO_HAVE_double_compare_and_swap
  119. AO_INLINE int
  120. AO_double_compare_and_swap(volatile AO_double_t *addr,
  121. AO_double_t old_val, AO_double_t new_val)
  122. {
  123. return (int)__atomic_compare_exchange_n(&addr->AO_whole,
  124. &old_val.AO_whole /* p_expected */,
  125. new_val.AO_whole /* desired */,
  126. 0 /* is_weak: false */,
  127. __ATOMIC_RELAXED /* success */,
  128. __ATOMIC_RELAXED /* failure */);
  129. }
  130. # define AO_HAVE_double_compare_and_swap
  131. # endif
  132. /* TODO: Add double CAS _acquire/release/full primitives. */
  133. #endif /* AO_HAVE_DOUBLE_PTR_STORAGE */