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

View File

@ -30,6 +30,15 @@ namespace Kernel
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
#error "Unknown architecure"
#endif

View File

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