[PATCH] i386 tlb flush optimization
Manfred Spraul
manfreds en colorfullife.com
Mie Ene 26 17:56:09 CST 2000
the i386 tlb flush is still paranoid about lock-ups, but this is
superflous:
e.g. the Alpha port uses a normal smp_call_function() in it's tlb flush
code.
My attached patch removes most of these paranoid checks.
Could you please test it?
I'm preparing a follow-up patch that optimizes flush_tlb_page() for
multi-threaded applications, and that patch will be incompatible with
the current, anti-lock-up flush_tlb_others() code.
The patch is tested on 2.3.40 i386 SMP.
--
Manfred
------------ próxima parte ------------
--- 2.3/arch/i386/kernel/smp.c Fri Jan 21 12:59:23 2000
+++ build-2.3/arch/i386/kernel/smp.c Wed Jan 26 18:52:24 2000
@@ -281,56 +281,52 @@
#endif
}
-/*
- * This is fraught with deadlocks. Probably the situation is not that
- * bad as in the early days of SMP, so we might ease some of the
- * paranoia here.
- */
+#define TLB_PARANOIA 1
+
static void flush_tlb_others(unsigned int cpumask)
{
- int cpu = smp_processor_id();
- int stuck;
- unsigned long flags;
+#ifdef TLB_PARANOIA
+ if(in_interrupt()) {
+ printk("tlb flush from interrupt: %d,%d",
+ local_bh_count[smp_processor_id()],
+ local_irq_count[smp_processor_id()]);
+ }
+ if(cpumask & (1<<smp_processor_id())) {
+ printk("flush_tlb_others: bad cpumask!");
+ cpumask &= ~(1<<smp_processor_id());
+ local_flush_tlb();
+ }
+ {
+ int flags;
+
+ save_flags(flags);
+ if(flags != 1) {
+static int limit=10;
+ if(limit > 0) {
+ limit--;
+ printk("flush_tlb_others: possible lock-up, broken!(%d)",
+ flags);
+ }
+ sti();
+ }
+ }
+#endif
+ cpumask &= cpu_online_map;
/*
* it's important that we do not generate any APIC traffic
* until the AP CPUs have booted up!
*/
- cpumask &= cpu_online_map;
+
if (cpumask) {
atomic_set_mask(cpumask, &smp_invalidate_needed);
-
- /*
- * Processors spinning on some lock with IRQs disabled
- * will see this IRQ late. The smp_invalidate_needed
- * map will ensure they don't do a spurious flush tlb
- * or miss one.
- */
-
- __save_flags(flags);
- __cli();
-
send_IPI_allbutself(INVALIDATE_TLB_VECTOR);
- /*
- * Spin waiting for completion
- */
-
- stuck = 50000000;
while (smp_invalidate_needed) {
- /*
- * Take care of "crossing" invalidates
+ /* FIXME: lockup-detection, print backtrace on
+ * lock-up
*/
- if (test_bit(cpu, &smp_invalidate_needed))
- do_flush_tlb_local();
-
- --stuck;
- if (!stuck) {
- printk("stuck on TLB IPI wait (CPU#%d)\n",cpu);
- break;
- }
}
- __restore_flags(flags);
}
}
--- 2.3/arch/i386/kernel/irq.c Fri Jan 21 12:59:23 2000
+++ build-2.3/arch/i386/kernel/irq.c Wed Jan 26 17:46:35 2000
@@ -192,20 +192,6 @@
atomic_t global_bh_count;
atomic_t global_bh_lock;
-/*
- * "global_cli()" is a special case, in that it can hold the
- * interrupts disabled for a longish time, and also because
- * we may be doing TLB invalidates when holding the global
- * IRQ lock for historical reasons. Thus we may need to check
- * SMP invalidate events specially by hand here (but not in
- * any normal spinlocks)
- */
-static inline void check_smp_invalidate(int cpu)
-{
- if (test_bit(cpu, &smp_invalidate_needed))
- do_flush_tlb_local();
-}
-
static void show(char * str)
{
int i;
@@ -294,7 +280,6 @@
__sti();
SYNC_OTHER_CORES(cpu);
__cli();
- check_smp_invalidate(cpu);
if (atomic_read(&global_irq_count))
continue;
if (global_irq_lock)
@@ -346,7 +331,6 @@
/* Uhhuh.. Somebody else got it. Wait.. */
do {
do {
- check_smp_invalidate(cpu);
} while (test_bit(0,&global_irq_lock));
} while (test_and_set_bit(0,&global_irq_lock));
}
Más información sobre la lista de distribución Ayuda