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
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
+15
-10
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user