atomics-internal.h 4.6 KB

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