From b938008fe1d84dd8595dcfff4b7cedb0f3088bb7 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Tue, 18 Dec 2007 19:46:26 +0000 Subject: [PATCH] * Update the PAUSE macro from "rep; nop;" to "pause;" which is the same bytecode wise but more readable * Insert the pause op in all spin wait loops (as macro for platform independent sources or as inline assembly on x86 only files) * Fix some warnings with tracing on and extended some output * Minor cleanups here and there The pause instruction is implemented since P4 systems but is fully backwards compatible (it's a no-op prior to P4). According to Intel specs it reduces performance penalties as memory order violations can be avoided. Also power consumption is reduced. Most of all this will be beneficial to hyper-threading systems as it frees resources to the other logical processor when one logical processor executes a fast spinning loop. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@23141 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/system/boot/platform/bios_ia32/smp.cpp | 8 +++--- src/system/kernel/arch/x86/arch_cpu.c | 8 +++--- .../kernel/arch/x86/arch_debug_console.c | 4 +-- src/system/kernel/arch/x86/arch_smp.c | 3 ++- src/system/kernel/smp.c | 25 +++++++++---------- src/system/kernel/timer.c | 9 +++++-- 6 files changed, 31 insertions(+), 26 deletions(-) diff --git a/src/system/boot/platform/bios_ia32/smp.cpp b/src/system/boot/platform/bios_ia32/smp.cpp index 48c16bbbaf..677b576aab 100644 --- a/src/system/boot/platform/bios_ia32/smp.cpp +++ b/src/system/boot/platform/bios_ia32/smp.cpp @@ -442,7 +442,7 @@ calculate_apic_timer_conversion_factor(void) t1 = system_time(); apic_write(APIC_INITIAL_TIMER_COUNT, 0xffffffff); // start the counter - execute_n_instructions(128*20000); + execute_n_instructions(128 * 20000); count = apic_read(APIC_CURRENT_TIMER_COUNT); t2 = system_time(); @@ -544,7 +544,7 @@ smp_boot_other_cpus(void) dprintf("wait for delivery\n"); // wait for pending to end while ((apic_read(APIC_INTR_COMMAND_1) & APIC_DELIVERY_STATUS) != 0) - ; + asm volatile ("pause;"); dprintf("deassert INIT\n"); /* deassert INIT */ @@ -558,7 +558,7 @@ dprintf("deassert INIT\n"); dprintf("wait for delivery\n"); // wait for pending to end while ((apic_read(APIC_INTR_COMMAND_1) & APIC_DELIVERY_STATUS) != 0) - ; + asm volatile ("pause;"); /* wait 10ms */ spin(10000); @@ -586,7 +586,7 @@ dprintf("send STARTUP\n"); dprintf("wait for delivery\n"); while ((apic_read(APIC_INTR_COMMAND_1) & APIC_DELIVERY_STATUS) != 0) - ; + asm volatile ("pause;"); } } diff --git a/src/system/kernel/arch/x86/arch_cpu.c b/src/system/kernel/arch/x86/arch_cpu.c index b36f119708..017da71603 100644 --- a/src/system/kernel/arch/x86/arch_cpu.c +++ b/src/system/kernel/arch/x86/arch_cpu.c @@ -106,7 +106,7 @@ set_mtrr(void *_parameter, int cpu) // wait until all CPUs have arrived here atomic_add(&sWaitAllCPUs, 1); while (sWaitAllCPUs != smp_get_num_cpus()) - ; + asm volatile ("pause;"); disable_caches(); @@ -118,7 +118,7 @@ set_mtrr(void *_parameter, int cpu) // wait until all CPUs have arrived here atomic_add(&sWaitAllCPUs, -1); while (sWaitAllCPUs != 0) - ; + asm volatile ("pause;"); } @@ -128,7 +128,7 @@ init_mtrrs(void *_unused, int cpu) // wait until all CPUs have arrived here atomic_add(&sWaitAllCPUs, 1); while (sWaitAllCPUs != smp_get_num_cpus()) - ; + asm volatile ("pause;"); disable_caches(); @@ -139,7 +139,7 @@ init_mtrrs(void *_unused, int cpu) // wait until all CPUs have arrived here atomic_add(&sWaitAllCPUs, -1); while (sWaitAllCPUs != 0) - ; + asm volatile ("pause;"); } diff --git a/src/system/kernel/arch/x86/arch_debug_console.c b/src/system/kernel/arch/x86/arch_debug_console.c index eee557549c..fd62379a08 100644 --- a/src/system/kernel/arch/x86/arch_debug_console.c +++ b/src/system/kernel/arch/x86/arch_debug_console.c @@ -111,7 +111,7 @@ put_char(const char c) // wait until the transmitter empty bit is set while ((in8(sSerialBasePort + SERIAL_LINE_STATUS) & 0x20) == 0) - ; + asm volatile ("pause;"); out8(c, sSerialBasePort + SERIAL_TRANSMIT_BUFFER); } @@ -275,7 +275,7 @@ arch_debug_serial_getchar(void) #endif while ((in8(sSerialBasePort + SERIAL_LINE_STATUS) & 0x1) == 0) - ; + asm volatile ("pause;"); return in8(sSerialBasePort + SERIAL_RECEIVE_BUFFER); } diff --git a/src/system/kernel/arch/x86/arch_smp.c b/src/system/kernel/arch/x86/arch_smp.c index 1bf8d56eaa..c871aa7020 100644 --- a/src/system/kernel/arch/x86/arch_smp.c +++ b/src/system/kernel/arch/x86/arch_smp.c @@ -254,7 +254,8 @@ arch_smp_send_ici(int32 target_cpu) timeout = 100000000; // wait for message to be sent while ((apic_read(APIC_INTR_COMMAND_1) & APIC_DELIVERY_STATUS) != 0 && --timeout != 0) - ; + asm volatile ("pause;"); + if (timeout == 0) panic("arch_smp_send_ici: timeout, target_cpu %ld", target_cpu); diff --git a/src/system/kernel/smp.c b/src/system/kernel/smp.c index 604675b685..f9f1c218a9 100644 --- a/src/system/kernel/smp.c +++ b/src/system/kernel/smp.c @@ -30,9 +30,9 @@ #endif #if __INTEL__ - #define PAUSE() asm volatile ("rep; nop;") +# define PAUSE() asm volatile ("pause;") #else - #define PAUSE() +# define PAUSE() #endif #define MSG_POOL_SIZE (SMP_MAX_CPUS * 4) @@ -248,7 +248,7 @@ check_for_message(int currentCPU, int *source_mailbox) if (msg != NULL) { smp_msgs[currentCPU] = msg->next; release_spinlock(&cpu_msg_spinlock[currentCPU]); - TRACE((" found msg %p in cpu mailbox\n", msg)); + TRACE((" cpu %d: found msg %p in cpu mailbox\n", currentCPU, msg)); *source_mailbox = MAILBOX_LOCAL; } else { // try getting one from the broadcast mailbox @@ -270,7 +270,7 @@ check_for_message(int currentCPU, int *source_mailbox) break; } release_spinlock(&broadcast_msg_spinlock); - TRACE((" found msg %p in broadcast mailbox\n", msg)); + TRACE((" cpu %d: found msg %p in broadcast mailbox\n", currentCPU, msg)); } return msg; } @@ -355,7 +355,7 @@ process_pending_ici(int32 currentCPU) if (msg == NULL) return retval; - TRACE((" cpu %d message = %d\n", currentCPU, msg->message)); + TRACE((" cpu %ld message = %ld\n", currentCPU, msg->message)); switch (msg->message) { case SMP_MSG_INVALIDATE_PAGE_RANGE: @@ -396,7 +396,7 @@ process_pending_ici(int32 currentCPU) cpu_status state = disable_interrupts(); while (*haltValue != 0) - ; + PAUSE(); restore_interrupts(state); } @@ -430,7 +430,7 @@ smp_send_ici(int32 targetCPU, int32 message, uint32 data, uint32 data2, uint32 d { struct smp_msg *msg; - TRACE(("smp_send_ici: target 0x%x, mess 0x%x, data 0x%lx, data2 0x%lx, data3 0x%lx, ptr %p, flags 0x%x\n", + TRACE(("smp_send_ici: target 0x%lx, mess 0x%lx, data 0x%lx, data2 0x%lx, data3 0x%lx, ptr %p, flags 0x%lx\n", targetCPU, message, data, data2, data3, data_ptr, flags)); if (sICIEnabled) { @@ -489,7 +489,7 @@ smp_send_broadcast_ici(int32 message, uint32 data, uint32 data2, uint32 data3, { struct smp_msg *msg; - TRACE(("smp_send_broadcast_ici: cpu %d mess 0x%x, data 0x%lx, data2 0x%lx, data3 0x%lx, ptr %p, flags 0x%x\n", + TRACE(("smp_send_broadcast_ici: cpu %ld mess 0x%lx, data 0x%lx, data2 0x%lx, data3 0x%lx, ptr %p, flags 0x%lx\n", smp_get_current_cpu(), message, data, data2, data3, data_ptr, flags)); if (sICIEnabled) { @@ -512,7 +512,7 @@ smp_send_broadcast_ici(int32 message, uint32 data, uint32 data2, uint32 data3, msg->done = false; TRACE(("smp_send_broadcast_ici%d: inserting msg %p into broadcast mbox\n", - smp_get_current_cpu(), msg)); + currentCPU, msg)); // stick it in the appropriate cpu's mailbox acquire_spinlock_nocheck(&broadcast_msg_spinlock); @@ -555,7 +555,6 @@ smp_trap_non_boot_cpus(int32 cpu) if (cpu > 0) { boot_cpu_spin[cpu] = 1; acquire_spinlock_nocheck(&boot_cpu_spin[cpu]); - return false; } @@ -582,10 +581,10 @@ smp_wake_up_non_boot_cpus() void smp_cpu_rendezvous(volatile uint32 *var, int current_cpu) { - atomic_or(var, 1<