From 7f987e49d77f20a4a98a4f88f1e007f838ea2975 Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Fri, 30 Apr 2010 19:32:12 +0000 Subject: [PATCH] Added a rendez-vous variable parameter to smp_trap_non_boot_cpus() and make boot CPU wait until all other CPUs are ready to wait. This solves a theoretical problem in main(): The boot CPU could run fully through the early initialization and reset sCpuRendezvous2 before the other CPUs left smp_cpu_rendezvous(). It's very unlikely on real hardware that the non-boot CPUs are so much slower, but it might be a concern in emulation. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@36558 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/private/kernel/smp.h | 2 +- src/system/kernel/main.cpp | 3 ++- src/system/kernel/smp.cpp | 25 +++++++++++++++---------- 3 files changed, 18 insertions(+), 12 deletions(-) diff --git a/headers/private/kernel/smp.h b/headers/private/kernel/smp.h index 6cec754528..8e9c793d69 100644 --- a/headers/private/kernel/smp.h +++ b/headers/private/kernel/smp.h @@ -44,7 +44,7 @@ extern "C" { status_t smp_init(struct kernel_args *args); status_t smp_per_cpu_init(struct kernel_args *args, int32 cpu); status_t smp_init_post_generic_syscalls(void); -bool smp_trap_non_boot_cpus(int32 cpu); +bool smp_trap_non_boot_cpus(int32 cpu, uint32* rendezVous); void smp_wake_up_non_boot_cpus(void); void smp_cpu_rendezvous(volatile uint32 *var, int current_cpu); void smp_send_ici(int32 targetCPU, int32 message, uint32 data, uint32 data2, uint32 data3, diff --git a/src/system/kernel/main.cpp b/src/system/kernel/main.cpp index 2718939471..c7d61e32ca 100644 --- a/src/system/kernel/main.cpp +++ b/src/system/kernel/main.cpp @@ -67,6 +67,7 @@ bool gKernelStartup = true; static kernel_args sKernelArgs; static uint32 sCpuRendezvous; static uint32 sCpuRendezvous2; +static uint32 sCpuRendezvous3; static int32 main2(void *); @@ -100,7 +101,7 @@ _start(kernel_args *bootKernelArgs, int currentCPU) thread_preboot_init_percpu(&sKernelArgs, currentCPU); // if we're not a boot cpu, spin here until someone wakes us up - if (smp_trap_non_boot_cpus(currentCPU)) { + if (smp_trap_non_boot_cpus(currentCPU, &sCpuRendezvous3)) { // init platform arch_platform_init(&sKernelArgs); diff --git a/src/system/kernel/smp.cpp b/src/system/kernel/smp.cpp index 7a7dc3479e..fa2cd6e3e2 100644 --- a/src/system/kernel/smp.cpp +++ b/src/system/kernel/smp.cpp @@ -1044,20 +1044,25 @@ smp_send_broadcast_ici_interrupts_disabled(int32 currentCPU, int32 message, } +/*! Spin on non-boot CPUs until smp_wake_up_non_boot_cpus() has been called. + + \param cpu The index of the calling CPU. + \param rendezVous A rendez-vous variable to make sure that the boot CPU + does not return before all other CPUs have started waiting. + \return \c true on the boot CPU, \c false otherwise. +*/ bool -smp_trap_non_boot_cpus(int32 cpu) +smp_trap_non_boot_cpus(int32 cpu, uint32* rendezVous) { - if (cpu > 0) { -#if B_DEBUG_SPINLOCK_CONTENTION - boot_cpu_spin[cpu].lock = 1; -#else - boot_cpu_spin[cpu] = 1; -#endif - acquire_spinlock_nocheck(&boot_cpu_spin[cpu]); - return false; + if (cpu == 0) { + smp_cpu_rendezvous(rendezVous, cpu); + return true; } - return true; + acquire_spinlock_nocheck(&boot_cpu_spin[cpu]); + smp_cpu_rendezvous(rendezVous, cpu); + acquire_spinlock_nocheck(&boot_cpu_spin[cpu]); + return false; }