CPlay/spinlocks/spinlock.h
2025-08-28 14:45:45 +02:00

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