| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274 |
- #include <stdlib.h>
- #include <sys/lock.h>
- #include "bsp.h"
- #define LOCK_MAX_NUM (1024)
- typedef long _lock_t;
- typedef struct
- {
- _lock_t *lock;
- long counter;
- unsigned long core;
- } reculock_t;
- reculock_t reculock[LOCK_MAX_NUM];
- static _lock_t reculock_mutex;
- void show_error(void)
- {
- register unsigned long a7 asm("a7") = 93;
- register unsigned long a0 asm("a0") = 0;
- register unsigned long a1 asm("a1") = 0;
- register unsigned long a2 asm("a2") = 0;
- asm volatile("scall"
- : "+r"(a0)
- : "r"(a1), "r"(a2), "r"(a7));
- }
- static inline long lock_trylock(_lock_t *lock)
- {
- long res = atomic_swap(lock, -1);
- /* Use memory barrier to keep coherency */
- mb();
- return res;
- }
- static inline void lock_lock(_lock_t *lock)
- {
- while(lock_trylock(lock))
- ;
- }
- static inline void lock_unlock(_lock_t *lock)
- {
- /* Use memory barrier to keep coherency */
- mb();
- atomic_swap(lock, 0);
- asm volatile("nop");
- }
- static reculock_t *get_reculock(_lock_t *lock)
- {
- for(uint32_t i = 0; i < LOCK_MAX_NUM; i++)
- {
- if(reculock[i].lock == lock)
- return &reculock[i];
- }
- return NULL;
- }
- static reculock_t *get_free_reculock(void)
- {
- for(uint32_t i = 0; i < LOCK_MAX_NUM; i++)
- {
- if(reculock[i].lock == NULL)
- {
- return &reculock[i];
- }
- }
- return NULL;
- }
- static reculock_t *reculock_init(_lock_t *lock)
- {
- lock_lock(&reculock_mutex);
- reculock_t *v_reculock = get_free_reculock();
- if(v_reculock)
- {
- *v_reculock = (reculock_t){
- .lock = lock,
- .counter = 0,
- .core = 0,
- };
- }
- lock_unlock(&reculock_mutex);
- return v_reculock;
- }
- static void reculock_deinit(_lock_t *lock)
- {
- lock_lock(lock);
- reculock_t *v_reculock = get_reculock(lock);
- if(v_reculock)
- {
- *v_reculock = (reculock_t){
- .lock = NULL,
- .counter = 0,
- .core = 0,
- };
- }
- lock_unlock(lock);
- }
- static inline int reculock_trylock(_lock_t *lock)
- {
- int res = 0;
- unsigned long core;
- asm volatile("csrr %0, mhartid;"
- : "=r"(core));
- if(lock_trylock(lock))
- {
- return -1;
- }
- reculock_t *v_reculock = get_reculock(lock);
- if(v_reculock == NULL)
- {
- v_reculock = reculock_init(lock);
- if(v_reculock == NULL)
- {
- lock_unlock(lock);
- show_error();
- }
- }
- if(v_reculock->counter == 0)
- {
- /* First time get lock */
- v_reculock->counter++;
- v_reculock->core = core;
- res = 0;
- } else if(v_reculock->core == core)
- {
- /* Same core get lock */
- v_reculock->counter++;
- res = 0;
- } else
- {
- /* Different core get lock */
- res = -1;
- }
- lock_unlock(lock);
- return res;
- }
- static inline void reculock_lock(_lock_t *lock)
- {
- unsigned long core;
- asm volatile("csrr %0, mhartid;"
- : "=r"(core));
- lock_lock(lock);
- reculock_t *v_reculock = get_reculock(lock);
- if(v_reculock == NULL)
- {
- v_reculock = reculock_init(lock);
- if(v_reculock == NULL)
- {
- lock_unlock(lock);
- show_error();
- }
- }
- if(v_reculock->counter == 0)
- {
- /* First time get lock */
- v_reculock->counter++;
- v_reculock->core = core;
- } else if(v_reculock->core == core)
- {
- /* Same core get lock */
- v_reculock->counter++;
- } else
- {
- /* Different core get lock */
- lock_unlock(lock);
- do
- {
- while(atomic_read(&reculock->counter))
- ;
- } while(reculock_trylock(lock));
- return;
- }
- lock_unlock(lock);
- }
- static inline void reculock_unlock(_lock_t *lock)
- {
- unsigned long core;
- asm volatile("csrr %0, mhartid;"
- : "=r"(core));
- lock_lock(lock);
- reculock_t *v_reculock = get_reculock(lock);
- if(v_reculock == NULL)
- {
- lock_unlock(lock);
- show_error();
- }
- if(v_reculock->core == core)
- {
- /* Same core release lock */
- v_reculock->counter--;
- if(v_reculock->counter <= 0)
- {
- v_reculock->core = 0;
- v_reculock->counter = 0;
- v_reculock->lock = NULL;
- }
- } else
- {
- /* Different core release lock */
- lock_unlock(lock);
- show_error();
- }
- lock_unlock(lock);
- }
- void _lock_init(_lock_t *lock)
- {
- *lock = 0;
- }
- void _lock_init_recursive(_lock_t *lock)
- {
- reculock_init(lock);
- }
- void _lock_close(_lock_t *lock)
- {
- lock_unlock(lock);
- }
- void _lock_close_recursive(_lock_t *lock)
- {
- reculock_deinit(lock);
- }
- void _lock_acquire(_lock_t *lock)
- {
- lock_lock(lock);
- }
- void _lock_acquire_recursive(_lock_t *lock)
- {
- reculock_lock(lock);
- }
- int _lock_try_acquire(_lock_t *lock)
- {
- return lock_trylock(lock);
- }
- int _lock_try_acquire_recursive(_lock_t *lock)
- {
- return reculock_trylock(lock);
- }
- void _lock_release(_lock_t *lock)
- {
- lock_unlock(lock);
- }
- void _lock_release_recursive(_lock_t *lock)
- {
- reculock_unlock(lock);
- }
|