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