Kernel: Store SchedulerThreadNode directly in Thread
Having the pointer indirection was weird and forced allocations when adding/binding a new thread :P
This commit is contained in:
@@ -22,7 +22,6 @@ namespace Kernel
|
|||||||
class GDT;
|
class GDT;
|
||||||
class IDT;
|
class IDT;
|
||||||
class Scheduler;
|
class Scheduler;
|
||||||
class SchedulerThreadNode;
|
|
||||||
class Thread;
|
class Thread;
|
||||||
|
|
||||||
#if ARCH(x86_64) || ARCH(i686)
|
#if ARCH(x86_64) || ARCH(i686)
|
||||||
@@ -54,8 +53,8 @@ namespace Kernel
|
|||||||
union
|
union
|
||||||
{
|
{
|
||||||
TLBEntry flush_tlb;
|
TLBEntry flush_tlb;
|
||||||
SchedulerThreadNode* new_thread;
|
Thread* new_thread;
|
||||||
SchedulerThreadNode* unblock_thread;
|
Thread* unblock_thread;
|
||||||
bool dummy;
|
bool dummy;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -41,9 +41,8 @@ namespace Kernel
|
|||||||
void on_timer_interrupt();
|
void on_timer_interrupt();
|
||||||
void on_yield(YieldRegisters*);
|
void on_yield(YieldRegisters*);
|
||||||
|
|
||||||
static BAN::ErrorOr<void> bind_thread_to_processor(Thread*, ProcessorID);
|
static void bind_thread_to_processor(Thread*, ProcessorID);
|
||||||
// if thread is already bound, this will never fail
|
void add_thread(Thread*);
|
||||||
BAN::ErrorOr<void> add_thread(Thread*);
|
|
||||||
|
|
||||||
void block_current_thread(ThreadBlocker* thread_blocker, uint64_t wake_time_ns, BaseMutex* mutex);
|
void block_current_thread(ThreadBlocker* thread_blocker, uint64_t wake_time_ns, BaseMutex* mutex);
|
||||||
void unblock_thread(Thread*);
|
void unblock_thread(Thread*);
|
||||||
@@ -68,9 +67,6 @@ namespace Kernel
|
|||||||
|
|
||||||
class ProcessorID find_least_loaded_processor() const;
|
class ProcessorID find_least_loaded_processor() const;
|
||||||
|
|
||||||
void add_thread(SchedulerThreadNode*);
|
|
||||||
void unblock_thread(SchedulerThreadNode*);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SchedulerQueue m_run_list;
|
SchedulerQueue m_run_list;
|
||||||
SchedulerHeap m_block_list;
|
SchedulerHeap m_block_list;
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
#include <kernel/InterruptStack.h>
|
#include <kernel/InterruptStack.h>
|
||||||
#include <kernel/Lock/Mutex.h>
|
#include <kernel/Lock/Mutex.h>
|
||||||
#include <kernel/Memory/VirtualRange.h>
|
#include <kernel/Memory/VirtualRange.h>
|
||||||
|
#include <kernel/SchedulerThreadNode.h>
|
||||||
|
|
||||||
#include <LibELF/AuxiliaryVector.h>
|
#include <LibELF/AuxiliaryVector.h>
|
||||||
|
|
||||||
@@ -192,7 +193,7 @@ namespace Kernel
|
|||||||
vaddr_t m_fsbase { 0 };
|
vaddr_t m_fsbase { 0 };
|
||||||
vaddr_t m_gsbase { 0 };
|
vaddr_t m_gsbase { 0 };
|
||||||
|
|
||||||
SchedulerThreadNode* m_scheduler_node { nullptr };
|
SchedulerThreadNode m_scheduler_node;
|
||||||
|
|
||||||
YieldRegisters m_yield_registers { };
|
YieldRegisters m_yield_registers { };
|
||||||
|
|
||||||
|
|||||||
@@ -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())
|
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());
|
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
|
else
|
||||||
|
{
|
||||||
|
Processor::scheduler().add_thread(thread_or_error.value());
|
||||||
dprintln("Initialized ACPI interrupts");
|
dprintln("Initialized ACPI interrupts");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (auto ret = initialize_embedded_controllers(); ret.is_error())
|
if (auto ret = initialize_embedded_controllers(); ret.is_error())
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ namespace Kernel::ACPI
|
|||||||
return BAN::Error::from_errno(ENOMEM);
|
return BAN::Error::from_errno(ENOMEM);
|
||||||
|
|
||||||
auto* thread = TRY(Thread::create_kernel([](void* ec) { static_cast<EmbeddedController*>(ec)->thread_task(); }, embedded_controller_ptr));
|
auto* thread = TRY(Thread::create_kernel([](void* ec) { static_cast<EmbeddedController*>(ec)->thread_task(); }, embedded_controller_ptr));
|
||||||
TRY(Processor::scheduler().add_thread(thread));
|
Processor::scheduler().add_thread(thread);
|
||||||
|
|
||||||
auto embedded_controller = BAN::UniqPtr<EmbeddedController>::adopt(embedded_controller_ptr);
|
auto embedded_controller = BAN::UniqPtr<EmbeddedController>::adopt(embedded_controller_ptr);
|
||||||
embedded_controller->m_thread = thread;
|
embedded_controller->m_thread = thread;
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ namespace Kernel
|
|||||||
}
|
}
|
||||||
}, s_instance
|
}, s_instance
|
||||||
));
|
));
|
||||||
MUST(Processor::scheduler().add_thread(updater_thread));
|
Processor::scheduler().add_thread(updater_thread);
|
||||||
|
|
||||||
auto* disk_cache_drop_thread = MUST(Thread::create_kernel(
|
auto* disk_cache_drop_thread = MUST(Thread::create_kernel(
|
||||||
[](void* _devfs)
|
[](void* _devfs)
|
||||||
@@ -93,7 +93,7 @@ namespace Kernel
|
|||||||
}
|
}
|
||||||
}, s_instance
|
}, 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(
|
auto* disk_sync_thread = MUST(Thread::create_kernel(
|
||||||
[](void* _devfs)
|
[](void* _devfs)
|
||||||
@@ -129,7 +129,7 @@ namespace Kernel
|
|||||||
}
|
}
|
||||||
}, s_instance
|
}, s_instance
|
||||||
));
|
));
|
||||||
MUST(Processor::scheduler().add_thread(disk_sync_thread));
|
Processor::scheduler().add_thread(disk_sync_thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DevFileSystem::initiate_disk_cache_drop()
|
void DevFileSystem::initiate_disk_cache_drop()
|
||||||
|
|||||||
@@ -307,8 +307,7 @@ namespace Kernel
|
|||||||
BAN::ErrorOr<void> KeyboardDevice::initialize_tty_thread()
|
BAN::ErrorOr<void> KeyboardDevice::initialize_tty_thread()
|
||||||
{
|
{
|
||||||
auto* thread = TRY(Thread::create_kernel(tty_keyboard_thread, nullptr));
|
auto* thread = TRY(Thread::create_kernel(tty_keyboard_thread, nullptr));
|
||||||
ASSERT(thread);
|
Processor::scheduler().add_thread(thread);
|
||||||
TRY(Processor::scheduler().add_thread(thread));
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -551,7 +551,7 @@ namespace Kernel::Input
|
|||||||
static_cast<PS2DeviceInitInfo*>(info)->controller->device_initialize_task(info);
|
static_cast<PS2DeviceInitInfo*>(info)->controller->device_initialize_task(info);
|
||||||
}, &info
|
}, &info
|
||||||
));
|
));
|
||||||
TRY(Processor::scheduler().add_thread(init_thread));
|
Processor::scheduler().add_thread(init_thread);
|
||||||
|
|
||||||
while (!info.thread_started)
|
while (!info.thread_started)
|
||||||
Processor::pause();
|
Processor::pause();
|
||||||
|
|||||||
@@ -95,11 +95,8 @@ namespace Kernel
|
|||||||
auto* thread = TRY(Thread::create_kernel([](void* e1000_ptr) {
|
auto* thread = TRY(Thread::create_kernel([](void* e1000_ptr) {
|
||||||
static_cast<E1000*>(e1000_ptr)->receive_thread();
|
static_cast<E1000*>(e1000_ptr)->receive_thread();
|
||||||
}, this));
|
}, this));
|
||||||
if (auto ret = Processor::scheduler().add_thread(thread); ret.is_error())
|
|
||||||
{
|
Processor::scheduler().add_thread(thread);
|
||||||
delete thread;
|
|
||||||
return ret.release_error();
|
|
||||||
}
|
|
||||||
m_thread_is_dead = false;
|
m_thread_is_dead = false;
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
|
|||||||
@@ -25,11 +25,8 @@ namespace Kernel
|
|||||||
auto* thread = TRY(Thread::create_kernel([](void* loopback_ptr) {
|
auto* thread = TRY(Thread::create_kernel([](void* loopback_ptr) {
|
||||||
static_cast<LoopbackInterface*>(loopback_ptr)->receive_thread();
|
static_cast<LoopbackInterface*>(loopback_ptr)->receive_thread();
|
||||||
}, loopback_ptr));
|
}, loopback_ptr));
|
||||||
if (auto ret = Processor::scheduler().add_thread(thread); ret.is_error())
|
|
||||||
{
|
Processor::scheduler().add_thread(thread);
|
||||||
delete thread;
|
|
||||||
return ret.release_error();
|
|
||||||
}
|
|
||||||
loopback->m_thread_is_dead = false;
|
loopback->m_thread_is_dead = false;
|
||||||
|
|
||||||
loopback->set_ipv4_address({ 127, 0, 0, 1 });
|
loopback->set_ipv4_address({ 127, 0, 0, 1 });
|
||||||
|
|||||||
@@ -75,11 +75,8 @@ namespace Kernel
|
|||||||
auto* thread = TRY(Thread::create_kernel([](void* rtl8169_ptr) {
|
auto* thread = TRY(Thread::create_kernel([](void* rtl8169_ptr) {
|
||||||
static_cast<RTL8169*>(rtl8169_ptr)->receive_thread();
|
static_cast<RTL8169*>(rtl8169_ptr)->receive_thread();
|
||||||
}, this));
|
}, this));
|
||||||
if (auto ret = Processor::scheduler().add_thread(thread); ret.is_error())
|
|
||||||
{
|
Processor::scheduler().add_thread(thread);
|
||||||
delete thread;
|
|
||||||
return ret.release_error();
|
|
||||||
}
|
|
||||||
m_rx_thread_is_dead = false;
|
m_rx_thread_is_dead = false;
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ namespace Kernel
|
|||||||
reinterpret_cast<TCPSocket*>(socket_ptr)->process_task();
|
reinterpret_cast<TCPSocket*>(socket_ptr)->process_task();
|
||||||
}, socket.ptr()
|
}, 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
|
// hack to keep socket alive until its process starts
|
||||||
socket->ref();
|
socket->ref();
|
||||||
return socket;
|
return socket;
|
||||||
|
|||||||
@@ -237,9 +237,8 @@ namespace Kernel
|
|||||||
#endif
|
#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(process->m_threads.reserve(1));
|
||||||
TRY(Processor::scheduler().bind_thread_to_processor(thread, Processor::current_id()));
|
|
||||||
|
|
||||||
{
|
{
|
||||||
SpinLockGuard _(s_process_lock);
|
SpinLockGuard _(s_process_lock);
|
||||||
@@ -247,7 +246,7 @@ namespace Kernel
|
|||||||
}
|
}
|
||||||
|
|
||||||
MUST(process->m_threads.push_back(thread));
|
MUST(process->m_threads.push_back(thread));
|
||||||
MUST(Processor::scheduler().add_thread(thread));
|
Processor::scheduler().add_thread(thread);
|
||||||
|
|
||||||
process_deleter.disable();
|
process_deleter.disable();
|
||||||
thread_deleter.disable();
|
thread_deleter.disable();
|
||||||
@@ -877,9 +876,8 @@ namespace Kernel
|
|||||||
Thread* thread = TRY(Thread::current().clone(forked, sp, ip));
|
Thread* thread = TRY(Thread::current().clone(forked, sp, ip));
|
||||||
BAN::ScopeGuard thread_deleter([thread] { delete thread; });
|
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(forked->m_threads.reserve(1));
|
||||||
TRY(Processor::scheduler().bind_thread_to_processor(thread, Processor::current_id()));
|
|
||||||
|
|
||||||
{
|
{
|
||||||
SpinLockGuard _(s_process_lock);
|
SpinLockGuard _(s_process_lock);
|
||||||
@@ -905,7 +903,7 @@ namespace Kernel
|
|||||||
ASSERT(this == &Process::current());
|
ASSERT(this == &Process::current());
|
||||||
|
|
||||||
MUST(forked->m_threads.push_back(thread));
|
MUST(forked->m_threads.push_back(thread));
|
||||||
MUST(Processor::scheduler().add_thread(thread));
|
Processor::scheduler().add_thread(thread);
|
||||||
|
|
||||||
process_deleter.disable();
|
process_deleter.disable();
|
||||||
thread_deleter.disable();
|
thread_deleter.disable();
|
||||||
@@ -1072,14 +1070,6 @@ namespace Kernel
|
|||||||
#endif
|
#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);
|
RWLockWRGuard wr_guard(m_memory_region_lock);
|
||||||
|
|
||||||
@@ -1103,7 +1093,9 @@ namespace Kernel
|
|||||||
m_threads.front()->m_process = nullptr;
|
m_threads.front()->m_process = nullptr;
|
||||||
m_threads.front()->give_keep_alive_page_table(BAN::move(m_page_table));
|
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;
|
m_threads.front() = new_thread;
|
||||||
|
|
||||||
for (size_t i = 0; i < sizeof(m_signal_handlers) / sizeof(*m_signal_handlers); i++)
|
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);
|
LockGuard _1(m_process_lock);
|
||||||
|
|
||||||
TRY(m_threads.push_back(thread));
|
TRY(m_threads.push_back(thread));
|
||||||
if (auto ret = Processor::scheduler().add_thread(thread); ret.is_error())
|
Processor::scheduler().add_thread(thread);
|
||||||
{
|
|
||||||
m_threads.pop_back();
|
|
||||||
delete thread;
|
|
||||||
return ret.release_error();
|
|
||||||
}
|
|
||||||
|
|
||||||
return thread->tid();
|
return thread->tid();
|
||||||
}
|
}
|
||||||
|
|||||||
+68
-84
@@ -33,9 +33,6 @@ namespace Kernel
|
|||||||
static SpinLock s_processor_info_time_lock;
|
static SpinLock s_processor_info_time_lock;
|
||||||
static BAN::Array<ProcessorInfo, 0xFF> s_processor_infos;
|
static BAN::Array<ProcessorInfo, 0xFF> s_processor_infos;
|
||||||
|
|
||||||
|
|
||||||
static BAN::Atomic<size_t> s_next_processor_index { 0 };
|
|
||||||
|
|
||||||
BAN::ErrorOr<Scheduler*> Scheduler::create()
|
BAN::ErrorOr<Scheduler*> Scheduler::create()
|
||||||
{
|
{
|
||||||
auto* scheduler = new Scheduler();
|
auto* scheduler = new Scheduler();
|
||||||
@@ -151,7 +148,6 @@ namespace Kernel
|
|||||||
if (&PageTable::current() != &PageTable::kernel())
|
if (&PageTable::current() != &PageTable::kernel())
|
||||||
PageTable::kernel().load();
|
PageTable::kernel().load();
|
||||||
delete m_current->thread;
|
delete m_current->thread;
|
||||||
delete m_current;
|
|
||||||
m_thread_count--;
|
m_thread_count--;
|
||||||
break;
|
break;
|
||||||
case Thread::State::Executing:
|
case Thread::State::Executing:
|
||||||
@@ -185,7 +181,6 @@ namespace Kernel
|
|||||||
if (&PageTable::current() != &PageTable::kernel())
|
if (&PageTable::current() != &PageTable::kernel())
|
||||||
PageTable::kernel().load();
|
PageTable::kernel().load();
|
||||||
delete m_current->thread;
|
delete m_current->thread;
|
||||||
delete m_current;
|
|
||||||
m_thread_count--;
|
m_thread_count--;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -236,7 +231,7 @@ namespace Kernel
|
|||||||
|
|
||||||
const uint64_t current_ns = SystemTimer::get().ns_since_boot();
|
const uint64_t current_ns = SystemTimer::get().ns_since_boot();
|
||||||
while (!m_block_list.empty() && current_ns >= m_block_list.front()->wake_time_ns)
|
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()
|
void Scheduler::update_wake_up_deadline()
|
||||||
@@ -300,60 +295,6 @@ namespace Kernel
|
|||||||
update_wake_up_deadline();
|
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 Scheduler::find_least_loaded_processor() const
|
||||||
{
|
{
|
||||||
ProcessorID least_loaded_id = Processor::current_id();
|
ProcessorID least_loaded_id = Processor::current_id();
|
||||||
@@ -535,7 +476,7 @@ namespace Kernel
|
|||||||
thread_info.node->processor_id = least_loaded_id;
|
thread_info.node->processor_id = least_loaded_id;
|
||||||
Processor::send_smp_message(least_loaded_id, {
|
Processor::send_smp_message(least_loaded_id, {
|
||||||
.type = Processor::SMPMessage::Type::NewThread,
|
.type = Processor::SMPMessage::Type::NewThread,
|
||||||
.new_thread = thread_info.node
|
.new_thread = thread_info.node->thread
|
||||||
});
|
});
|
||||||
|
|
||||||
thread_info = {
|
thread_info = {
|
||||||
@@ -563,41 +504,52 @@ namespace Kernel
|
|||||||
m_last_load_balance_ns += s_load_balance_interval_ns;
|
m_last_load_balance_ns += s_load_balance_interval_ns;
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<void> 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);
|
ASSERT(processor_id != PROCESSOR_NONE);
|
||||||
new_node->processor_id = processor_id;
|
ASSERT(thread->m_scheduler_node.processor_id == PROCESSOR_NONE);
|
||||||
thread->m_scheduler_node = new_node;
|
thread->m_scheduler_node.processor_id = processor_id;
|
||||||
|
|
||||||
return {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<void> 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<size_t> s_next_processor_index { 0 };
|
||||||
const size_t processor_index = s_next_processor_index++ % Processor::count();
|
const size_t processor_index = s_next_processor_index++ % Processor::count();
|
||||||
const auto processor_id = Processor::id_from_index(processor_index);
|
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 (const auto proc_id = thread->m_scheduler_node.processor_id; proc_id != Processor::current_id())
|
||||||
if (node->processor_id == Processor::current_id())
|
{
|
||||||
add_thread(node);
|
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
|
else
|
||||||
{
|
{
|
||||||
Processor::send_smp_message(node->processor_id, {
|
m_block_list.push(&thread->m_scheduler_node);
|
||||||
.type = Processor::SMPMessage::Type::NewThread,
|
if (m_block_list.front() == &thread->m_scheduler_node)
|
||||||
.new_thread = 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)
|
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)
|
if (SystemTimer::get().ns_since_boot() >= wake_time_ns)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto state = Processor::get_interrupt_state();
|
const auto state = Processor::get_interrupt_state();
|
||||||
Processor::set_interrupt_state(InterruptState::Disabled);
|
Processor::set_interrupt_state(InterruptState::Disabled);
|
||||||
|
|
||||||
ASSERT(m_current->processor_id == Processor::current_id());
|
ASSERT(m_current->processor_id == Processor::current_id());
|
||||||
@@ -639,7 +591,39 @@ namespace Kernel
|
|||||||
|
|
||||||
void Scheduler::unblock_thread(Thread* thread)
|
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()
|
Thread& Scheduler::current_thread()
|
||||||
|
|||||||
@@ -240,6 +240,7 @@ namespace Kernel
|
|||||||
|
|
||||||
Thread::Thread(pid_t tid, Process* process)
|
Thread::Thread(pid_t tid, Process* process)
|
||||||
: m_tid(tid), m_process(process)
|
: m_tid(tid), m_process(process)
|
||||||
|
, m_scheduler_node(this)
|
||||||
{
|
{
|
||||||
if (!s_default_sse_storage_initialized)
|
if (!s_default_sse_storage_initialized)
|
||||||
initialize_default_sse_storage();
|
initialize_default_sse_storage();
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ namespace Kernel
|
|||||||
node->block_chain_prev = nullptr;
|
node->block_chain_prev = nullptr;
|
||||||
node->block_chain_next = nullptr;
|
node->block_chain_next = nullptr;
|
||||||
|
|
||||||
Processor::scheduler().unblock_thread(node);
|
Processor::scheduler().unblock_thread(node->thread);
|
||||||
|
|
||||||
node = next;
|
node = next;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -218,7 +218,7 @@ namespace Kernel
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_port_updater = TRY(Thread::create_kernel([](void* data) { reinterpret_cast<USBHubDriver*>(data)->port_updater_task(); }, this));
|
m_port_updater = TRY(Thread::create_kernel([](void* data) { reinterpret_cast<USBHubDriver*>(data)->port_updater_task(); }, this));
|
||||||
TRY(Processor::scheduler().add_thread(m_port_updater));
|
Processor::scheduler().add_thread(m_port_updater);
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -149,7 +149,7 @@ namespace Kernel
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
m_port_updater = TRY(Thread::create_kernel([](void* data) { reinterpret_cast<XHCIController*>(data)->port_updater_task(); }, this));
|
m_port_updater = TRY(Thread::create_kernel([](void* data) { reinterpret_cast<XHCIController*>(data)->port_updater_task(); }, this));
|
||||||
TRY(Processor::scheduler().add_thread(m_port_updater));
|
Processor::scheduler().add_thread(m_port_updater);
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -196,7 +196,7 @@ extern "C" void kernel_main(uint32_t boot_magic, uint32_t boot_info)
|
|||||||
MUST(Processor::scheduler().initialize());
|
MUST(Processor::scheduler().initialize());
|
||||||
|
|
||||||
auto* init_thread = MUST(Thread::create_kernel(init2, nullptr));
|
auto* init_thread = MUST(Thread::create_kernel(init2, nullptr));
|
||||||
MUST(Processor::scheduler().add_thread(init_thread));
|
Processor::scheduler().add_thread(init_thread);
|
||||||
Processor::yield();
|
Processor::yield();
|
||||||
|
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
|
|||||||
Reference in New Issue
Block a user