This commit is contained in:
2025-09-27 15:16:26 +02:00
parent 5af7c5276a
commit 3b1bb9d531
63 changed files with 1087 additions and 407 deletions

View File

@ -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();
}