summaryrefslogtreecommitdiff
path: root/Kernel/Scheduler.cpp
diff options
context:
space:
mode:
authorTom <tomut@yahoo.com>2020-07-06 07:27:22 -0600
committerAndreas Kling <kling@serenityos.org>2020-07-06 17:07:44 +0200
commitbc107d0b3311677de7bc084cbb75c21b166c8ad5 (patch)
tree586d1cfa189d72309f978122e15d112539feef61 /Kernel/Scheduler.cpp
parentdec27e5e6fad25fedd9203087b8107242369dd2b (diff)
downloadserenity-bc107d0b3311677de7bc084cbb75c21b166c8ad5.zip
Kernel: Add SMP IPI support
We can now properly initialize all processors without crashing by sending SMP IPI messages to synchronize memory between processors. We now initialize the APs once we have the scheduler running. This is so that we can process IPI messages from the other cores. Also rework interrupt handling a bit so that it's more of a 1:1 mapping. We need to allocate non-sharable interrupts for IPIs. This also fixes the occasional hang/crash because all CPUs now synchronize memory with each other.
Diffstat (limited to 'Kernel/Scheduler.cpp')
-rw-r--r--Kernel/Scheduler.cpp64
1 files changed, 30 insertions, 34 deletions
diff --git a/Kernel/Scheduler.cpp b/Kernel/Scheduler.cpp
index b97595c570..ec05ad69ee 100644
--- a/Kernel/Scheduler.cpp
+++ b/Kernel/Scheduler.cpp
@@ -566,57 +566,51 @@ void Scheduler::enter_current(Thread& prev_thread)
Process* Scheduler::colonel()
{
+ ASSERT(s_colonel_process);
return s_colonel_process;
}
-void Scheduler::initialize(u32 cpu)
+void Scheduler::initialize()
{
- static Atomic<u32> s_bsp_is_initialized;
-
ASSERT(&Processor::current() != nullptr); // sanity check
Thread* idle_thread = nullptr;
- if (cpu == 0) {
- ASSERT(s_bsp_is_initialized.load(AK::MemoryOrder::memory_order_consume) == 0);
- g_scheduler_data = new SchedulerData;
- g_finalizer_wait_queue = new WaitQueue;
-
- g_finalizer_has_work.store(false, AK::MemoryOrder::memory_order_release);
- s_colonel_process = Process::create_kernel_process(idle_thread, "colonel", idle_loop, 1 << cpu);
- ASSERT(s_colonel_process);
- ASSERT(idle_thread);
- idle_thread->set_priority(THREAD_PRIORITY_MIN);
- idle_thread->set_name(String::format("idle thread #%u", cpu));
- } else {
- // We need to make sure the BSP initialized the global data first
- if (s_bsp_is_initialized.load(AK::MemoryOrder::memory_order_consume) == 0) {
-#ifdef SCHEDULER_DEBUG
- dbg() << "Scheduler[" << cpu << "]: waiting for BSP to initialize...";
-#endif
- while (s_bsp_is_initialized.load(AK::MemoryOrder::memory_order_consume) == 0) {
- }
-#ifdef SCHEDULER_DEBUG
- dbg() << "Scheduler[" << cpu << "]: initializing now";
-#endif
- }
+ g_scheduler_data = new SchedulerData;
+ g_finalizer_wait_queue = new WaitQueue;
- ASSERT(s_colonel_process);
- 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);
- }
+ g_finalizer_has_work.store(false, AK::MemoryOrder::memory_order_release);
+ s_colonel_process = Process::create_kernel_process(idle_thread, "colonel", idle_loop, 1);
+ ASSERT(s_colonel_process);
+ ASSERT(idle_thread);
+ idle_thread->set_priority(THREAD_PRIORITY_MIN);
+ idle_thread->set_name("idle thread #0");
+ set_idle_thread(idle_thread);
+}
+
+void Scheduler::set_idle_thread(Thread* idle_thread)
+{
Processor::current().set_idle_thread(*idle_thread);
Processor::current().set_current_thread(*idle_thread);
+}
- if (cpu == 0)
- s_bsp_is_initialized.store(1, AK::MemoryOrder::memory_order_release);
+Thread* Scheduler::create_ap_idle_thread(u32 cpu)
+{
+ ASSERT(cpu != 0);
+ // This function is called on the bsp, but creates an idle thread for another AP
+ ASSERT(Processor::current().id() == 0);
+
+ ASSERT(s_colonel_process);
+ Thread* 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);
+ return idle_thread;
}
void Scheduler::timer_tick(const RegisterState& regs)
{
ASSERT_INTERRUPTS_DISABLED();
ASSERT(Processor::current().in_irq());
-
+if (Processor::current().id() > 0) return;
auto current_thread = Processor::current().current_thread();
if (!current_thread)
return;
@@ -664,9 +658,11 @@ void Scheduler::idle_loop()
{
dbg() << "Scheduler[" << Processor::current().id() << "]: idle loop running";
ASSERT(are_interrupts_enabled());
+
for (;;) {
asm("hlt");
- yield();
+
+if (Processor::current().id() == 0) yield();
}
}