rtatomic.h 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. /**
  2. * RT-Thread RuiChing
  3. *
  4. * COPYRIGHT (C) 2024-2025 Shanghai Real-Thread Electronic Technology Co., Ltd.
  5. * All rights reserved.
  6. *
  7. * The license and distribution terms for this file may be
  8. * found in the file LICENSE in this distribution.
  9. */
  10. #ifndef __RTATOMIC_H__
  11. #define __RTATOMIC_H__
  12. #include <rthw.h>
  13. #include <kpi.h>
  14. typedef rt_atomic_t (*__kpi_rt_atomic_load)(volatile rt_atomic_t *ptr);
  15. typedef void (*__kpi_rt_atomic_store)(volatile rt_atomic_t *ptr,
  16. rt_atomic_t val);
  17. typedef rt_atomic_t (*__kpi_rt_atomic_add)(volatile rt_atomic_t *ptr,
  18. rt_atomic_t val);
  19. typedef rt_atomic_t (*__kpi_rt_atomic_sub)(volatile rt_atomic_t *ptr,
  20. rt_atomic_t val);
  21. typedef rt_atomic_t (*__kpi_rt_atomic_and)(volatile rt_atomic_t *ptr,
  22. rt_atomic_t val);
  23. typedef rt_atomic_t (*__kpi_rt_atomic_or)(volatile rt_atomic_t *ptr,
  24. rt_atomic_t val);
  25. typedef rt_atomic_t (*__kpi_rt_atomic_xor)(volatile rt_atomic_t *ptr,
  26. rt_atomic_t val);
  27. typedef rt_atomic_t (*__kpi_rt_atomic_exchange)(volatile rt_atomic_t *ptr,
  28. rt_atomic_t val);
  29. typedef void (*__kpi_rt_atomic_flag_clear)(volatile rt_atomic_t *ptr);
  30. typedef rt_atomic_t (*__kpi_rt_atomic_flag_test_and_set)(volatile
  31. rt_atomic_t *ptr);
  32. typedef rt_atomic_t (*__kpi_rt_atomic_compare_exchange_strong)(volatile
  33. rt_atomic_t *ptr,
  34. rt_atomic_t *expected, rt_atomic_t desired);
  35. KPI_EXTERN(rt_atomic_load);
  36. KPI_EXTERN(rt_atomic_store);
  37. KPI_EXTERN(rt_atomic_add);
  38. KPI_EXTERN(rt_atomic_sub);
  39. KPI_EXTERN(rt_atomic_and);
  40. KPI_EXTERN(rt_atomic_or);
  41. KPI_EXTERN(rt_atomic_xor);
  42. KPI_EXTERN(rt_atomic_exchange);
  43. KPI_EXTERN(rt_atomic_flag_clear);
  44. KPI_EXTERN(rt_atomic_flag_test_and_set);
  45. KPI_EXTERN(rt_atomic_compare_exchange_strong);
  46. rt_inline rt_atomic_t rt_soft_atomic_exchange(volatile rt_atomic_t *ptr,
  47. rt_atomic_t val)
  48. {
  49. rt_base_t level;
  50. rt_atomic_t temp;
  51. level = rt_hw_interrupt_disable();
  52. temp = *ptr;
  53. *ptr = val;
  54. rt_hw_interrupt_enable(level);
  55. return temp;
  56. }
  57. rt_inline rt_atomic_t rt_soft_atomic_add(volatile rt_atomic_t *ptr,
  58. rt_atomic_t val)
  59. {
  60. rt_base_t level;
  61. rt_atomic_t temp;
  62. level = rt_hw_interrupt_disable();
  63. temp = *ptr;
  64. *ptr += val;
  65. rt_hw_interrupt_enable(level);
  66. return temp;
  67. }
  68. rt_inline rt_atomic_t rt_soft_atomic_sub(volatile rt_atomic_t *ptr,
  69. rt_atomic_t val)
  70. {
  71. rt_base_t level;
  72. rt_atomic_t temp;
  73. level = rt_hw_interrupt_disable();
  74. temp = *ptr;
  75. *ptr -= val;
  76. rt_hw_interrupt_enable(level);
  77. return temp;
  78. }
  79. rt_inline rt_atomic_t rt_soft_atomic_xor(volatile rt_atomic_t *ptr,
  80. rt_atomic_t val)
  81. {
  82. rt_base_t level;
  83. rt_atomic_t temp;
  84. level = rt_hw_interrupt_disable();
  85. temp = *ptr;
  86. *ptr = (*ptr) ^ val;
  87. rt_hw_interrupt_enable(level);
  88. return temp;
  89. }
  90. rt_inline rt_atomic_t rt_soft_atomic_and(volatile rt_atomic_t *ptr,
  91. rt_atomic_t val)
  92. {
  93. rt_base_t level;
  94. rt_atomic_t temp;
  95. level = rt_hw_interrupt_disable();
  96. temp = *ptr;
  97. *ptr = (*ptr) & val;
  98. rt_hw_interrupt_enable(level);
  99. return temp;
  100. }
  101. rt_inline rt_atomic_t rt_soft_atomic_or(volatile rt_atomic_t *ptr,
  102. 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_load(volatile rt_atomic_t *ptr)
  113. {
  114. rt_base_t level;
  115. rt_atomic_t temp;
  116. level = rt_hw_interrupt_disable();
  117. temp = *ptr;
  118. rt_hw_interrupt_enable(level);
  119. return temp;
  120. }
  121. rt_inline void rt_soft_atomic_store(volatile rt_atomic_t *ptr, rt_atomic_t val)
  122. {
  123. rt_base_t level;
  124. level = rt_hw_interrupt_disable();
  125. *ptr = val;
  126. rt_hw_interrupt_enable(level);
  127. }
  128. rt_inline rt_atomic_t rt_soft_atomic_flag_test_and_set(volatile rt_atomic_t *ptr)
  129. {
  130. rt_base_t level;
  131. rt_atomic_t temp;
  132. level = rt_hw_interrupt_disable();
  133. if (*ptr == 0)
  134. {
  135. temp = 0;
  136. *ptr = 1;
  137. }
  138. else
  139. temp = 1;
  140. rt_hw_interrupt_enable(level);
  141. return temp;
  142. }
  143. rt_inline void rt_soft_atomic_flag_clear(volatile rt_atomic_t *ptr)
  144. {
  145. rt_base_t level;
  146. level = rt_hw_interrupt_disable();
  147. *ptr = 0;
  148. rt_hw_interrupt_enable(level);
  149. }
  150. rt_inline rt_atomic_t rt_soft_atomic_compare_exchange_strong(
  151. volatile rt_atomic_t *ptr1, rt_atomic_t *ptr2,
  152. rt_atomic_t desired)
  153. {
  154. rt_base_t level;
  155. rt_atomic_t temp;
  156. level = rt_hw_interrupt_disable();
  157. if ((*ptr1) != (*ptr2))
  158. {
  159. *ptr2 = *ptr1;
  160. temp = 0;
  161. }
  162. else
  163. {
  164. *ptr1 = desired;
  165. temp = 1;
  166. }
  167. rt_hw_interrupt_enable(level);
  168. return temp;
  169. }
  170. rt_inline rt_bool_t rt_atomic_dec_and_test(volatile rt_atomic_t *ptr)
  171. {
  172. return rt_atomic_sub(ptr, 1) == 1;
  173. }
  174. rt_inline rt_atomic_t rt_atomic_fetch_add_unless(volatile rt_atomic_t *ptr,
  175. rt_atomic_t a, rt_atomic_t u)
  176. {
  177. rt_atomic_t c = rt_atomic_load(ptr);
  178. do {
  179. if (c == u)
  180. {
  181. break;
  182. }
  183. } while (!rt_atomic_compare_exchange_strong(ptr, &c, c + a));
  184. return c;
  185. }
  186. rt_inline rt_bool_t rt_atomic_add_unless(volatile rt_atomic_t *ptr,
  187. rt_atomic_t a, rt_atomic_t u)
  188. {
  189. return rt_atomic_fetch_add_unless(ptr, a, u) != u;
  190. }
  191. rt_inline rt_bool_t rt_atomic_inc_not_zero(volatile rt_atomic_t *ptr)
  192. {
  193. return rt_atomic_add_unless(ptr, 1, 0);
  194. }
  195. /**
  196. * @brief initialize a lock-less single list
  197. *
  198. * @param l the single list to be initialized
  199. */
  200. rt_inline void rt_ll_slist_init(rt_ll_slist_t *l)
  201. {
  202. l->next = 0;
  203. }
  204. rt_inline void rt_ll_slist_enqueue(rt_ll_slist_t *l, rt_ll_slist_t *n)
  205. {
  206. rt_base_t exp;
  207. exp = rt_atomic_load(&l->next);
  208. do
  209. {
  210. n->next = exp;
  211. } while (!rt_atomic_compare_exchange_strong(&l->next, &exp, (rt_base_t)n));
  212. }
  213. rt_inline rt_ll_slist_t *rt_ll_slist_dequeue(rt_ll_slist_t *l)
  214. {
  215. rt_base_t exp;
  216. rt_ll_slist_t *head;
  217. exp = rt_atomic_load(&l->next);
  218. do
  219. {
  220. head = (rt_ll_slist_t *)exp;
  221. } while (head && !rt_atomic_compare_exchange_strong(&l->next, &exp,
  222. rt_atomic_load(&head->next)));
  223. return head;
  224. }
  225. #endif /* __RTATOMIC_H__ */