diff --git a/include/sys/spin.h b/include/sys/spin.h index 0ccf5c8..b221d8f 100644 --- a/include/sys/spin.h +++ b/include/sys/spin.h @@ -1,4 +1,5 @@ #pragma once +#include "sys/types.h" #if defined(ARCH_AMD64) #include "sys/amd64/sys/spin.h" @@ -6,3 +7,5 @@ void spin_lock(spin_t *s); void spin_release(spin_t *s); +void spin_lock_irqsave(spin_t *s, uintptr_t *irq); +void spin_release_irqrestore(spin_t *s, uintptr_t *irq); diff --git a/sys/amd64/sys/sched.c b/sys/amd64/sys/sched.c index 2755c0a..0c62403 100644 --- a/sys/amd64/sys/sched.c +++ b/sys/amd64/sys/sched.c @@ -17,6 +17,7 @@ static struct thread t_idle[AMD64_MAX_SMP] = {0}; void idle_func(uintptr_t id) { while (1) { kdebug("%d\n", id); + asm volatile ("sti; hlt"); } } diff --git a/sys/amd64/sys/spin_s.S b/sys/amd64/sys/spin_s.S index 7322463..517a490 100644 --- a/sys/amd64/sys/spin_s.S +++ b/sys/amd64/sys/spin_s.S @@ -1,9 +1,17 @@ .section .text .global spin_lock .global spin_release +.global spin_lock_irqsave +.global spin_release_irqrestore // TODO: maybe add some tracing to this so I know // the locks that consume too much CPU time +spin_lock_irqsave: + pushfq + popq %rax + movq %rax, (%rsi) + cli + spin_lock: // %rdi - spinlock lock bts $1, (%rdi) @@ -17,6 +25,13 @@ spin_lock: jnz 1b jmp spin_lock +spin_release_irqrestore: + movq $0, (%rdi) + testq $(1 << 9), (%rsi) + jz 1f + sti +1: + retq spin_release: movq $0, (%rdi) diff --git a/sys/debug.c b/sys/debug.c index bd59676..f762f6f 100644 --- a/sys/debug.c +++ b/sys/debug.c @@ -160,9 +160,8 @@ void debugf(int level, const char *f, ...) { } void debugfv(int level, const char *fmt, va_list args) { - // FIXME Problem: if this code gets interrupted while - // inside the locked region, the CPU freezes - spin_lock(&debug_spin); + uintptr_t irq; + spin_lock_irqsave(&debug_spin, &irq); char c; union { @@ -295,6 +294,6 @@ void debugfv(int level, const char *fmt, va_list args) { ++fmt; } - spin_release(&debug_spin); + spin_release_irqrestore(&debug_spin, &irq); }