WIP 2
This commit is contained in:
@ -5,25 +5,62 @@
|
||||
#include "hal/hal.h"
|
||||
#include "kprintf.h"
|
||||
|
||||
#define SPINLOCK_IRQ_DBG 1
|
||||
|
||||
#define SPINLOCK_HINT() asm volatile("pause")
|
||||
|
||||
struct {
|
||||
atomic_uint64_t irq_flags;
|
||||
atomic_int irq_nest;
|
||||
} IRQ_CTX;
|
||||
|
||||
void spinlock_init(SpinLock *sl) {
|
||||
atomic_store(&sl->lock, false);
|
||||
sl->flags = 0;
|
||||
}
|
||||
|
||||
uint64_t spinlock_irqsave(void) {
|
||||
uint64_t irqsave(void) {
|
||||
uint64_t flags;
|
||||
asm volatile("pushfq; cli; popq %0" : "=r"(flags) :: "memory");
|
||||
asm volatile("pushfq; cli; popq %0" : "=r"(flags) :: "memory", "cc");
|
||||
return flags;
|
||||
}
|
||||
|
||||
void spinlock_irqrestore(uint64_t flags) {
|
||||
void irqrestore(uint64_t flags) {
|
||||
if (flags & (1<<9)) {
|
||||
asm volatile("sti" ::: "memory");
|
||||
asm volatile("sti" ::: "memory", "cc");
|
||||
}
|
||||
}
|
||||
|
||||
void irqsave_nested(void) {
|
||||
if (atomic_load(&IRQ_CTX.irq_nest) == 0) {
|
||||
atomic_store(&IRQ_CTX.irq_flags, irqsave());
|
||||
}
|
||||
atomic_inc(&IRQ_CTX.irq_nest);
|
||||
|
||||
#if SPINLOCK_IRQ_DBG
|
||||
if (atomic_load(&IRQ_CTX.irq_nest) < 0) {
|
||||
kprintf("IRQ_CTX.irq_nest underflow\n");
|
||||
hal_hang();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void irqrestore_nested(void) {
|
||||
#if SPINLOCK_IRQ_DBG
|
||||
int irq_nest = atomic_load(&IRQ_CTX.irq_nest);
|
||||
if (irq_nest <= 0) {
|
||||
kprintf("spinlock: irqs restored too many times: %d\n", irq_nest);
|
||||
hal_hang();
|
||||
}
|
||||
#endif
|
||||
|
||||
atomic_dec(&IRQ_CTX.irq_nest);
|
||||
if (atomic_load(&IRQ_CTX.irq_nest) == 0) {
|
||||
irqrestore(atomic_load(&IRQ_CTX.irq_flags));
|
||||
}
|
||||
}
|
||||
|
||||
void spinlock_acquire(SpinLock *sl) {
|
||||
sl->flags = spinlock_irqsave();
|
||||
irqsave_nested();
|
||||
|
||||
while (atomic_test_and_set_explicit(&sl->lock, memory_order_acquire)) {
|
||||
SPINLOCK_HINT();
|
||||
@ -33,6 +70,6 @@ void spinlock_acquire(SpinLock *sl) {
|
||||
void spinlock_release(SpinLock *sl) {
|
||||
atomic_clear_flag_explicit(&sl->lock, memory_order_release);
|
||||
|
||||
spinlock_irqrestore(sl->flags);
|
||||
irqrestore_nested();
|
||||
}
|
||||
|
||||
|
@ -6,11 +6,8 @@
|
||||
|
||||
typedef struct {
|
||||
atomic_bool lock;
|
||||
uint64_t flags;
|
||||
} SpinLock;
|
||||
|
||||
#define SPINLOCK_HINT() asm volatile("pause")
|
||||
|
||||
void spinlock_init(SpinLock *sl);
|
||||
void spinlock_acquire(SpinLock *sl);
|
||||
void spinlock_release(SpinLock *sl);
|
||||
|
Reference in New Issue
Block a user