Kernel: Move SpinLock definition to header and fix Scheduler locking
This patch allows inlining of spinlocks :)
This commit is contained in:
parent
9c36d7c338
commit
418bc54f2b
|
@ -42,7 +42,6 @@ set(KERNEL_SOURCES
|
||||||
kernel/Input/PS2/Mouse.cpp
|
kernel/Input/PS2/Mouse.cpp
|
||||||
kernel/InterruptController.cpp
|
kernel/InterruptController.cpp
|
||||||
kernel/kernel.cpp
|
kernel/kernel.cpp
|
||||||
kernel/Lock/SpinLock.cpp
|
|
||||||
kernel/Memory/DMARegion.cpp
|
kernel/Memory/DMARegion.cpp
|
||||||
kernel/Memory/FileBackedRegion.cpp
|
kernel/Memory/FileBackedRegion.cpp
|
||||||
kernel/Memory/Heap.cpp
|
kernel/Memory/Heap.cpp
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <BAN/Assert.h>
|
||||||
#include <BAN/Atomic.h>
|
#include <BAN/Atomic.h>
|
||||||
#include <BAN/NoCopyMove.h>
|
#include <BAN/NoCopyMove.h>
|
||||||
#include <kernel/Processor.h>
|
#include <kernel/Processor.h>
|
||||||
|
@ -17,8 +18,32 @@ namespace Kernel
|
||||||
public:
|
public:
|
||||||
SpinLock() = default;
|
SpinLock() = default;
|
||||||
|
|
||||||
InterruptState lock();
|
InterruptState lock()
|
||||||
void unlock(InterruptState state);
|
{
|
||||||
|
auto state = Processor::get_interrupt_state();
|
||||||
|
Processor::set_interrupt_state(InterruptState::Disabled);
|
||||||
|
|
||||||
|
auto id = Processor::current_id();
|
||||||
|
ASSERT(m_locker != id);
|
||||||
|
|
||||||
|
while (!m_locker.compare_exchange(PROCESSOR_NONE, id, BAN::MemoryOrder::memory_order_acquire))
|
||||||
|
__builtin_ia32_pause();
|
||||||
|
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
void unlock(InterruptState state)
|
||||||
|
{
|
||||||
|
ASSERT(Processor::get_interrupt_state() == InterruptState::Disabled);
|
||||||
|
ASSERT(m_locker == Processor::current_id());
|
||||||
|
m_locker.store(PROCESSOR_NONE, BAN::MemoryOrder::memory_order_release);
|
||||||
|
Processor::set_interrupt_state(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool current_processor_has_lock() const
|
||||||
|
{
|
||||||
|
return m_locker == Processor::current_id();
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BAN::Atomic<ProcessorID> m_locker { PROCESSOR_NONE };
|
BAN::Atomic<ProcessorID> m_locker { PROCESSOR_NONE };
|
||||||
|
@ -32,45 +57,44 @@ namespace Kernel
|
||||||
public:
|
public:
|
||||||
RecursiveSpinLock() = default;
|
RecursiveSpinLock() = default;
|
||||||
|
|
||||||
InterruptState lock();
|
|
||||||
void unlock(InterruptState state);
|
|
||||||
|
|
||||||
private:
|
|
||||||
BAN::Atomic<ProcessorID> m_locker { PROCESSOR_NONE };
|
|
||||||
uint32_t m_lock_depth { 0 };
|
|
||||||
};
|
|
||||||
|
|
||||||
class SpinLockUnsafe
|
|
||||||
{
|
|
||||||
BAN_NON_COPYABLE(SpinLockUnsafe);
|
|
||||||
BAN_NON_MOVABLE(SpinLockUnsafe);
|
|
||||||
|
|
||||||
public:
|
|
||||||
SpinLockUnsafe() = default;
|
|
||||||
|
|
||||||
InterruptState lock()
|
InterruptState lock()
|
||||||
{
|
{
|
||||||
auto id = Processor::current_id();
|
|
||||||
|
|
||||||
auto state = Processor::get_interrupt_state();
|
auto state = Processor::get_interrupt_state();
|
||||||
Processor::set_interrupt_state(InterruptState::Disabled);
|
Processor::set_interrupt_state(InterruptState::Disabled);
|
||||||
|
|
||||||
|
auto id = Processor::current_id();
|
||||||
|
if (m_locker == id)
|
||||||
|
ASSERT(m_lock_depth > 0);
|
||||||
|
else
|
||||||
|
{
|
||||||
while (!m_locker.compare_exchange(PROCESSOR_NONE, id, BAN::MemoryOrder::memory_order_acquire))
|
while (!m_locker.compare_exchange(PROCESSOR_NONE, id, BAN::MemoryOrder::memory_order_acquire))
|
||||||
__builtin_ia32_pause();
|
__builtin_ia32_pause();
|
||||||
|
ASSERT(m_lock_depth == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_lock_depth++;
|
||||||
|
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
void unlock(InterruptState state)
|
void unlock(InterruptState state)
|
||||||
{
|
{
|
||||||
|
ASSERT(Processor::get_interrupt_state() == InterruptState::Disabled);
|
||||||
|
ASSERT(m_locker == Processor::current_id());
|
||||||
|
ASSERT(m_lock_depth > 0);
|
||||||
|
if (--m_lock_depth == 0)
|
||||||
m_locker.store(PROCESSOR_NONE, BAN::MemoryOrder::memory_order_release);
|
m_locker.store(PROCESSOR_NONE, BAN::MemoryOrder::memory_order_release);
|
||||||
Processor::set_interrupt_state(state);
|
Processor::set_interrupt_state(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_locked() const { return m_locker != PROCESSOR_NONE; }
|
bool current_processor_has_lock() const
|
||||||
|
{
|
||||||
|
return m_locker == Processor::current_id();
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BAN::Atomic<ProcessorID> m_locker { PROCESSOR_NONE };
|
BAN::Atomic<ProcessorID> m_locker { PROCESSOR_NONE };
|
||||||
|
uint32_t m_lock_depth { 0 };
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Lock>
|
template<typename Lock>
|
||||||
|
|
|
@ -62,7 +62,7 @@ namespace Kernel
|
||||||
Semaphore* semaphore;
|
Semaphore* semaphore;
|
||||||
};
|
};
|
||||||
|
|
||||||
SpinLockUnsafe m_lock;
|
SpinLock m_lock;
|
||||||
|
|
||||||
Thread* m_idle_thread { nullptr };
|
Thread* m_idle_thread { nullptr };
|
||||||
BAN::LinkedList<SchedulerThread> m_active_threads;
|
BAN::LinkedList<SchedulerThread> m_active_threads;
|
||||||
|
|
|
@ -1,61 +0,0 @@
|
||||||
#include <kernel/InterruptController.h>
|
|
||||||
#include <kernel/Lock/SpinLock.h>
|
|
||||||
#include <kernel/Scheduler.h>
|
|
||||||
|
|
||||||
// FIXME: try to move these to header
|
|
||||||
|
|
||||||
namespace Kernel
|
|
||||||
{
|
|
||||||
|
|
||||||
InterruptState SpinLock::lock()
|
|
||||||
{
|
|
||||||
auto id = Processor::current_id();
|
|
||||||
ASSERT(m_locker != id);
|
|
||||||
|
|
||||||
auto state = Processor::get_interrupt_state();
|
|
||||||
Processor::set_interrupt_state(InterruptState::Disabled);
|
|
||||||
|
|
||||||
while (!m_locker.compare_exchange(PROCESSOR_NONE, id, BAN::MemoryOrder::memory_order_acquire))
|
|
||||||
__builtin_ia32_pause();
|
|
||||||
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SpinLock::unlock(InterruptState state)
|
|
||||||
{
|
|
||||||
ASSERT(m_locker == Processor::current_id());
|
|
||||||
m_locker.store(PROCESSOR_NONE, BAN::MemoryOrder::memory_order_release);
|
|
||||||
Processor::set_interrupt_state(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
InterruptState RecursiveSpinLock::lock()
|
|
||||||
{
|
|
||||||
auto id = Processor::current_id();
|
|
||||||
|
|
||||||
auto state = Processor::get_interrupt_state();
|
|
||||||
Processor::set_interrupt_state(InterruptState::Disabled);
|
|
||||||
|
|
||||||
if (id == m_locker)
|
|
||||||
ASSERT(m_lock_depth > 0);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
while (!m_locker.compare_exchange(PROCESSOR_NONE, id, BAN::MemoryOrder::memory_order_acquire))
|
|
||||||
__builtin_ia32_pause();
|
|
||||||
ASSERT(m_lock_depth == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_lock_depth++;
|
|
||||||
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
void RecursiveSpinLock::unlock(InterruptState state)
|
|
||||||
{
|
|
||||||
ASSERT(m_locker == Processor::current_id());
|
|
||||||
ASSERT(m_lock_depth > 0);
|
|
||||||
if (--m_lock_depth == 0)
|
|
||||||
m_locker.store(PROCESSOR_NONE, BAN::MemoryOrder::memory_order_release);
|
|
||||||
Processor::set_interrupt_state(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -64,7 +64,7 @@ namespace Kernel
|
||||||
auto state = m_lock.lock();
|
auto state = m_lock.lock();
|
||||||
wake_threads();
|
wake_threads();
|
||||||
if (save_current_thread())
|
if (save_current_thread())
|
||||||
return m_lock.unlock(state);
|
return Processor::set_interrupt_state(state);
|
||||||
advance_current_thread();
|
advance_current_thread();
|
||||||
execute_current_thread_locked();
|
execute_current_thread_locked();
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
|
@ -86,7 +86,7 @@ namespace Kernel
|
||||||
if (m_active_threads.empty() || ¤t_thread() != m_idle_thread)
|
if (m_active_threads.empty() || ¤t_thread() != m_idle_thread)
|
||||||
return m_lock.unlock(state);
|
return m_lock.unlock(state);
|
||||||
if (save_current_thread())
|
if (save_current_thread())
|
||||||
return m_lock.unlock(state);
|
return Processor::set_interrupt_state(state);
|
||||||
m_current_thread = m_active_threads.begin();
|
m_current_thread = m_active_threads.begin();
|
||||||
execute_current_thread_locked();
|
execute_current_thread_locked();
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
|
@ -94,7 +94,7 @@ namespace Kernel
|
||||||
|
|
||||||
void Scheduler::wake_threads()
|
void Scheduler::wake_threads()
|
||||||
{
|
{
|
||||||
ASSERT(m_lock.is_locked());
|
ASSERT(m_lock.current_processor_has_lock());
|
||||||
|
|
||||||
uint64_t current_time = SystemTimer::get().ms_since_boot();
|
uint64_t current_time = SystemTimer::get().ms_since_boot();
|
||||||
while (!m_sleeping_threads.empty() && m_sleeping_threads.front().wake_time <= current_time)
|
while (!m_sleeping_threads.empty() && m_sleeping_threads.front().wake_time <= current_time)
|
||||||
|
@ -124,7 +124,7 @@ namespace Kernel
|
||||||
|
|
||||||
void Scheduler::advance_current_thread()
|
void Scheduler::advance_current_thread()
|
||||||
{
|
{
|
||||||
ASSERT(m_lock.is_locked());
|
ASSERT(m_lock.current_processor_has_lock());
|
||||||
|
|
||||||
if (m_active_threads.empty())
|
if (m_active_threads.empty())
|
||||||
{
|
{
|
||||||
|
@ -137,7 +137,7 @@ namespace Kernel
|
||||||
|
|
||||||
void Scheduler::remove_and_advance_current_thread()
|
void Scheduler::remove_and_advance_current_thread()
|
||||||
{
|
{
|
||||||
ASSERT(m_lock.is_locked());
|
ASSERT(m_lock.current_processor_has_lock());
|
||||||
|
|
||||||
ASSERT(m_current_thread);
|
ASSERT(m_current_thread);
|
||||||
|
|
||||||
|
@ -158,7 +158,7 @@ namespace Kernel
|
||||||
// after getting the rsp
|
// after getting the rsp
|
||||||
ALWAYS_INLINE bool Scheduler::save_current_thread()
|
ALWAYS_INLINE bool Scheduler::save_current_thread()
|
||||||
{
|
{
|
||||||
ASSERT(m_lock.is_locked());
|
ASSERT(m_lock.current_processor_has_lock());
|
||||||
|
|
||||||
uintptr_t rsp, rip;
|
uintptr_t rsp, rip;
|
||||||
push_callee_saved();
|
push_callee_saved();
|
||||||
|
@ -209,7 +209,7 @@ namespace Kernel
|
||||||
|
|
||||||
void Scheduler::execute_current_thread_locked()
|
void Scheduler::execute_current_thread_locked()
|
||||||
{
|
{
|
||||||
ASSERT(m_lock.is_locked());
|
ASSERT(m_lock.current_processor_has_lock());
|
||||||
load_temp_stack();
|
load_temp_stack();
|
||||||
PageTable::kernel().load();
|
PageTable::kernel().load();
|
||||||
execute_current_thread_stack_loaded();
|
execute_current_thread_stack_loaded();
|
||||||
|
@ -218,7 +218,7 @@ namespace Kernel
|
||||||
|
|
||||||
NEVER_INLINE void Scheduler::execute_current_thread_stack_loaded()
|
NEVER_INLINE void Scheduler::execute_current_thread_stack_loaded()
|
||||||
{
|
{
|
||||||
ASSERT(m_lock.is_locked());
|
ASSERT(m_lock.current_processor_has_lock());
|
||||||
|
|
||||||
#if SCHEDULER_VERIFY_STACK
|
#if SCHEDULER_VERIFY_STACK
|
||||||
vaddr_t rsp;
|
vaddr_t rsp;
|
||||||
|
@ -281,7 +281,7 @@ namespace Kernel
|
||||||
|
|
||||||
void Scheduler::set_current_thread_sleeping_impl(uint64_t wake_time)
|
void Scheduler::set_current_thread_sleeping_impl(uint64_t wake_time)
|
||||||
{
|
{
|
||||||
ASSERT(m_lock.is_locked());
|
ASSERT(m_lock.current_processor_has_lock());
|
||||||
|
|
||||||
if (save_current_thread())
|
if (save_current_thread())
|
||||||
return;
|
return;
|
||||||
|
@ -307,16 +307,18 @@ namespace Kernel
|
||||||
|
|
||||||
void Scheduler::set_current_thread_sleeping(uint64_t wake_time)
|
void Scheduler::set_current_thread_sleeping(uint64_t wake_time)
|
||||||
{
|
{
|
||||||
SpinLockGuard _(m_lock);
|
auto state = m_lock.lock();
|
||||||
m_current_thread->semaphore = nullptr;
|
m_current_thread->semaphore = nullptr;
|
||||||
set_current_thread_sleeping_impl(wake_time);
|
set_current_thread_sleeping_impl(wake_time);
|
||||||
|
Processor::set_interrupt_state(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scheduler::block_current_thread(Semaphore* semaphore, uint64_t wake_time)
|
void Scheduler::block_current_thread(Semaphore* semaphore, uint64_t wake_time)
|
||||||
{
|
{
|
||||||
SpinLockGuard _(m_lock);
|
auto state = m_lock.lock();
|
||||||
m_current_thread->semaphore = semaphore;
|
m_current_thread->semaphore = semaphore;
|
||||||
set_current_thread_sleeping_impl(wake_time);
|
set_current_thread_sleeping_impl(wake_time);
|
||||||
|
Processor::set_interrupt_state(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scheduler::unblock_threads(Semaphore* semaphore)
|
void Scheduler::unblock_threads(Semaphore* semaphore)
|
||||||
|
|
Loading…
Reference in New Issue