66 lines
1.4 KiB
C
66 lines
1.4 KiB
C
typedef struct {
|
|
volatile unsigned int locked; // 0 = unlocked, 1 = locked
|
|
} spinlock_t;
|
|
|
|
static inline void initlock(spinlock_t *lk) {
|
|
lk->locked = 0;
|
|
}
|
|
|
|
static inline void acquire(spinlock_t *lk) {
|
|
while (__sync_lock_test_and_set(&lk->locked, 1) != 0); // spin
|
|
}
|
|
|
|
static inline void release(spinlock_t *lk) {
|
|
__sync_lock_release(&lk->locked);
|
|
}
|
|
|
|
#ifdef ATOMIC_MUTEX
|
|
|
|
#include <stdatomic.h>
|
|
#include <stdbool.h>
|
|
|
|
typedef struct {
|
|
atomic_int flag;
|
|
} mutex_t;
|
|
|
|
void mutex_init(mutex_t *m) {
|
|
atomic_store(&m->flag, 0);
|
|
}
|
|
|
|
void mutex_lock(mutex_t *m) {
|
|
int expected;
|
|
do {
|
|
expected = 0;
|
|
} while (!atomic_compare_exchange_weak(&m->flag, &expected, 1));
|
|
}
|
|
|
|
void mutex_unlock(mutex_t *m) {
|
|
atomic_store(&m->flag, 0);
|
|
}
|
|
|
|
#endif
|
|
#ifdef ATOMIC_MUTEX_RISCV
|
|
|
|
typedef struct {
|
|
volatile int locked;
|
|
} spinlock_t;
|
|
|
|
void spinlock_init(spinlock_t *lk) {
|
|
lk->locked = 0;
|
|
}
|
|
|
|
void spinlock_acquire(spinlock_t *lk) {
|
|
int tmp;
|
|
do {
|
|
__asm__ volatile("amoswap.w %0, %1, (%2)"
|
|
: "=r"(tmp) // old value in tmp
|
|
: "r"(1), "r"(&lk->locked) // store 1 into memory
|
|
: "memory");
|
|
} while (tmp != 0); // spin until old value was 0
|
|
}
|
|
|
|
void spinlock_release(spinlock_t *lk) {
|
|
__asm__ volatile("amoswap.w zero, %1, (%0)" : : "r"(&lk->locked), "r"(0) : "memory");
|
|
}
|
|
|
|
#endif
|