Files
alexvoste 1a9fd27a31 push
2026-05-07 02:22:25 +03:00

44 lines
1.4 KiB
C

#ifndef SPINLOCK_H
#define SPINLOCK_H
#include <stdint.h>
typedef struct {
volatile uint32_t ticket;
volatile uint32_t serving;
} spinlock_t;
#define SPINLOCK_INIT { .ticket = 0, .serving = 0 }
static inline void spinlock_acquire(spinlock_t* lock) {
uint32_t my_ticket = __atomic_fetch_add(&lock->ticket, 1, __ATOMIC_RELAXED);
while (__atomic_load_n(&lock->serving, __ATOMIC_ACQUIRE) != my_ticket)
asm volatile("pause");
}
static inline void spinlock_release(spinlock_t* lock) {
__atomic_fetch_add(&lock->serving, 1, __ATOMIC_RELEASE);
}
static inline int spinlock_try_acquire(spinlock_t* lock) {
uint32_t serving = __atomic_load_n(&lock->serving, __ATOMIC_RELAXED);
uint32_t ticket = __atomic_load_n(&lock->ticket, __ATOMIC_RELAXED);
if (serving != ticket) return 0;
uint32_t expected = serving;
return __atomic_compare_exchange_n(&lock->ticket, &expected, serving + 1,
0, __ATOMIC_ACQUIRE, __ATOMIC_RELAXED);
}
static inline uint64_t spinlock_acquire_irqsave(spinlock_t* lock) {
uint64_t flags;
asm volatile("pushfq; pop %0; cli" : "=r"(flags) :: "memory");
spinlock_acquire(lock);
return flags;
}
static inline void spinlock_release_irqrestore(spinlock_t* lock, uint64_t flags) {
spinlock_release(lock);
asm volatile("push %0; popfq" :: "r"(flags) : "memory", "cc");
}
#endif