Kernel: Move interrupt status stuff to Processor.h

SpinLocks are now locked with processor id instead of thread id. This
allows having multiple processors running while scheduler is not yet
activated.
This commit is contained in:
Bananymous 2024-03-03 01:47:22 +02:00
parent efd8203232
commit 1de9daa40f
3 changed files with 31 additions and 21 deletions

View File

@ -2,7 +2,7 @@
#include <BAN/Atomic.h> #include <BAN/Atomic.h>
#include <BAN/NoCopyMove.h> #include <BAN/NoCopyMove.h>
#include <kernel/Interrupts.h> #include <kernel/Processor.h>
#include <sys/types.h> #include <sys/types.h>
@ -21,7 +21,7 @@ namespace Kernel
void unlock(InterruptState state); void unlock(InterruptState state);
private: private:
BAN::Atomic<pid_t> m_locker { -1 }; BAN::Atomic<ProcessorID> m_locker { PROCESSOR_NONE };
}; };
class RecursiveSpinLock class RecursiveSpinLock
@ -36,8 +36,8 @@ namespace Kernel
void unlock(InterruptState state); void unlock(InterruptState state);
private: private:
BAN::Atomic<pid_t> m_locker { -1 }; BAN::Atomic<ProcessorID> m_locker { PROCESSOR_NONE };
uint32_t m_lock_depth { 0 }; uint32_t m_lock_depth { 0 };
}; };
class SpinLockUnsafe class SpinLockUnsafe
@ -50,10 +50,12 @@ namespace Kernel
InterruptState lock() InterruptState lock()
{ {
auto id = get_processor_id();
auto state = get_interrupt_state(); auto state = get_interrupt_state();
set_interrupt_state(InterruptState::Disabled); set_interrupt_state(InterruptState::Disabled);
while (!m_locked.compare_exchange(false, true)) while (!m_locker.compare_exchange(PROCESSOR_NONE, id, BAN::MemoryOrder::memory_order_acquire))
__builtin_ia32_pause(); __builtin_ia32_pause();
return state; return state;
@ -61,14 +63,14 @@ namespace Kernel
void unlock(InterruptState state) void unlock(InterruptState state)
{ {
m_locked.store(false); m_locker.store(PROCESSOR_NONE, BAN::MemoryOrder::memory_order_release);
set_interrupt_state(state); set_interrupt_state(state);
} }
bool is_locked() const { return m_locked; } bool is_locked() const { return m_locker != PROCESSOR_NONE; }
private: private:
BAN::Atomic<bool> m_locked; BAN::Atomic<ProcessorID> m_locker { PROCESSOR_NONE };
}; };
template<typename Lock> template<typename Lock>

View File

@ -30,6 +30,15 @@ namespace Kernel
return InterruptState::Disabled; return InterruptState::Disabled;
} }
using ProcessorID = uint8_t;
constexpr ProcessorID PROCESSOR_NONE = 0xFF;
inline ProcessorID get_processor_id()
{
uint16_t id;
asm volatile("movw %%gs, %0" : "=rm"(id));
return id;
}
#else #else
#error "Unknown architecure" #error "Unknown architecure"
#endif #endif

View File

@ -9,38 +9,38 @@ namespace Kernel
InterruptState SpinLock::lock() InterruptState SpinLock::lock()
{ {
auto tid = Scheduler::current_tid(); auto id = get_processor_id();
ASSERT_NEQ(m_locker.load(), tid); ASSERT_NEQ(m_locker.load(), id);
auto state = get_interrupt_state(); auto state = get_interrupt_state();
set_interrupt_state(InterruptState::Disabled); set_interrupt_state(InterruptState::Disabled);
if (!m_locker.compare_exchange(-1, tid)) while (!m_locker.compare_exchange(PROCESSOR_NONE, id, BAN::MemoryOrder::memory_order_acquire))
ASSERT_NOT_REACHED(); __builtin_ia32_pause();
return state; return state;
} }
void SpinLock::unlock(InterruptState state) void SpinLock::unlock(InterruptState state)
{ {
ASSERT_EQ(m_locker.load(), Scheduler::current_tid()); ASSERT_EQ(m_locker.load(), get_processor_id());
m_locker.store(-1); m_locker.store(PROCESSOR_NONE, BAN::MemoryOrder::memory_order_release);
set_interrupt_state(state); set_interrupt_state(state);
} }
InterruptState RecursiveSpinLock::lock() InterruptState RecursiveSpinLock::lock()
{ {
auto tid = Scheduler::current_tid(); auto id = get_processor_id();
auto state = get_interrupt_state(); auto state = get_interrupt_state();
set_interrupt_state(InterruptState::Disabled); set_interrupt_state(InterruptState::Disabled);
if (tid == m_locker) if (id == m_locker)
ASSERT_GT(m_lock_depth, 0); ASSERT_GT(m_lock_depth, 0);
else else
{ {
if (!m_locker.compare_exchange(-1, tid)) while (!m_locker.compare_exchange(PROCESSOR_NONE, id, BAN::MemoryOrder::memory_order_acquire))
ASSERT_NOT_REACHED(); __builtin_ia32_pause();
ASSERT_EQ(m_lock_depth, 0); ASSERT_EQ(m_lock_depth, 0);
} }
@ -51,11 +51,10 @@ namespace Kernel
void RecursiveSpinLock::unlock(InterruptState state) void RecursiveSpinLock::unlock(InterruptState state)
{ {
auto tid = Scheduler::current_tid(); ASSERT_EQ(m_locker.load(), get_processor_id());
ASSERT_EQ(m_locker.load(), tid);
ASSERT_GT(m_lock_depth, 0); ASSERT_GT(m_lock_depth, 0);
if (--m_lock_depth == 0) if (--m_lock_depth == 0)
m_locker = -1; m_locker.store(PROCESSOR_NONE, BAN::MemoryOrder::memory_order_release);
set_interrupt_state(state); set_interrupt_state(state);
} }