atomics-internal.h 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. #ifndef SCM_ATOMICS_INTERNAL_H
  2. #define SCM_ATOMICS_INTERNAL_H
  3. /* Copyright 2016,2018-2019
  4. Free Software Foundation, Inc.
  5. This file is part of Guile.
  6. Guile is free software: you can redistribute it and/or modify it
  7. under the terms of the GNU Lesser General Public License as published
  8. by the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. Guile is distributed in the hope that it will be useful, but WITHOUT
  11. ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12. FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
  13. License for more details.
  14. You should have received a copy of the GNU Lesser General Public
  15. License along with Guile. If not, see
  16. <https://www.gnu.org/licenses/>. */
  17. #include "scm.h"
  18. #ifdef HAVE_STDATOMIC_H
  19. #include <stdatomic.h>
  20. static inline uint32_t
  21. scm_atomic_subtract_uint32 (uint32_t *loc, uint32_t arg)
  22. {
  23. atomic_uint_least32_t *a_loc = (atomic_uint_least32_t *) loc;
  24. return atomic_fetch_sub (a_loc, arg);
  25. }
  26. static inline _Bool
  27. scm_atomic_compare_and_swap_uint32 (uint32_t *loc, uint32_t *expected,
  28. uint32_t desired)
  29. {
  30. atomic_uint_least32_t *a_loc = (atomic_uint_least32_t *) loc;
  31. return atomic_compare_exchange_weak (a_loc, expected, desired);
  32. }
  33. static inline void
  34. scm_atomic_set_pointer (void **loc, void *val)
  35. {
  36. atomic_uintptr_t *a_loc = (atomic_uintptr_t *) loc;
  37. atomic_store (a_loc, (uintptr_t) val);
  38. }
  39. static inline void *
  40. scm_atomic_ref_pointer (void **loc)
  41. {
  42. atomic_uintptr_t *a_loc = (atomic_uintptr_t *) loc;
  43. return (void *) atomic_load (a_loc);
  44. }
  45. static inline void
  46. scm_atomic_set_scm (SCM *loc, SCM val)
  47. {
  48. atomic_uintptr_t *a_loc = (atomic_uintptr_t *) loc;
  49. atomic_store (a_loc, SCM_UNPACK (val));
  50. }
  51. static inline SCM
  52. scm_atomic_ref_scm (SCM *loc)
  53. {
  54. atomic_uintptr_t *a_loc = (atomic_uintptr_t *) loc;
  55. return SCM_PACK (atomic_load (a_loc));
  56. }
  57. static inline SCM
  58. scm_atomic_swap_scm (SCM *loc, SCM val)
  59. {
  60. atomic_uintptr_t *a_loc = (atomic_uintptr_t *) loc;
  61. return SCM_PACK (atomic_exchange (a_loc, SCM_UNPACK (val)));
  62. }
  63. static inline SCM
  64. scm_atomic_compare_and_swap_scm (SCM *loc, SCM expected, SCM desired)
  65. {
  66. atomic_uintptr_t *a_loc = (atomic_uintptr_t *) loc;
  67. SCM result = expected;
  68. atomic_compare_exchange_strong (a_loc, (uintptr_t *) &result,
  69. SCM_UNPACK (desired));
  70. return result;
  71. }
  72. #else /* HAVE_STDATOMIC_H */
  73. /* Fallback implementation using locks. */
  74. #include "libguile/threads.h"
  75. static scm_i_pthread_mutex_t atomics_lock = SCM_I_PTHREAD_MUTEX_INITIALIZER;
  76. static inline uint32_t
  77. scm_atomic_subtract_uint32 (uint32_t *loc, uint32_t arg)
  78. {
  79. uint32_t ret;
  80. scm_i_pthread_mutex_lock (&atomics_lock);
  81. ret = *loc;
  82. *loc -= arg;
  83. scm_i_pthread_mutex_unlock (&atomics_lock);
  84. return ret;
  85. }
  86. static inline int
  87. scm_atomic_compare_and_swap_uint32 (uint32_t *loc, uint32_t *expected,
  88. uint32_t desired)
  89. {
  90. int ret;
  91. scm_i_pthread_mutex_lock (&atomics_lock);
  92. if (*loc == *expected)
  93. {
  94. *loc = desired;
  95. ret = 1;
  96. }
  97. else
  98. {
  99. *expected = *loc;
  100. ret = 0;
  101. }
  102. scm_i_pthread_mutex_unlock (&atomics_lock);
  103. return ret;
  104. }
  105. static inline void
  106. scm_atomic_set_pointer (void **loc, void *val)
  107. {
  108. scm_i_pthread_mutex_lock (&atomics_lock);
  109. *loc = val;
  110. scm_i_pthread_mutex_unlock (&atomics_lock);
  111. }
  112. static inline void *
  113. scm_atomic_ref_pointer (void **loc)
  114. {
  115. void *ret;
  116. scm_i_pthread_mutex_lock (&atomics_lock);
  117. ret = *loc;
  118. scm_i_pthread_mutex_unlock (&atomics_lock);
  119. return ret;
  120. }
  121. static inline void
  122. scm_atomic_set_scm (SCM *loc, SCM val)
  123. {
  124. scm_i_pthread_mutex_lock (&atomics_lock);
  125. *loc = val;
  126. scm_i_pthread_mutex_unlock (&atomics_lock);
  127. }
  128. static inline SCM
  129. scm_atomic_ref_scm (SCM *loc)
  130. {
  131. SCM ret;
  132. scm_i_pthread_mutex_lock (&atomics_lock);
  133. ret = *loc;
  134. scm_i_pthread_mutex_unlock (&atomics_lock);
  135. return ret;
  136. }
  137. static inline SCM
  138. scm_atomic_swap_scm (SCM *loc, SCM val)
  139. {
  140. SCM ret;
  141. scm_i_pthread_mutex_lock (&atomics_lock);
  142. ret = *loc;
  143. *loc = val;
  144. scm_i_pthread_mutex_unlock (&atomics_lock);
  145. return ret;
  146. }
  147. static inline SCM
  148. scm_atomic_compare_and_swap_scm (SCM *loc, SCM expected, SCM desired)
  149. {
  150. SCM ret;
  151. scm_i_pthread_mutex_lock (&atomics_lock);
  152. if (*loc == expected)
  153. {
  154. *loc = desired;
  155. ret = expected;
  156. }
  157. else
  158. {
  159. ret = *loc;
  160. }
  161. scm_i_pthread_mutex_unlock (&atomics_lock);
  162. return ret;
  163. }
  164. #endif /* HAVE_STDATOMIC_H */
  165. #endif /* SCM_ATOMICS_INTERNAL_H */