Commit 8c27e07f authored by Fenghua Yu's avatar Fenghua Yu Committed by Linus Torvalds

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

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.
Acked-by: default avatarAndi Kleen <ak@muc.de>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent fc62f159
...@@ -149,10 +149,8 @@ static void ipi_handler(void *info) ...@@ -149,10 +149,8 @@ static void ipi_handler(void *info)
local_irq_save(flags); local_irq_save(flags);
atomic_dec(&data->count); atomic_dec(&data->count);
while(!atomic_read(&data->gate)) { while(!atomic_read(&data->gate))
cpu_relax(); cpu_relax();
barrier();
}
/* The master has cleared me to execute */ /* The master has cleared me to execute */
if (data->smp_reg != ~0U) if (data->smp_reg != ~0U)
...@@ -162,10 +160,9 @@ static void ipi_handler(void *info) ...@@ -162,10 +160,9 @@ static void ipi_handler(void *info)
mtrr_if->set_all(); mtrr_if->set_all();
atomic_dec(&data->count); atomic_dec(&data->count);
while(atomic_read(&data->gate)) { while(atomic_read(&data->gate))
cpu_relax(); cpu_relax();
barrier();
}
atomic_dec(&data->count); atomic_dec(&data->count);
local_irq_restore(flags); local_irq_restore(flags);
} }
...@@ -230,10 +227,9 @@ static void set_mtrr(unsigned int reg, unsigned long base, ...@@ -230,10 +227,9 @@ static void set_mtrr(unsigned int reg, unsigned long base,
local_irq_save(flags); local_irq_save(flags);
while(atomic_read(&data.count)) { while(atomic_read(&data.count))
cpu_relax(); cpu_relax();
barrier();
}
/* ok, reset count and toggle gate */ /* ok, reset count and toggle gate */
atomic_set(&data.count, num_booting_cpus() - 1); atomic_set(&data.count, num_booting_cpus() - 1);
atomic_set(&data.gate,1); atomic_set(&data.gate,1);
...@@ -250,10 +246,9 @@ static void set_mtrr(unsigned int reg, unsigned long base, ...@@ -250,10 +246,9 @@ static void set_mtrr(unsigned int reg, unsigned long base,
mtrr_if->set(reg,base,size,type); mtrr_if->set(reg,base,size,type);
/* wait for the others */ /* wait for the others */
while(atomic_read(&data.count)) { while(atomic_read(&data.count))
cpu_relax(); cpu_relax();
barrier();
}
atomic_set(&data.count, num_booting_cpus() - 1); atomic_set(&data.count, num_booting_cpus() - 1);
atomic_set(&data.gate,0); atomic_set(&data.gate,0);
...@@ -261,10 +256,9 @@ static void set_mtrr(unsigned int reg, unsigned long base, ...@@ -261,10 +256,9 @@ static void set_mtrr(unsigned int reg, unsigned long base,
* Wait here for everyone to have seen the gate change * Wait here for everyone to have seen the gate change
* So we're the last ones to touch 'data' * So we're the last ones to touch 'data'
*/ */
while(atomic_read(&data.count)) { while(atomic_read(&data.count))
cpu_relax(); cpu_relax();
barrier();
}
local_irq_restore(flags); local_irq_restore(flags);
} }
......
...@@ -538,11 +538,11 @@ int smp_call_function (void (*func) (void *info), void *info, int nonatomic, ...@@ -538,11 +538,11 @@ int smp_call_function (void (*func) (void *info), void *info, int nonatomic,
/* Wait for response */ /* Wait for response */
while (atomic_read(&data.started) != cpus) while (atomic_read(&data.started) != cpus)
barrier(); cpu_relax();
if (wait) if (wait)
while (atomic_read(&data.finished) != cpus) while (atomic_read(&data.finished) != cpus)
barrier(); cpu_relax();
spin_unlock(&call_lock); spin_unlock(&call_lock);
return 0; return 0;
......
...@@ -310,10 +310,10 @@ static void __smp_call_function (void (*func) (void *info), void *info, ...@@ -310,10 +310,10 @@ static void __smp_call_function (void (*func) (void *info), void *info,
/* Wait for response */ /* Wait for response */
while (atomic_read(&data.started) != cpus) while (atomic_read(&data.started) != cpus)
barrier(); cpu_relax();
while (atomic_read(&data.finished) != cpus) while (atomic_read(&data.finished) != cpus)
barrier(); cpu_relax();
} }
/* /*
......
...@@ -53,7 +53,8 @@ static __inline unsigned long apic_read(unsigned long reg) ...@@ -53,7 +53,8 @@ static __inline unsigned long apic_read(unsigned long reg)
static __inline__ void apic_wait_icr_idle(void) 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); int get_physical_broadcast(void);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment