push
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
#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
|
||||
Reference in New Issue
Block a user