forked from Bananymous/banan-os
Kernel: Create CriticalScope and fix kmalloc
This disables interrupts for the current scope and restores them after the scope. This is used in kmalloc, since scheduler might call into kmalloc/kfree, but deadlock if some thread is currently trying to allocate. This allows us to use kmalloc in Scheduler.
This commit is contained in:
parent
a068d828fe
commit
d90aba0963
|
@ -0,0 +1,30 @@
|
|||
#pragma once
|
||||
|
||||
#include <BAN/NoCopyMove.h>
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
class CriticalScope
|
||||
{
|
||||
BAN_NON_COPYABLE(CriticalScope);
|
||||
BAN_NON_MOVABLE(CriticalScope);
|
||||
|
||||
public:
|
||||
CriticalScope()
|
||||
{
|
||||
asm volatile("pushf; cli; pop %0" : "=r"(m_flags) :: "memory");
|
||||
}
|
||||
|
||||
~CriticalScope()
|
||||
{
|
||||
asm volatile("push %0; popf" :: "rm"(m_flags) : "memory", "cc");
|
||||
}
|
||||
|
||||
private:
|
||||
size_t m_flags;
|
||||
};
|
||||
|
||||
}
|
|
@ -18,6 +18,4 @@ public:
|
|||
static InterruptController& get();
|
||||
};
|
||||
|
||||
uintptr_t disable_interrupts_and_get_flags();
|
||||
void restore_flags(uintptr_t);
|
||||
bool interrupts_enabled();
|
|
@ -26,18 +26,6 @@ void InterruptController::initialize(bool force_pic)
|
|||
s_instance = PIC::create();
|
||||
}
|
||||
|
||||
uintptr_t disable_interrupts_and_get_flags()
|
||||
{
|
||||
uintptr_t flags;
|
||||
asm volatile("pushf; cli; pop %0" : "=r"(flags) :: "memory");
|
||||
return flags;
|
||||
}
|
||||
|
||||
void restore_flags(uintptr_t flags)
|
||||
{
|
||||
asm volatile("push %0; popf" :: "rm"(flags) : "memory", "cc");
|
||||
}
|
||||
|
||||
bool interrupts_enabled()
|
||||
{
|
||||
uintptr_t flags;
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
#include <kernel/Arch.h>
|
||||
#include <kernel/Attributes.h>
|
||||
#include <kernel/CriticalScope.h>
|
||||
#include <kernel/InterruptController.h>
|
||||
#include <kernel/Scheduler.h>
|
||||
|
||||
#include <kernel/PCI.h>
|
||||
|
||||
#if 1
|
||||
#define VERIFY_STI() ASSERT(interrupts_enabled())
|
||||
#define VERIFY_CLI() ASSERT(!interrupts_enabled())
|
||||
|
@ -89,10 +88,9 @@ namespace Kernel
|
|||
|
||||
BAN::ErrorOr<void> Scheduler::add_thread(BAN::RefPtr<Thread> thread)
|
||||
{
|
||||
auto flags = disable_interrupts_and_get_flags();
|
||||
BAN::ErrorOr<void> result = m_active_threads.emplace_back(thread);
|
||||
restore_flags(flags);
|
||||
return result;
|
||||
Kernel::CriticalScope critical;
|
||||
TRY(m_active_threads.emplace_back(thread));
|
||||
return {};
|
||||
}
|
||||
|
||||
void Scheduler::advance_current_thread()
|
||||
|
|
|
@ -195,7 +195,7 @@ argument_done:
|
|||
if (thread_or_error.is_error())
|
||||
return TTY_PRINTLN("{}", thread_or_error.error());
|
||||
|
||||
MUST(Scheduler::get().add_thread(thread));
|
||||
MUST(Scheduler::get().add_thread(thread_or_error.release_value()));
|
||||
|
||||
while (s_thread_spinlock.is_locked());
|
||||
}
|
||||
|
|
|
@ -47,6 +47,7 @@ namespace Kernel
|
|||
|
||||
Thread::~Thread()
|
||||
{
|
||||
dprintln("thread {} destruct", tid());
|
||||
kfree(m_stack_base);
|
||||
}
|
||||
|
||||
|
|
|
@ -103,7 +103,6 @@ extern "C" void kernel_main()
|
|||
|
||||
MUST(Scheduler::initialize());
|
||||
Scheduler& scheduler = Scheduler::get();
|
||||
#if 1
|
||||
MUST(scheduler.add_thread(MUST(Thread::create(
|
||||
[terminal_driver]
|
||||
{
|
||||
|
@ -120,7 +119,6 @@ extern "C" void kernel_main()
|
|||
terminal_driver->set_font(font_or_error.release_value());
|
||||
}
|
||||
))));
|
||||
#endif
|
||||
MUST(scheduler.add_thread(MUST(Thread::create(
|
||||
[tty1]
|
||||
{
|
||||
|
|
|
@ -1,21 +1,13 @@
|
|||
#include <BAN/Errors.h>
|
||||
#include <BAN/Math.h>
|
||||
#include <kernel/CriticalScope.h>
|
||||
#include <kernel/kmalloc.h>
|
||||
#include <kernel/kprint.h>
|
||||
#include <kernel/multiboot.h>
|
||||
|
||||
#include <kernel/SpinLock.h>
|
||||
#include <kernel/LockGuard.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define MB (1 << 20)
|
||||
|
||||
static constexpr size_t s_kmalloc_min_align = alignof(max_align_t);
|
||||
|
||||
static Kernel::SpinLock s_general_lock;
|
||||
static Kernel::SpinLock s_fixed_lock;
|
||||
|
||||
struct kmalloc_node
|
||||
{
|
||||
void set_align(ptrdiff_t align) { m_align = align; }
|
||||
|
@ -192,8 +184,6 @@ void kmalloc_dump_info()
|
|||
|
||||
static void* kmalloc_fixed()
|
||||
{
|
||||
Kernel::LockGuard guard(s_fixed_lock);
|
||||
|
||||
auto& info = s_kmalloc_fixed_info;
|
||||
|
||||
if (!info.free_list_head)
|
||||
|
@ -233,8 +223,6 @@ static void* kmalloc_fixed()
|
|||
|
||||
static void* kmalloc_impl(size_t size, size_t align)
|
||||
{
|
||||
Kernel::LockGuard guard(s_general_lock);
|
||||
|
||||
ASSERT(align % s_kmalloc_min_align == 0);
|
||||
ASSERT(size % s_kmalloc_min_align == 0);
|
||||
|
||||
|
@ -309,6 +297,7 @@ static constexpr bool is_power_of_two(size_t value)
|
|||
|
||||
void* kmalloc(size_t size, size_t align)
|
||||
{
|
||||
|
||||
const kmalloc_info& info = s_kmalloc_info;
|
||||
|
||||
if (size == 0 || size >= info.size)
|
||||
|
@ -316,6 +305,8 @@ void* kmalloc(size_t size, size_t align)
|
|||
|
||||
ASSERT(is_power_of_two(align));
|
||||
|
||||
Kernel::CriticalScope critical;
|
||||
|
||||
// if the size fits into fixed node, we will try to use that since it is faster
|
||||
if (align == s_kmalloc_min_align && size <= sizeof(kmalloc_fixed_info::node::data))
|
||||
if (void* result = kmalloc_fixed())
|
||||
|
@ -334,10 +325,10 @@ void kfree(void* address)
|
|||
uintptr_t address_uint = (uintptr_t)address;
|
||||
ASSERT(address_uint % s_kmalloc_min_align == 0);
|
||||
|
||||
Kernel::CriticalScope critical;
|
||||
|
||||
if (s_kmalloc_fixed_info.base <= address_uint && address_uint < s_kmalloc_fixed_info.end)
|
||||
{
|
||||
Kernel::LockGuard guard(s_fixed_lock);
|
||||
|
||||
auto& info = s_kmalloc_fixed_info;
|
||||
ASSERT(info.used_list_head);
|
||||
|
||||
|
@ -369,8 +360,6 @@ void kfree(void* address)
|
|||
}
|
||||
else if (s_kmalloc_info.base <= address_uint && address_uint < s_kmalloc_info.end)
|
||||
{
|
||||
Kernel::LockGuard guard(s_general_lock);
|
||||
|
||||
auto& info = s_kmalloc_info;
|
||||
|
||||
auto* node = info.from_address(address);
|
||||
|
|
Loading…
Reference in New Issue