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:
Ingo Weinhold
2010-04-30 19:32:12 +00:00
parent 7846d91843
commit 7f987e49d7
3 changed files with 18 additions and 12 deletions
+1 -1
View File
@@ -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,
+2 -1
View File
@@ -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
View File
@@ -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;
}