locks.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. #include <stdlib.h>
  2. #include <sys/lock.h>
  3. #include "bsp.h"
  4. #define LOCK_MAX_NUM (1024)
  5. typedef long _lock_t;
  6. typedef struct
  7. {
  8. _lock_t *lock;
  9. long counter;
  10. unsigned long core;
  11. } reculock_t;
  12. reculock_t reculock[LOCK_MAX_NUM];
  13. static _lock_t reculock_mutex;
  14. void show_error(void)
  15. {
  16. register unsigned long a7 asm("a7") = 93;
  17. register unsigned long a0 asm("a0") = 0;
  18. register unsigned long a1 asm("a1") = 0;
  19. register unsigned long a2 asm("a2") = 0;
  20. asm volatile("scall"
  21. : "+r"(a0)
  22. : "r"(a1), "r"(a2), "r"(a7));
  23. }
  24. static inline long lock_trylock(_lock_t *lock)
  25. {
  26. long res = atomic_swap(lock, -1);
  27. /* Use memory barrier to keep coherency */
  28. mb();
  29. return res;
  30. }
  31. static inline void lock_lock(_lock_t *lock)
  32. {
  33. while(lock_trylock(lock))
  34. ;
  35. }
  36. static inline void lock_unlock(_lock_t *lock)
  37. {
  38. /* Use memory barrier to keep coherency */
  39. mb();
  40. atomic_swap(lock, 0);
  41. asm volatile("nop");
  42. }
  43. static reculock_t *get_reculock(_lock_t *lock)
  44. {
  45. for(uint32_t i = 0; i < LOCK_MAX_NUM; i++)
  46. {
  47. if(reculock[i].lock == lock)
  48. return &reculock[i];
  49. }
  50. return NULL;
  51. }
  52. static reculock_t *get_free_reculock(void)
  53. {
  54. for(uint32_t i = 0; i < LOCK_MAX_NUM; i++)
  55. {
  56. if(reculock[i].lock == NULL)
  57. {
  58. return &reculock[i];
  59. }
  60. }
  61. return NULL;
  62. }
  63. static reculock_t *reculock_init(_lock_t *lock)
  64. {
  65. lock_lock(&reculock_mutex);
  66. reculock_t *v_reculock = get_free_reculock();
  67. if(v_reculock)
  68. {
  69. *v_reculock = (reculock_t){
  70. .lock = lock,
  71. .counter = 0,
  72. .core = 0,
  73. };
  74. }
  75. lock_unlock(&reculock_mutex);
  76. return v_reculock;
  77. }
  78. static void reculock_deinit(_lock_t *lock)
  79. {
  80. lock_lock(lock);
  81. reculock_t *v_reculock = get_reculock(lock);
  82. if(v_reculock)
  83. {
  84. *v_reculock = (reculock_t){
  85. .lock = NULL,
  86. .counter = 0,
  87. .core = 0,
  88. };
  89. }
  90. lock_unlock(lock);
  91. }
  92. static inline int reculock_trylock(_lock_t *lock)
  93. {
  94. int res = 0;
  95. unsigned long core;
  96. asm volatile("csrr %0, mhartid;"
  97. : "=r"(core));
  98. if(lock_trylock(lock))
  99. {
  100. return -1;
  101. }
  102. reculock_t *v_reculock = get_reculock(lock);
  103. if(v_reculock == NULL)
  104. {
  105. v_reculock = reculock_init(lock);
  106. if(v_reculock == NULL)
  107. {
  108. lock_unlock(lock);
  109. show_error();
  110. }
  111. }
  112. if(v_reculock->counter == 0)
  113. {
  114. /* First time get lock */
  115. v_reculock->counter++;
  116. v_reculock->core = core;
  117. res = 0;
  118. } else if(v_reculock->core == core)
  119. {
  120. /* Same core get lock */
  121. v_reculock->counter++;
  122. res = 0;
  123. } else
  124. {
  125. /* Different core get lock */
  126. res = -1;
  127. }
  128. lock_unlock(lock);
  129. return res;
  130. }
  131. static inline void reculock_lock(_lock_t *lock)
  132. {
  133. unsigned long core;
  134. asm volatile("csrr %0, mhartid;"
  135. : "=r"(core));
  136. lock_lock(lock);
  137. reculock_t *v_reculock = get_reculock(lock);
  138. if(v_reculock == NULL)
  139. {
  140. v_reculock = reculock_init(lock);
  141. if(v_reculock == NULL)
  142. {
  143. lock_unlock(lock);
  144. show_error();
  145. }
  146. }
  147. if(v_reculock->counter == 0)
  148. {
  149. /* First time get lock */
  150. v_reculock->counter++;
  151. v_reculock->core = core;
  152. } else if(v_reculock->core == core)
  153. {
  154. /* Same core get lock */
  155. v_reculock->counter++;
  156. } else
  157. {
  158. /* Different core get lock */
  159. lock_unlock(lock);
  160. do
  161. {
  162. while(atomic_read(&reculock->counter))
  163. ;
  164. } while(reculock_trylock(lock));
  165. return;
  166. }
  167. lock_unlock(lock);
  168. }
  169. static inline void reculock_unlock(_lock_t *lock)
  170. {
  171. unsigned long core;
  172. asm volatile("csrr %0, mhartid;"
  173. : "=r"(core));
  174. lock_lock(lock);
  175. reculock_t *v_reculock = get_reculock(lock);
  176. if(v_reculock == NULL)
  177. {
  178. lock_unlock(lock);
  179. show_error();
  180. }
  181. if(v_reculock->core == core)
  182. {
  183. /* Same core release lock */
  184. v_reculock->counter--;
  185. if(v_reculock->counter <= 0)
  186. {
  187. v_reculock->core = 0;
  188. v_reculock->counter = 0;
  189. v_reculock->lock = NULL;
  190. }
  191. } else
  192. {
  193. /* Different core release lock */
  194. lock_unlock(lock);
  195. show_error();
  196. }
  197. lock_unlock(lock);
  198. }
  199. void _lock_init(_lock_t *lock)
  200. {
  201. *lock = 0;
  202. }
  203. void _lock_init_recursive(_lock_t *lock)
  204. {
  205. reculock_init(lock);
  206. }
  207. void _lock_close(_lock_t *lock)
  208. {
  209. lock_unlock(lock);
  210. }
  211. void _lock_close_recursive(_lock_t *lock)
  212. {
  213. reculock_deinit(lock);
  214. }
  215. void _lock_acquire(_lock_t *lock)
  216. {
  217. lock_lock(lock);
  218. }
  219. void _lock_acquire_recursive(_lock_t *lock)
  220. {
  221. reculock_lock(lock);
  222. }
  223. int _lock_try_acquire(_lock_t *lock)
  224. {
  225. return lock_trylock(lock);
  226. }
  227. int _lock_try_acquire_recursive(_lock_t *lock)
  228. {
  229. return reculock_trylock(lock);
  230. }
  231. void _lock_release(_lock_t *lock)
  232. {
  233. lock_unlock(lock);
  234. }
  235. void _lock_release_recursive(_lock_t *lock)
  236. {
  237. reculock_unlock(lock);
  238. }