[PATCH] add cpu_relax() in spin loops & clean up barrier() for 2.6.9

From: Fenghua Yu
Date: Tue Nov 09 2004 - 22:59:42 EST


The patch adds cpu_relax() in the body of some spin loops
for 2.6.9. The patch also removes redundant
barrier() code after cpu_relax() on ia32.

In the PAUSE instruction section, IA32 SDM claims "it is
recommended that a PASUE instruction be placed in all
spin-wait loops". And x86_64 SDM says that PAUSE instruction
is same as legacy mode in IA-32e mode operation.

This patch is against 2.6.9 (kernel.org). It was tested on
ia32 and x86_64.

Thanks.

-Fenghua
--- a/arch/x86_64/kernel/smp.c 2004-10-26 11:52:46.000000000 -0700
+++ b/arch/x86_64/kernel/smp.c 2004-10-28 14:37:56.000000000 -0700
@@ -405,11 +405,11 @@ static void __smp_call_function (void (*

/* Wait for response */
while (atomic_read(&data.started) != cpus)
- barrier();
+ cpu_relax();

if (wait)
while (atomic_read(&data.finished) != cpus)
- barrier();
+ cpu_relax();
}

/*
--- a/arch/i386/kernel/smp.c 2004-10-26 11:52:42.000000000 -0700
+++ b/arch/i386/kernel/smp.c 2004-10-28 14:29:22.000000000 -0700
@@ -538,11 +538,11 @@ int smp_call_function (void (*func) (voi

/* Wait for response */
while (atomic_read(&data.started) != cpus)
- barrier();
+ cpu_relax();

if (wait)
while (atomic_read(&data.finished) != cpus)
- barrier();
+ cpu_relax();
spin_unlock(&call_lock);

return 0;
--- a/include/asm-i386/apic.h 2004-10-26 11:53:32.000000000 -0700
+++ b/include/asm-i386/apic.h 2004-10-28 14:31:58.000000000 -0700
@@ -53,7 +53,8 @@ static __inline unsigned long apic_read(

static __inline__ void apic_wait_icr_idle(void)
{
- do { } while ( apic_read( APIC_ICR ) & APIC_ICR_BUSY );
+ while ( apic_read( APIC_ICR ) & APIC_ICR_BUSY )
+ cpu_relax();
}

int get_physical_broadcast(void);
--- a/arch/i386/kernel/cpu/mtrr/main.c 2004-10-26 11:52:42.000000000 -0700
+++ b/arch/i386/kernel/cpu/mtrr/main.c 2004-10-28 14:27:49.000000000 -0700
@@ -147,10 +147,8 @@ static void ipi_handler(void *info)
local_irq_save(flags);

atomic_dec(&data->count);
- while(!atomic_read(&data->gate)) {
+ while(!atomic_read(&data->gate))
cpu_relax();
- barrier();
- }

/* The master has cleared me to execute */
if (data->smp_reg != ~0U)
@@ -160,10 +158,9 @@ static void ipi_handler(void *info)
mtrr_if->set_all();

atomic_dec(&data->count);
- while(atomic_read(&data->gate)) {
+ while(atomic_read(&data->gate))
cpu_relax();
- barrier();
- }
+
atomic_dec(&data->count);
local_irq_restore(flags);
}
@@ -228,10 +225,9 @@ static void set_mtrr(unsigned int reg, u

local_irq_save(flags);

- while(atomic_read(&data.count)) {
+ while(atomic_read(&data.count))
cpu_relax();
- barrier();
- }
+
/* ok, reset count and toggle gate */
atomic_set(&data.count, num_booting_cpus() - 1);
atomic_set(&data.gate,1);
@@ -248,10 +244,9 @@ static void set_mtrr(unsigned int reg, u
mtrr_if->set(reg,base,size,type);

/* wait for the others */
- while(atomic_read(&data.count)) {
+ while(atomic_read(&data.count))
cpu_relax();
- barrier();
- }
+
atomic_set(&data.count, num_booting_cpus() - 1);
atomic_set(&data.gate,0);

@@ -259,10 +254,9 @@ static void set_mtrr(unsigned int reg, u
* Wait here for everyone to have seen the gate change
* So we're the last ones to touch 'data'
*/
- while(atomic_read(&data.count)) {
+ while(atomic_read(&data.count))
cpu_relax();
- barrier();
- }
+
local_irq_restore(flags);
}