mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 08:57:34 +00:00
Kernel: Boot all APS all the way into their own idle loop
This commit is contained in:
parent
691d767fba
commit
96109e9776
2 changed files with 27 additions and 22 deletions
|
@ -47,12 +47,14 @@ RecursiveSpinLock g_scheduler_lock;
|
||||||
|
|
||||||
void Scheduler::init_thread(Thread& thread)
|
void Scheduler::init_thread(Thread& thread)
|
||||||
{
|
{
|
||||||
|
ASSERT(g_scheduler_data);
|
||||||
g_scheduler_data->m_nonrunnable_threads.append(thread);
|
g_scheduler_data->m_nonrunnable_threads.append(thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scheduler::update_state_for_thread(Thread& thread)
|
void Scheduler::update_state_for_thread(Thread& thread)
|
||||||
{
|
{
|
||||||
ASSERT_INTERRUPTS_DISABLED();
|
ASSERT_INTERRUPTS_DISABLED();
|
||||||
|
ASSERT(g_scheduler_data);
|
||||||
auto& list = g_scheduler_data->thread_list_for_state(thread.state());
|
auto& list = g_scheduler_data->thread_list_for_state(thread.state());
|
||||||
|
|
||||||
if (list.contains(thread))
|
if (list.contains(thread))
|
||||||
|
@ -318,14 +320,16 @@ void Scheduler::start()
|
||||||
{
|
{
|
||||||
ASSERT_INTERRUPTS_DISABLED();
|
ASSERT_INTERRUPTS_DISABLED();
|
||||||
auto& processor = Processor::current();
|
auto& processor = Processor::current();
|
||||||
ASSERT(processor.current_thread() == nullptr);
|
ASSERT(processor.is_initialized());
|
||||||
auto& idle_thread = *processor.idle_thread();
|
auto& idle_thread = *processor.idle_thread();
|
||||||
processor.set_current_thread(idle_thread);
|
ASSERT(processor.current_thread() == &idle_thread);
|
||||||
|
ASSERT(processor.idle_thread() == &idle_thread);
|
||||||
idle_thread.set_ticks_left(time_slice_for(idle_thread));
|
idle_thread.set_ticks_left(time_slice_for(idle_thread));
|
||||||
idle_thread.did_schedule();
|
idle_thread.did_schedule();
|
||||||
idle_thread.set_initialized(true);
|
idle_thread.set_initialized(true);
|
||||||
Processor::init_context(idle_thread);
|
Processor::init_context(idle_thread);
|
||||||
idle_thread.set_state(Thread::Running);
|
idle_thread.set_state(Thread::Running);
|
||||||
|
ASSERT(idle_thread.affinity() == (1u << processor.id()));
|
||||||
processor.initialize_context_switching(idle_thread);
|
processor.initialize_context_switching(idle_thread);
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
@ -354,7 +358,7 @@ bool Scheduler::pick_next()
|
||||||
auto name = process.name();
|
auto name = process.name();
|
||||||
auto pid = process.pid();
|
auto pid = process.pid();
|
||||||
auto exit_status = Process::reap(process);
|
auto exit_status = Process::reap(process);
|
||||||
dbg() << "Scheduler: Reaped unparented process " << name << "(" << pid << "), exit status: " << exit_status.si_status;
|
dbg() << "Scheduler[" << Processor::current().id() << "]: Reaped unparented process " << name << "(" << pid << "), exit status: " << exit_status.si_status;
|
||||||
}
|
}
|
||||||
return IterationDecision::Continue;
|
return IterationDecision::Continue;
|
||||||
}
|
}
|
||||||
|
@ -386,7 +390,7 @@ bool Scheduler::pick_next()
|
||||||
return IterationDecision::Continue;
|
return IterationDecision::Continue;
|
||||||
if (was_blocked) {
|
if (was_blocked) {
|
||||||
#ifdef SCHEDULER_DEBUG
|
#ifdef SCHEDULER_DEBUG
|
||||||
dbg() << "Unblock " << thread << " due to signal";
|
dbg() << "Scheduler[" << Processor::current().id() << "]:Unblock " << thread << " due to signal";
|
||||||
#endif
|
#endif
|
||||||
ASSERT(thread.m_blocker != nullptr);
|
ASSERT(thread.m_blocker != nullptr);
|
||||||
thread.m_blocker->set_interrupted_by_signal();
|
thread.m_blocker->set_interrupted_by_signal();
|
||||||
|
@ -411,6 +415,7 @@ bool Scheduler::pick_next()
|
||||||
|
|
||||||
Vector<Thread*, 128> sorted_runnables;
|
Vector<Thread*, 128> sorted_runnables;
|
||||||
for_each_runnable([&sorted_runnables](auto& thread) {
|
for_each_runnable([&sorted_runnables](auto& thread) {
|
||||||
|
if ((thread.affinity() & (1u << Processor::current().id())) != 0)
|
||||||
sorted_runnables.append(&thread);
|
sorted_runnables.append(&thread);
|
||||||
return IterationDecision::Continue;
|
return IterationDecision::Continue;
|
||||||
});
|
});
|
||||||
|
@ -439,7 +444,7 @@ bool Scheduler::pick_next()
|
||||||
thread_to_schedule = Processor::current().idle_thread();
|
thread_to_schedule = Processor::current().idle_thread();
|
||||||
|
|
||||||
#ifdef SCHEDULER_DEBUG
|
#ifdef SCHEDULER_DEBUG
|
||||||
dbg() << "Scheduler: Switch to " << *thread_to_schedule << " @ " << String::format("%04x:%08x", thread_to_schedule->tss().cs, thread_to_schedule->tss().eip);
|
dbg() << "Scheduler[" << Processor::current().id() << "]: Switch to " << *thread_to_schedule << " @ " << String::format("%04x:%08x", thread_to_schedule->tss().cs, thread_to_schedule->tss().eip);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
|
@ -451,7 +456,7 @@ bool Scheduler::yield()
|
||||||
auto& proc = Processor::current();
|
auto& proc = Processor::current();
|
||||||
auto current_thread = Thread::current();
|
auto current_thread = Thread::current();
|
||||||
#ifdef SCHEDULER_DEBUG
|
#ifdef SCHEDULER_DEBUG
|
||||||
dbg() << "Scheduler: yielding thread " << *current_thread << " in_trap: " << proc.in_trap() << " in_irq: " << proc.in_irq();
|
dbg() << "Scheduler[" << Processor::current().id() << "]: yielding thread " << *current_thread << " in_irq: " << proc.in_irq();
|
||||||
#endif
|
#endif
|
||||||
InterruptDisabler disabler;
|
InterruptDisabler disabler;
|
||||||
ASSERT(current_thread != nullptr);
|
ASSERT(current_thread != nullptr);
|
||||||
|
@ -462,7 +467,7 @@ bool Scheduler::yield()
|
||||||
} else if (!Scheduler::pick_next())
|
} else if (!Scheduler::pick_next())
|
||||||
return false;
|
return false;
|
||||||
#ifdef SCHEDULER_DEBUG
|
#ifdef SCHEDULER_DEBUG
|
||||||
dbg() << "Scheduler: yield returns to thread " << *current_thread << " in_trap: " << proc.in_trap() << " in_irq: " << proc.in_irq();
|
dbg() << "Scheduler[" << Processor::current().id() << "]: yield returns to thread " << *current_thread << " in_irq: " << proc.in_irq();
|
||||||
#endif
|
#endif
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -481,7 +486,7 @@ bool Scheduler::donate_to(Thread* beneficiary, const char* reason)
|
||||||
|
|
||||||
unsigned ticks_to_donate = min(ticks_left - 1, time_slice_for(*beneficiary));
|
unsigned ticks_to_donate = min(ticks_left - 1, time_slice_for(*beneficiary));
|
||||||
#ifdef SCHEDULER_DEBUG
|
#ifdef SCHEDULER_DEBUG
|
||||||
dbg() << "Scheduler: Donating " << ticks_to_donate << " ticks to " << *beneficiary << ", reason=" << reason;
|
dbg() << "Scheduler[" << Processor::current().id() << "]: Donating " << ticks_to_donate << " ticks to " << *beneficiary << ", reason=" << reason;
|
||||||
#endif
|
#endif
|
||||||
beneficiary->set_ticks_left(ticks_to_donate);
|
beneficiary->set_ticks_left(ticks_to_donate);
|
||||||
Scheduler::context_switch(*beneficiary);
|
Scheduler::context_switch(*beneficiary);
|
||||||
|
@ -504,7 +509,7 @@ bool Scheduler::context_switch(Thread& thread)
|
||||||
current_thread->set_state(Thread::Runnable);
|
current_thread->set_state(Thread::Runnable);
|
||||||
|
|
||||||
#ifdef LOG_EVERY_CONTEXT_SWITCH
|
#ifdef LOG_EVERY_CONTEXT_SWITCH
|
||||||
dbg() << "Scheduler: " << *current_thread << " -> " << thread << " [" << thread.priority() << "] " << String::format("%w", thread.tss().cs) << ":" << String::format("%x", thread.tss().eip);
|
dbg() << "Scheduler[" << Processor::current().id() << "]: " << *current_thread << " -> " << thread << " [" << thread.priority() << "] " << String::format("%w", thread.tss().cs) << ":" << String::format("%x", thread.tss().eip);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -536,7 +541,7 @@ void Scheduler::initialize(u32 cpu)
|
||||||
g_finalizer_wait_queue = new WaitQueue;
|
g_finalizer_wait_queue = new WaitQueue;
|
||||||
|
|
||||||
g_finalizer_has_work.store(false, AK::MemoryOrder::memory_order_release);
|
g_finalizer_has_work.store(false, AK::MemoryOrder::memory_order_release);
|
||||||
s_colonel_process = Process::create_kernel_process(idle_thread, "colonel", idle_loop);
|
s_colonel_process = Process::create_kernel_process(idle_thread, "colonel", idle_loop, 1 << cpu);
|
||||||
ASSERT(s_colonel_process);
|
ASSERT(s_colonel_process);
|
||||||
ASSERT(idle_thread);
|
ASSERT(idle_thread);
|
||||||
idle_thread->set_priority(THREAD_PRIORITY_MIN);
|
idle_thread->set_priority(THREAD_PRIORITY_MIN);
|
||||||
|
@ -544,17 +549,23 @@ void Scheduler::initialize(u32 cpu)
|
||||||
} else {
|
} else {
|
||||||
// We need to make sure the BSP initialized the global data first
|
// We need to make sure the BSP initialized the global data first
|
||||||
if (s_bsp_is_initialized.load(AK::MemoryOrder::memory_order_consume) == 0) {
|
if (s_bsp_is_initialized.load(AK::MemoryOrder::memory_order_consume) == 0) {
|
||||||
dbg() << "Scheduler CPU #" << cpu << " waiting for BSP to initialize first";
|
#ifdef SCHEDULER_DEBUG
|
||||||
|
dbg() << "Scheduler[" << cpu << "]: waiting for BSP to initialize...";
|
||||||
|
#endif
|
||||||
while (s_bsp_is_initialized.load(AK::MemoryOrder::memory_order_consume) == 0) {
|
while (s_bsp_is_initialized.load(AK::MemoryOrder::memory_order_consume) == 0) {
|
||||||
}
|
}
|
||||||
|
#ifdef SCHEDULER_DEBUG
|
||||||
|
dbg() << "Scheduler[" << cpu << "]: initializing now";
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
ASSERT(s_colonel_process);
|
ASSERT(s_colonel_process);
|
||||||
idle_thread = s_colonel_process->create_kernel_thread(idle_loop, THREAD_PRIORITY_MIN, String::format("idle thread #%u", cpu), false);
|
idle_thread = s_colonel_process->create_kernel_thread(idle_loop, THREAD_PRIORITY_MIN, String::format("idle thread #%u", cpu), 1 << cpu, false);
|
||||||
ASSERT(idle_thread);
|
ASSERT(idle_thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
Processor::current().set_idle_thread(*idle_thread);
|
Processor::current().set_idle_thread(*idle_thread);
|
||||||
|
Processor::current().set_current_thread(*idle_thread);
|
||||||
|
|
||||||
if (cpu == 0)
|
if (cpu == 0)
|
||||||
s_bsp_is_initialized.store(1, AK::MemoryOrder::memory_order_release);
|
s_bsp_is_initialized.store(1, AK::MemoryOrder::memory_order_release);
|
||||||
|
@ -604,7 +615,7 @@ void Scheduler::invoke_async()
|
||||||
|
|
||||||
void Scheduler::idle_loop()
|
void Scheduler::idle_loop()
|
||||||
{
|
{
|
||||||
dbg() << "Scheduler: idle loop on CPU #" << Processor::current().id();
|
dbg() << "Scheduler[" << Processor::current().id() << "]: idle loop running";
|
||||||
ASSERT(are_interrupts_enabled());
|
ASSERT(are_interrupts_enabled());
|
||||||
for (;;) {
|
for (;;) {
|
||||||
asm("hlt");
|
asm("hlt");
|
||||||
|
|
|
@ -172,14 +172,8 @@ extern "C" [[noreturn]] void init_ap(u32 cpu, Processor* processor_info)
|
||||||
|
|
||||||
APIC::the().enable(cpu);
|
APIC::the().enable(cpu);
|
||||||
|
|
||||||
#if 0
|
Scheduler::initialize(cpu);
|
||||||
Scheduler::idle_loop();
|
Scheduler::start();
|
||||||
#else
|
|
||||||
// FIXME: remove once schedule can handle APs
|
|
||||||
cli();
|
|
||||||
for (;;)
|
|
||||||
asm volatile("hlt");
|
|
||||||
#endif
|
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue