* Simplified smp_trap_non_boot_cpus() and smp_wake_up_non_boot_cpus(): We don't
need a spinlock per CPU; a single variable suffices. * Extended call_all_cpus[_sync]() to work before smp_wake_up_non_boot_cpus() (even before smp_init()). git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@37105 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -69,7 +69,11 @@ struct smp_msg {
|
|||||||
#define MAILBOX_LOCAL 1
|
#define MAILBOX_LOCAL 1
|
||||||
#define MAILBOX_BCAST 2
|
#define MAILBOX_BCAST 2
|
||||||
|
|
||||||
static spinlock boot_cpu_spin[SMP_MAX_CPUS] = { };
|
static vint32 sBootCPUSpin = 0;
|
||||||
|
|
||||||
|
static vint32 sEarlyCPUCall = 0;
|
||||||
|
static void (*sEarlyCPUCallFunction)(void*, int);
|
||||||
|
void* sEarlyCPUCallCookie;
|
||||||
|
|
||||||
static struct smp_msg *sFreeMessages = NULL;
|
static struct smp_msg *sFreeMessages = NULL;
|
||||||
static volatile int sFreeMessageCount = 0;
|
static volatile int sFreeMessageCount = 0;
|
||||||
@@ -778,6 +782,35 @@ spinlock_contention_syscall(const char* subsystem, uint32 function,
|
|||||||
#endif // B_DEBUG_SPINLOCK_CONTENTION
|
#endif // B_DEBUG_SPINLOCK_CONTENTION
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
process_early_cpu_call(int32 cpu)
|
||||||
|
{
|
||||||
|
sEarlyCPUCallFunction(sEarlyCPUCallCookie, cpu);
|
||||||
|
atomic_and(&sEarlyCPUCall, ~(uint32)(1 << cpu));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
call_all_cpus_early(void (*function)(void*, int), void* cookie)
|
||||||
|
{
|
||||||
|
if (sNumCPUs > 1) {
|
||||||
|
sEarlyCPUCallFunction = function;
|
||||||
|
sEarlyCPUCallCookie = cookie;
|
||||||
|
|
||||||
|
uint32 cpuMask = (1 << sNumCPUs) - 2;
|
||||||
|
// all CPUs but the boot cpu
|
||||||
|
|
||||||
|
sEarlyCPUCall = cpuMask;
|
||||||
|
|
||||||
|
// wait for all CPUs to finish
|
||||||
|
while ((sEarlyCPUCall & cpuMask) != 0)
|
||||||
|
PAUSE();
|
||||||
|
}
|
||||||
|
|
||||||
|
function(cookie, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark -
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
@@ -1059,9 +1092,15 @@ smp_trap_non_boot_cpus(int32 cpu, uint32* rendezVous)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
acquire_spinlock_nocheck(&boot_cpu_spin[cpu]);
|
|
||||||
smp_cpu_rendezvous(rendezVous, cpu);
|
smp_cpu_rendezvous(rendezVous, cpu);
|
||||||
acquire_spinlock_nocheck(&boot_cpu_spin[cpu]);
|
|
||||||
|
while (sBootCPUSpin == 0) {
|
||||||
|
if ((sEarlyCPUCall & (1 << cpu)) != 0)
|
||||||
|
process_early_cpu_call(cpu);
|
||||||
|
|
||||||
|
PAUSE();
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1069,16 +1108,12 @@ smp_trap_non_boot_cpus(int32 cpu, uint32* rendezVous)
|
|||||||
void
|
void
|
||||||
smp_wake_up_non_boot_cpus()
|
smp_wake_up_non_boot_cpus()
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
|
|
||||||
// ICIs were previously being ignored
|
// ICIs were previously being ignored
|
||||||
if (sNumCPUs > 1)
|
if (sNumCPUs > 1)
|
||||||
sICIEnabled = true;
|
sICIEnabled = true;
|
||||||
|
|
||||||
// resume non boot CPUs
|
// resume non boot CPUs
|
||||||
for (i = 1; i < sNumCPUs; i++) {
|
sBootCPUSpin = 1;
|
||||||
release_spinlock(&boot_cpu_spin[i]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1197,6 +1232,12 @@ smp_get_current_cpu(void)
|
|||||||
void
|
void
|
||||||
call_all_cpus(void (*func)(void *, int), void *cookie)
|
call_all_cpus(void (*func)(void *, int), void *cookie)
|
||||||
{
|
{
|
||||||
|
// if inter-CPU communication is not yet enabled, use the early mechanism
|
||||||
|
if (!sICIEnabled) {
|
||||||
|
call_all_cpus_early(func, cookie);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
cpu_status state = disable_interrupts();
|
cpu_status state = disable_interrupts();
|
||||||
|
|
||||||
if (smp_get_num_cpus() > 1) {
|
if (smp_get_num_cpus() > 1) {
|
||||||
@@ -1213,6 +1254,12 @@ call_all_cpus(void (*func)(void *, int), void *cookie)
|
|||||||
void
|
void
|
||||||
call_all_cpus_sync(void (*func)(void *, int), void *cookie)
|
call_all_cpus_sync(void (*func)(void *, int), void *cookie)
|
||||||
{
|
{
|
||||||
|
// if inter-CPU communication is not yet enabled, use the early mechanism
|
||||||
|
if (!sICIEnabled) {
|
||||||
|
call_all_cpus_early(func, cookie);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
cpu_status state = disable_interrupts();
|
cpu_status state = disable_interrupts();
|
||||||
|
|
||||||
if (smp_get_num_cpus() > 1) {
|
if (smp_get_num_cpus() > 1) {
|
||||||
|
|||||||
Reference in New Issue
Block a user