rtatomic.h 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. /*
  2. * Copyright (c) 2006-2023, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2023-03-14 WangShun first version
  9. * 2023-05-20 Bernard add stdc atomic detection.
  10. */
  11. #ifndef __RT_ATOMIC_H__
  12. #define __RT_ATOMIC_H__
  13. #if !defined(__cplusplus)
  14. rt_atomic_t rt_hw_atomic_load(volatile rt_atomic_t *ptr);
  15. void rt_hw_atomic_store(volatile rt_atomic_t *ptr, rt_atomic_t val);
  16. rt_atomic_t rt_hw_atomic_add(volatile rt_atomic_t *ptr, rt_atomic_t val);
  17. rt_atomic_t rt_hw_atomic_sub(volatile rt_atomic_t *ptr, rt_atomic_t val);
  18. rt_atomic_t rt_hw_atomic_and(volatile rt_atomic_t *ptr, rt_atomic_t val);
  19. rt_atomic_t rt_hw_atomic_or(volatile rt_atomic_t *ptr, rt_atomic_t val);
  20. rt_atomic_t rt_hw_atomic_xor(volatile rt_atomic_t *ptr, rt_atomic_t val);
  21. rt_atomic_t rt_hw_atomic_exchange(volatile rt_atomic_t *ptr, rt_atomic_t val);
  22. void rt_hw_atomic_flag_clear(volatile rt_atomic_t *ptr);
  23. rt_atomic_t rt_hw_atomic_flag_test_and_set(volatile rt_atomic_t *ptr);
  24. rt_atomic_t rt_hw_atomic_compare_exchange_strong(volatile rt_atomic_t *ptr, rt_atomic_t *expected, rt_atomic_t desired);
  25. /* To detect stdatomic */
  26. #if !defined(RT_USING_HW_ATOMIC) && !defined(RT_USING_STDC_ATOMIC)
  27. #if defined(__GNUC__) && defined(RT_USING_LIBC) && !defined(__STDC_NO_ATOMICS__)
  28. #define RT_USING_STDC_ATOMIC
  29. #endif /* __GNUC__ && .. */
  30. #endif /* !RT_USING_HW_ATOMIC && !RT_USING_STDC_ATOMIC */
  31. #if defined(RT_USING_HW_ATOMIC)
  32. #define rt_atomic_load(ptr) rt_hw_atomic_load(ptr)
  33. #define rt_atomic_store(ptr, v) rt_hw_atomic_store(ptr, v)
  34. #define rt_atomic_add(ptr, v) rt_hw_atomic_add(ptr, v)
  35. #define rt_atomic_sub(ptr, v) rt_hw_atomic_sub(ptr, v)
  36. #define rt_atomic_and(ptr, v) rt_hw_atomic_and(ptr, v)
  37. #define rt_atomic_or(ptr, v) rt_hw_atomic_or(ptr, v)
  38. #define rt_atomic_xor(ptr, v) rt_hw_atomic_xor(ptr, v)
  39. #define rt_atomic_exchange(ptr, v) rt_hw_atomic_exchange(ptr, v)
  40. #define rt_atomic_flag_clear(ptr) rt_hw_atomic_flag_clear(ptr)
  41. #define rt_atomic_flag_test_and_set(ptr) rt_hw_atomic_flag_test_and_set(ptr)
  42. #define rt_atomic_compare_exchange_strong(ptr, v,des) rt_hw_atomic_compare_exchange_strong(ptr, v ,des)
  43. #elif defined(RT_USING_STDC_ATOMIC)
  44. #ifndef __STDC_NO_ATOMICS__
  45. #define rt_atomic_load(ptr) atomic_load(ptr)
  46. #define rt_atomic_store(ptr, v) atomic_store(ptr, v)
  47. #define rt_atomic_add(ptr, v) atomic_fetch_add(ptr, v)
  48. #define rt_atomic_sub(ptr, v) atomic_fetch_sub(ptr, v)
  49. #define rt_atomic_and(ptr, v) atomic_fetch_and(ptr, v)
  50. #define rt_atomic_or(ptr, v) atomic_fetch_or(ptr, v)
  51. #define rt_atomic_xor(ptr, v) atomic_fetch_xor(ptr, v)
  52. #define rt_atomic_exchange(ptr, v) atomic_exchange(ptr, v)
  53. #define rt_atomic_flag_clear(ptr) atomic_flag_clear(ptr)
  54. #define rt_atomic_flag_test_and_set(ptr) atomic_flag_test_and_set(ptr)
  55. #define rt_atomic_compare_exchange_strong(ptr, v,des) atomic_compare_exchange_strong(ptr, v ,des)
  56. #else
  57. #error "The standard library C doesn't support the atomic operation"
  58. #endif /* __STDC_NO_ATOMICS__ */
  59. #else
  60. #include <rthw.h>
  61. #define rt_atomic_load(ptr) rt_soft_atomic_load(ptr)
  62. #define rt_atomic_store(ptr, v) rt_soft_atomic_store(ptr, v)
  63. #define rt_atomic_add(ptr, v) rt_soft_atomic_add(ptr, v)
  64. #define rt_atomic_sub(ptr, v) rt_soft_atomic_sub(ptr, v)
  65. #define rt_atomic_and(ptr, v) rt_soft_atomic_and(ptr, v)
  66. #define rt_atomic_or(ptr, v) rt_soft_atomic_or(ptr, v)
  67. #define rt_atomic_xor(ptr, v) rt_soft_atomic_xor(ptr, v)
  68. #define rt_atomic_exchange(ptr, v) rt_soft_atomic_exchange(ptr, v)
  69. #define rt_atomic_flag_clear(ptr) rt_soft_atomic_flag_clear(ptr)
  70. #define rt_atomic_flag_test_and_set(ptr) rt_soft_atomic_flag_test_and_set(ptr)
  71. #define rt_atomic_compare_exchange_strong(ptr, v,des) rt_soft_atomic_compare_exchange_strong(ptr, v ,des)
  72. rt_inline rt_atomic_t rt_soft_atomic_exchange(volatile rt_atomic_t *ptr, rt_atomic_t val)
  73. {
  74. rt_base_t level;
  75. rt_atomic_t temp;
  76. level = rt_hw_interrupt_disable();
  77. temp = *ptr;
  78. *ptr = val;
  79. rt_hw_interrupt_enable(level);
  80. return temp;
  81. }
  82. rt_inline rt_atomic_t rt_soft_atomic_add(volatile rt_atomic_t *ptr, rt_atomic_t val)
  83. {
  84. rt_base_t level;
  85. rt_atomic_t temp;
  86. level = rt_hw_interrupt_disable();
  87. temp = *ptr;
  88. *ptr += val;
  89. rt_hw_interrupt_enable(level);
  90. return temp;
  91. }
  92. rt_inline rt_atomic_t rt_soft_atomic_sub(volatile rt_atomic_t *ptr, rt_atomic_t val)
  93. {
  94. rt_base_t level;
  95. rt_atomic_t temp;
  96. level = rt_hw_interrupt_disable();
  97. temp = *ptr;
  98. *ptr -= val;
  99. rt_hw_interrupt_enable(level);
  100. return temp;
  101. }
  102. rt_inline rt_atomic_t rt_soft_atomic_xor(volatile rt_atomic_t *ptr, rt_atomic_t val)
  103. {
  104. rt_base_t level;
  105. rt_atomic_t temp;
  106. level = rt_hw_interrupt_disable();
  107. temp = *ptr;
  108. *ptr = (*ptr) ^ val;
  109. rt_hw_interrupt_enable(level);
  110. return temp;
  111. }
  112. rt_inline rt_atomic_t rt_soft_atomic_and(volatile rt_atomic_t *ptr, rt_atomic_t val)
  113. {
  114. rt_base_t level;
  115. rt_atomic_t temp;
  116. level = rt_hw_interrupt_disable();
  117. temp = *ptr;
  118. *ptr = (*ptr) & val;
  119. rt_hw_interrupt_enable(level);
  120. return temp;
  121. }
  122. rt_inline rt_atomic_t rt_soft_atomic_or(volatile rt_atomic_t *ptr, rt_atomic_t val)
  123. {
  124. rt_base_t level;
  125. rt_atomic_t temp;
  126. level = rt_hw_interrupt_disable();
  127. temp = *ptr;
  128. *ptr = (*ptr) | val;
  129. rt_hw_interrupt_enable(level);
  130. return temp;
  131. }
  132. rt_inline rt_atomic_t rt_soft_atomic_load(volatile rt_atomic_t *ptr)
  133. {
  134. rt_base_t level;
  135. rt_atomic_t temp;
  136. level = rt_hw_interrupt_disable();
  137. temp = *ptr;
  138. rt_hw_interrupt_enable(level);
  139. return temp;
  140. }
  141. rt_inline void rt_soft_atomic_store(volatile rt_atomic_t *ptr, rt_atomic_t val)
  142. {
  143. rt_base_t level;
  144. level = rt_hw_interrupt_disable();
  145. *ptr = val;
  146. rt_hw_interrupt_enable(level);
  147. }
  148. rt_inline rt_atomic_t rt_soft_atomic_flag_test_and_set(volatile rt_atomic_t *ptr)
  149. {
  150. rt_base_t level;
  151. rt_atomic_t temp;
  152. level = rt_hw_interrupt_disable();
  153. if (*ptr == 0)
  154. {
  155. temp = 0;
  156. *ptr = 1;
  157. }
  158. else
  159. temp = 1;
  160. rt_hw_interrupt_enable(level);
  161. return temp;
  162. }
  163. rt_inline void rt_soft_atomic_flag_clear(volatile rt_atomic_t *ptr)
  164. {
  165. rt_base_t level;
  166. level = rt_hw_interrupt_disable();
  167. *ptr = 0;
  168. rt_hw_interrupt_enable(level);
  169. }
  170. rt_inline rt_atomic_t rt_soft_atomic_compare_exchange_strong(volatile rt_atomic_t *ptr1, rt_atomic_t *ptr2,
  171. rt_atomic_t desired)
  172. {
  173. rt_base_t level;
  174. rt_atomic_t temp;
  175. level = rt_hw_interrupt_disable();
  176. if ((*ptr1) != (*ptr2))
  177. {
  178. *ptr2 = *ptr1;
  179. temp = 0;
  180. }
  181. else
  182. {
  183. *ptr1 = desired;
  184. temp = 1;
  185. }
  186. rt_hw_interrupt_enable(level);
  187. return temp;
  188. }
  189. #endif /* RT_USING_STDC_ATOMIC */
  190. #endif /* __cplusplus */
  191. #endif /* __RT_ATOMIC_H__ */