From 17813f3fcff41c5aee3bccac86911b534b1ae5fb Mon Sep 17 00:00:00 2001 From: Bananymous Date: Sun, 23 Aug 2026 14:19:32 +0300 Subject: [PATCH] Kernel: Store SchedulerThreadNode directly in Thread Having the pointer indirection was weird and forced allocations when adding/binding a new thread :P --- kernel/include/kernel/Processor.h | 5 +- kernel/include/kernel/Scheduler.h | 8 +- kernel/include/kernel/Thread.h | 3 +- kernel/kernel/ACPI/ACPI.cpp | 5 +- kernel/kernel/ACPI/EmbeddedController.cpp | 2 +- kernel/kernel/FS/DevFS/FileSystem.cpp | 6 +- kernel/kernel/Input/InputDevice.cpp | 3 +- kernel/kernel/Input/PS2/Controller.cpp | 2 +- kernel/kernel/Networking/E1000/E1000.cpp | 7 +- kernel/kernel/Networking/Loopback.cpp | 7 +- kernel/kernel/Networking/RTL8169/RTL8169.cpp | 7 +- kernel/kernel/Networking/TCPSocket.cpp | 2 +- kernel/kernel/Process.cpp | 29 +--- kernel/kernel/Scheduler.cpp | 152 +++++++++---------- kernel/kernel/Thread.cpp | 1 + kernel/kernel/ThreadBlocker.cpp | 2 +- kernel/kernel/USB/Hub/HubDriver.cpp | 2 +- kernel/kernel/USB/XHCI/Controller.cpp | 2 +- kernel/kernel/kernel.cpp | 2 +- 19 files changed, 103 insertions(+), 144 deletions(-) diff --git a/kernel/include/kernel/Processor.h b/kernel/include/kernel/Processor.h index 30c6266b..77d31d88 100644 --- a/kernel/include/kernel/Processor.h +++ b/kernel/include/kernel/Processor.h @@ -22,7 +22,6 @@ namespace Kernel class GDT; class IDT; class Scheduler; - class SchedulerThreadNode; class Thread; #if ARCH(x86_64) || ARCH(i686) @@ -54,8 +53,8 @@ namespace Kernel union { TLBEntry flush_tlb; - SchedulerThreadNode* new_thread; - SchedulerThreadNode* unblock_thread; + Thread* new_thread; + Thread* unblock_thread; bool dummy; }; }; diff --git a/kernel/include/kernel/Scheduler.h b/kernel/include/kernel/Scheduler.h index 0cf7bc23..979d1334 100644 --- a/kernel/include/kernel/Scheduler.h +++ b/kernel/include/kernel/Scheduler.h @@ -41,9 +41,8 @@ namespace Kernel void on_timer_interrupt(); void on_yield(YieldRegisters*); - static BAN::ErrorOr bind_thread_to_processor(Thread*, ProcessorID); - // if thread is already bound, this will never fail - BAN::ErrorOr add_thread(Thread*); + static void bind_thread_to_processor(Thread*, ProcessorID); + void add_thread(Thread*); void block_current_thread(ThreadBlocker* thread_blocker, uint64_t wake_time_ns, BaseMutex* mutex); void unblock_thread(Thread*); @@ -68,9 +67,6 @@ namespace Kernel class ProcessorID find_least_loaded_processor() const; - void add_thread(SchedulerThreadNode*); - void unblock_thread(SchedulerThreadNode*); - private: SchedulerQueue m_run_list; SchedulerHeap m_block_list; diff --git a/kernel/include/kernel/Thread.h b/kernel/include/kernel/Thread.h index ea52246c..e6121a8f 100644 --- a/kernel/include/kernel/Thread.h +++ b/kernel/include/kernel/Thread.h @@ -7,6 +7,7 @@ #include #include #include +#include #include @@ -192,7 +193,7 @@ namespace Kernel vaddr_t m_fsbase { 0 }; vaddr_t m_gsbase { 0 }; - SchedulerThreadNode* m_scheduler_node { nullptr }; + SchedulerThreadNode m_scheduler_node; YieldRegisters m_yield_registers { }; diff --git a/kernel/kernel/ACPI/ACPI.cpp b/kernel/kernel/ACPI/ACPI.cpp index e8609f58..94f950fe 100644 --- a/kernel/kernel/ACPI/ACPI.cpp +++ b/kernel/kernel/ACPI/ACPI.cpp @@ -1069,10 +1069,11 @@ acpi_release_global_lock: if (auto thread_or_error = Thread::create_kernel([](void*) { get().acpi_event_task(); }, nullptr); thread_or_error.is_error()) dwarnln("Failed to create ACPI thread, power button will not work: {}", thread_or_error.error()); - else if (auto ret = Processor::scheduler().add_thread(thread_or_error.value()); ret.is_error()) - dwarnln("Failed to create ACPI thread, power button will not work: {}", ret.error()); else + { + Processor::scheduler().add_thread(thread_or_error.value()); dprintln("Initialized ACPI interrupts"); + } } if (auto ret = initialize_embedded_controllers(); ret.is_error()) diff --git a/kernel/kernel/ACPI/EmbeddedController.cpp b/kernel/kernel/ACPI/EmbeddedController.cpp index 86c7c89b..3840c824 100644 --- a/kernel/kernel/ACPI/EmbeddedController.cpp +++ b/kernel/kernel/ACPI/EmbeddedController.cpp @@ -37,7 +37,7 @@ namespace Kernel::ACPI return BAN::Error::from_errno(ENOMEM); auto* thread = TRY(Thread::create_kernel([](void* ec) { static_cast(ec)->thread_task(); }, embedded_controller_ptr)); - TRY(Processor::scheduler().add_thread(thread)); + Processor::scheduler().add_thread(thread); auto embedded_controller = BAN::UniqPtr::adopt(embedded_controller_ptr); embedded_controller->m_thread = thread; diff --git a/kernel/kernel/FS/DevFS/FileSystem.cpp b/kernel/kernel/FS/DevFS/FileSystem.cpp index b363b69a..705fb17f 100644 --- a/kernel/kernel/FS/DevFS/FileSystem.cpp +++ b/kernel/kernel/FS/DevFS/FileSystem.cpp @@ -63,7 +63,7 @@ namespace Kernel } }, s_instance )); - MUST(Processor::scheduler().add_thread(updater_thread)); + Processor::scheduler().add_thread(updater_thread); auto* disk_cache_drop_thread = MUST(Thread::create_kernel( [](void* _devfs) @@ -93,7 +93,7 @@ namespace Kernel } }, s_instance )); - MUST(Processor::scheduler().add_thread(disk_cache_drop_thread)); + Processor::scheduler().add_thread(disk_cache_drop_thread); auto* disk_sync_thread = MUST(Thread::create_kernel( [](void* _devfs) @@ -129,7 +129,7 @@ namespace Kernel } }, s_instance )); - MUST(Processor::scheduler().add_thread(disk_sync_thread)); + Processor::scheduler().add_thread(disk_sync_thread); } void DevFileSystem::initiate_disk_cache_drop() diff --git a/kernel/kernel/Input/InputDevice.cpp b/kernel/kernel/Input/InputDevice.cpp index 14dc6119..eb5c1e11 100644 --- a/kernel/kernel/Input/InputDevice.cpp +++ b/kernel/kernel/Input/InputDevice.cpp @@ -307,8 +307,7 @@ namespace Kernel BAN::ErrorOr KeyboardDevice::initialize_tty_thread() { auto* thread = TRY(Thread::create_kernel(tty_keyboard_thread, nullptr)); - ASSERT(thread); - TRY(Processor::scheduler().add_thread(thread)); + Processor::scheduler().add_thread(thread); return {}; } diff --git a/kernel/kernel/Input/PS2/Controller.cpp b/kernel/kernel/Input/PS2/Controller.cpp index e4360930..bf31a73a 100644 --- a/kernel/kernel/Input/PS2/Controller.cpp +++ b/kernel/kernel/Input/PS2/Controller.cpp @@ -551,7 +551,7 @@ namespace Kernel::Input static_cast(info)->controller->device_initialize_task(info); }, &info )); - TRY(Processor::scheduler().add_thread(init_thread)); + Processor::scheduler().add_thread(init_thread); while (!info.thread_started) Processor::pause(); diff --git a/kernel/kernel/Networking/E1000/E1000.cpp b/kernel/kernel/Networking/E1000/E1000.cpp index e6aa02d3..072f6ad4 100644 --- a/kernel/kernel/Networking/E1000/E1000.cpp +++ b/kernel/kernel/Networking/E1000/E1000.cpp @@ -95,11 +95,8 @@ namespace Kernel auto* thread = TRY(Thread::create_kernel([](void* e1000_ptr) { static_cast(e1000_ptr)->receive_thread(); }, this)); - if (auto ret = Processor::scheduler().add_thread(thread); ret.is_error()) - { - delete thread; - return ret.release_error(); - } + + Processor::scheduler().add_thread(thread); m_thread_is_dead = false; return {}; diff --git a/kernel/kernel/Networking/Loopback.cpp b/kernel/kernel/Networking/Loopback.cpp index 6d2f670d..d2716d04 100644 --- a/kernel/kernel/Networking/Loopback.cpp +++ b/kernel/kernel/Networking/Loopback.cpp @@ -25,11 +25,8 @@ namespace Kernel auto* thread = TRY(Thread::create_kernel([](void* loopback_ptr) { static_cast(loopback_ptr)->receive_thread(); }, loopback_ptr)); - if (auto ret = Processor::scheduler().add_thread(thread); ret.is_error()) - { - delete thread; - return ret.release_error(); - } + + Processor::scheduler().add_thread(thread); loopback->m_thread_is_dead = false; loopback->set_ipv4_address({ 127, 0, 0, 1 }); diff --git a/kernel/kernel/Networking/RTL8169/RTL8169.cpp b/kernel/kernel/Networking/RTL8169/RTL8169.cpp index 006fcc32..cd4fd19e 100644 --- a/kernel/kernel/Networking/RTL8169/RTL8169.cpp +++ b/kernel/kernel/Networking/RTL8169/RTL8169.cpp @@ -75,11 +75,8 @@ namespace Kernel auto* thread = TRY(Thread::create_kernel([](void* rtl8169_ptr) { static_cast(rtl8169_ptr)->receive_thread(); }, this)); - if (auto ret = Processor::scheduler().add_thread(thread); ret.is_error()) - { - delete thread; - return ret.release_error(); - } + + Processor::scheduler().add_thread(thread); m_rx_thread_is_dead = false; return {}; diff --git a/kernel/kernel/Networking/TCPSocket.cpp b/kernel/kernel/Networking/TCPSocket.cpp index 6cc214c6..88d19b10 100644 --- a/kernel/kernel/Networking/TCPSocket.cpp +++ b/kernel/kernel/Networking/TCPSocket.cpp @@ -45,7 +45,7 @@ namespace Kernel reinterpret_cast(socket_ptr)->process_task(); }, socket.ptr() )); - TRY(Processor::scheduler().add_thread(socket->m_thread)); + Processor::scheduler().add_thread(socket->m_thread); // hack to keep socket alive until its process starts socket->ref(); return socket; diff --git a/kernel/kernel/Process.cpp b/kernel/kernel/Process.cpp index aadf34f6..56dd57ac 100644 --- a/kernel/kernel/Process.cpp +++ b/kernel/kernel/Process.cpp @@ -237,9 +237,8 @@ namespace Kernel #endif } - // NOTE: make sure the last two `MUST`s don't fail + // NOTE: make sure the last `MUST` doesn't fail TRY(process->m_threads.reserve(1)); - TRY(Processor::scheduler().bind_thread_to_processor(thread, Processor::current_id())); { SpinLockGuard _(s_process_lock); @@ -247,7 +246,7 @@ namespace Kernel } MUST(process->m_threads.push_back(thread)); - MUST(Processor::scheduler().add_thread(thread)); + Processor::scheduler().add_thread(thread); process_deleter.disable(); thread_deleter.disable(); @@ -877,9 +876,8 @@ namespace Kernel Thread* thread = TRY(Thread::current().clone(forked, sp, ip)); BAN::ScopeGuard thread_deleter([thread] { delete thread; }); - // NOTE: make sure the last two `MUST`s don't fail + // NOTE: make sure the last `MUST` doesn't fail TRY(forked->m_threads.reserve(1)); - TRY(Processor::scheduler().bind_thread_to_processor(thread, Processor::current_id())); { SpinLockGuard _(s_process_lock); @@ -905,7 +903,7 @@ namespace Kernel ASSERT(this == &Process::current()); MUST(forked->m_threads.push_back(thread)); - MUST(Processor::scheduler().add_thread(thread)); + Processor::scheduler().add_thread(thread); process_deleter.disable(); thread_deleter.disable(); @@ -1072,14 +1070,6 @@ namespace Kernel #endif } - // NOTE: bind new thread to this processor so it wont be rescheduled before end of this function - // and so that adding the thread to the scheduler cannot fail - if (auto ret = Scheduler::bind_thread_to_processor(new_thread, Processor::current_id()); ret.is_error()) - { - Processor::set_interrupt_state(InterruptState::Enabled); - delete new_thread; - return ret.release_error(); - } RWLockWRGuard wr_guard(m_memory_region_lock); @@ -1103,7 +1093,9 @@ namespace Kernel m_threads.front()->m_process = nullptr; m_threads.front()->give_keep_alive_page_table(BAN::move(m_page_table)); - MUST(Processor::scheduler().add_thread(new_thread)); + // NOTE: bind new thread to this processor so it wont be rescheduled before end of this function + Scheduler::bind_thread_to_processor(new_thread, Processor::current_id()); + Processor::scheduler().add_thread(new_thread); m_threads.front() = new_thread; for (size_t i = 0; i < sizeof(m_signal_handlers) / sizeof(*m_signal_handlers); i++) @@ -3580,12 +3572,7 @@ namespace Kernel LockGuard _1(m_process_lock); TRY(m_threads.push_back(thread)); - if (auto ret = Processor::scheduler().add_thread(thread); ret.is_error()) - { - m_threads.pop_back(); - delete thread; - return ret.release_error(); - } + Processor::scheduler().add_thread(thread); return thread->tid(); } diff --git a/kernel/kernel/Scheduler.cpp b/kernel/kernel/Scheduler.cpp index c71b91b8..bf7ec899 100644 --- a/kernel/kernel/Scheduler.cpp +++ b/kernel/kernel/Scheduler.cpp @@ -33,9 +33,6 @@ namespace Kernel static SpinLock s_processor_info_time_lock; static BAN::Array s_processor_infos; - - static BAN::Atomic s_next_processor_index { 0 }; - BAN::ErrorOr Scheduler::create() { auto* scheduler = new Scheduler(); @@ -151,7 +148,6 @@ namespace Kernel if (&PageTable::current() != &PageTable::kernel()) PageTable::kernel().load(); delete m_current->thread; - delete m_current; m_thread_count--; break; case Thread::State::Executing: @@ -185,7 +181,6 @@ namespace Kernel if (&PageTable::current() != &PageTable::kernel()) PageTable::kernel().load(); delete m_current->thread; - delete m_current; m_thread_count--; } @@ -236,7 +231,7 @@ namespace Kernel const uint64_t current_ns = SystemTimer::get().ns_since_boot(); while (!m_block_list.empty() && current_ns >= m_block_list.front()->wake_time_ns) - unblock_thread(m_block_list.front()); + unblock_thread(m_block_list.front()->thread); } void Scheduler::update_wake_up_deadline() @@ -300,60 +295,6 @@ namespace Kernel update_wake_up_deadline(); } - void Scheduler::unblock_thread(SchedulerThreadNode* node) - { - auto state = Processor::get_interrupt_state(); - Processor::set_interrupt_state(InterruptState::Disabled); - - if (node->processor_id == Processor::current_id()) - { - if (!node->blocked) - return; - ASSERT(node != m_current); - Processor::set_disable_smp_messages(true); - m_block_list.pop(node); - if (auto* blocker = node->blocker.load()) - blocker->remove_thread_from_block_queue(node); - node->blocked = false; - m_run_list.push(node); - update_most_loaded_node_list(node, &m_run_list); - Processor::set_disable_smp_messages(false); - } - else - { - Processor::send_smp_message(node->processor_id, { - .type = Processor::SMPMessage::Type::UnblockThread, - .unblock_thread = node - }); - } - - Processor::set_interrupt_state(state); - } - - void Scheduler::add_thread(SchedulerThreadNode* node) - { - auto state = Processor::get_interrupt_state(); - Processor::set_interrupt_state(InterruptState::Disabled); - - ASSERT(node->processor_id == Processor::current_id()); - - if (!node->blocked) - m_run_list.push(node); - else - { - m_block_list.push(node); - if (m_block_list.front() == node) - update_wake_up_deadline(); - } - - if (auto* thread = node->thread; thread->is_userspace() && thread->has_process()) - thread->update_processor_index_address(); - - m_thread_count++; - - Processor::set_interrupt_state(state); - } - ProcessorID Scheduler::find_least_loaded_processor() const { ProcessorID least_loaded_id = Processor::current_id(); @@ -535,7 +476,7 @@ namespace Kernel thread_info.node->processor_id = least_loaded_id; Processor::send_smp_message(least_loaded_id, { .type = Processor::SMPMessage::Type::NewThread, - .new_thread = thread_info.node + .new_thread = thread_info.node->thread }); thread_info = { @@ -563,41 +504,52 @@ namespace Kernel m_last_load_balance_ns += s_load_balance_interval_ns; } - BAN::ErrorOr Scheduler::bind_thread_to_processor(Thread* thread, ProcessorID processor_id) + void Scheduler::bind_thread_to_processor(Thread* thread, ProcessorID processor_id) { - ASSERT(thread->m_scheduler_node == nullptr); - auto* new_node = new SchedulerThreadNode(thread); - if (new_node == nullptr) - return BAN::Error::from_errno(ENOMEM); - ASSERT(processor_id != PROCESSOR_NONE); - new_node->processor_id = processor_id; - thread->m_scheduler_node = new_node; - - return {}; + ASSERT(thread->m_scheduler_node.processor_id == PROCESSOR_NONE); + thread->m_scheduler_node.processor_id = processor_id; } - BAN::ErrorOr Scheduler::add_thread(Thread* thread) + void Scheduler::add_thread(Thread* thread) { - if (thread->m_scheduler_node == nullptr) + ASSERT(thread); + + if (thread->m_scheduler_node.processor_id == PROCESSOR_NONE) { + static BAN::Atomic s_next_processor_index { 0 }; const size_t processor_index = s_next_processor_index++ % Processor::count(); const auto processor_id = Processor::id_from_index(processor_index); - TRY(bind_thread_to_processor(thread, processor_id)); + bind_thread_to_processor(thread, processor_id); } - auto* node = thread->m_scheduler_node; - if (node->processor_id == Processor::current_id()) - add_thread(node); + if (const auto proc_id = thread->m_scheduler_node.processor_id; proc_id != Processor::current_id()) + { + Processor::send_smp_message(proc_id, { + .type = Processor::SMPMessage::Type::NewThread, + .new_thread = thread + }); + return; + } + + const auto state = Processor::get_interrupt_state(); + Processor::set_interrupt_state(InterruptState::Disabled); + + if (!thread->m_scheduler_node.blocked) + m_run_list.push(&thread->m_scheduler_node); else { - Processor::send_smp_message(node->processor_id, { - .type = Processor::SMPMessage::Type::NewThread, - .new_thread = node - }); + m_block_list.push(&thread->m_scheduler_node); + if (m_block_list.front() == &thread->m_scheduler_node) + update_wake_up_deadline(); } - return {}; + if (thread->is_userspace() && thread->has_process()) + thread->update_processor_index_address(); + + m_thread_count++; + + Processor::set_interrupt_state(state); } void Scheduler::block_current_thread(ThreadBlocker* blocker, uint64_t wake_time_ns, BaseMutex* mutex) @@ -605,7 +557,7 @@ namespace Kernel if (SystemTimer::get().ns_since_boot() >= wake_time_ns) return; - auto state = Processor::get_interrupt_state(); + const auto state = Processor::get_interrupt_state(); Processor::set_interrupt_state(InterruptState::Disabled); ASSERT(m_current->processor_id == Processor::current_id()); @@ -639,7 +591,39 @@ namespace Kernel void Scheduler::unblock_thread(Thread* thread) { - unblock_thread(thread->m_scheduler_node); + if (const auto proc_id = thread->m_scheduler_node.processor_id; proc_id != Processor::current_id()) + { + Processor::send_smp_message(proc_id, { + .type = Processor::SMPMessage::Type::UnblockThread, + .unblock_thread = thread + }); + return; + } + + const auto state = Processor::get_interrupt_state(); + Processor::set_interrupt_state(InterruptState::Disabled); + + if (!thread->m_scheduler_node.blocked) + { + Processor::set_interrupt_state(state); + return; + } + + ASSERT(&thread->m_scheduler_node != m_current); + + Processor::set_disable_smp_messages(true); + + m_block_list.pop(&thread->m_scheduler_node); + if (auto* blocker = thread->m_scheduler_node.blocker.load()) + blocker->remove_thread_from_block_queue(&thread->m_scheduler_node); + thread->m_scheduler_node.blocked = false; + + m_run_list.push(&thread->m_scheduler_node); + update_most_loaded_node_list(&thread->m_scheduler_node, &m_run_list); + + Processor::set_disable_smp_messages(false); + + Processor::set_interrupt_state(state); } Thread& Scheduler::current_thread() diff --git a/kernel/kernel/Thread.cpp b/kernel/kernel/Thread.cpp index c863b1bb..bf2dbeeb 100644 --- a/kernel/kernel/Thread.cpp +++ b/kernel/kernel/Thread.cpp @@ -240,6 +240,7 @@ namespace Kernel Thread::Thread(pid_t tid, Process* process) : m_tid(tid), m_process(process) + , m_scheduler_node(this) { if (!s_default_sse_storage_initialized) initialize_default_sse_storage(); diff --git a/kernel/kernel/ThreadBlocker.cpp b/kernel/kernel/ThreadBlocker.cpp index f9313269..e8ecabb5 100644 --- a/kernel/kernel/ThreadBlocker.cpp +++ b/kernel/kernel/ThreadBlocker.cpp @@ -37,7 +37,7 @@ namespace Kernel node->block_chain_prev = nullptr; node->block_chain_next = nullptr; - Processor::scheduler().unblock_thread(node); + Processor::scheduler().unblock_thread(node->thread); node = next; } diff --git a/kernel/kernel/USB/Hub/HubDriver.cpp b/kernel/kernel/USB/Hub/HubDriver.cpp index e4c89949..de29f660 100644 --- a/kernel/kernel/USB/Hub/HubDriver.cpp +++ b/kernel/kernel/USB/Hub/HubDriver.cpp @@ -218,7 +218,7 @@ namespace Kernel } m_port_updater = TRY(Thread::create_kernel([](void* data) { reinterpret_cast(data)->port_updater_task(); }, this)); - TRY(Processor::scheduler().add_thread(m_port_updater)); + Processor::scheduler().add_thread(m_port_updater); return {}; } diff --git a/kernel/kernel/USB/XHCI/Controller.cpp b/kernel/kernel/USB/XHCI/Controller.cpp index 8a535009..f540b9db 100644 --- a/kernel/kernel/USB/XHCI/Controller.cpp +++ b/kernel/kernel/USB/XHCI/Controller.cpp @@ -149,7 +149,7 @@ namespace Kernel continue; m_port_updater = TRY(Thread::create_kernel([](void* data) { reinterpret_cast(data)->port_updater_task(); }, this)); - TRY(Processor::scheduler().add_thread(m_port_updater)); + Processor::scheduler().add_thread(m_port_updater); return {}; } diff --git a/kernel/kernel/kernel.cpp b/kernel/kernel/kernel.cpp index e3ff22fe..5547ed99 100644 --- a/kernel/kernel/kernel.cpp +++ b/kernel/kernel/kernel.cpp @@ -196,7 +196,7 @@ extern "C" void kernel_main(uint32_t boot_magic, uint32_t boot_info) MUST(Processor::scheduler().initialize()); auto* init_thread = MUST(Thread::create_kernel(init2, nullptr)); - MUST(Processor::scheduler().add_thread(init_thread)); + Processor::scheduler().add_thread(init_thread); Processor::yield(); ASSERT_NOT_REACHED();