Messages in this thread Patch in this message | | | Date | Tue, 9 Nov 2004 19:54:00 -0800 | From | Fenghua Yu <> | Subject | [PATCH] add cpu_relax() in spin loops & clean up barrier() for 2.6.9 |
| |
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); } | |