rtatomic.h 6.2 KB

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