Hi Andrew
This addreses one of the concerns Andi had about checks for empty cpumask
in the intr speed patch. This patch adds a flag check, so we just check it
rather than the entire cpumask for work to do in move_irq time.
This depends on the other deferred irq write patches we have in -mm so far.
--
Cheers,
Ashok Raj
- Open Source Technology Center
---
Signed-off-by: Ashok Raj <[email protected]>
Depends-on: Following file
x86-x86_64-deferred-handling-of-writes-to-proc-irq-xx-smp_affinitypatch-added-to-mm-tree-fix-4.patch
This patch speeds up checks in move_irq which is called in intr_path.
Earlier checks for the same under CONFIG_IRQBALANCE would check if
the cpumask is empty, which is a slower operation when NR_CPUS is large.
This patch adds a check to speed up processing in the irq_desc structure.
Also adds a new function to generalize setting the pending_irq array
so it can be used in other places.
---
---
linux-2.6.12-rc3-mm2-araj/arch/i386/kernel/io_apic.c | 16 ++---------
linux-2.6.12-rc3-mm2-araj/include/linux/irq.h | 27 +++++++++++++++----
linux-2.6.12-rc3-mm2-araj/kernel/irq/proc.c | 7 ----
3 files changed, 27 insertions(+), 23 deletions(-)
diff -puN arch/i386/kernel/io_apic.c~optimize-move-irq arch/i386/kernel/io_apic.c
--- linux-2.6.12-rc3-mm2/arch/i386/kernel/io_apic.c~optimize-move-irq 2005-05-03 11:03:46.000000000 -0700
+++ linux-2.6.12-rc3-mm2-araj/arch/i386/kernel/io_apic.c 2005-05-03 11:03:46.000000000 -0700
@@ -334,12 +334,7 @@ static inline void balance_irq(int cpu,
cpus_and(allowed_mask, cpu_online_map, irq_affinity[irq]);
new_cpu = move(cpu, allowed_mask, now, 1);
if (cpu != new_cpu) {
- irq_desc_t *desc = irq_desc + irq;
- unsigned long flags;
-
- spin_lock_irqsave(&desc->lock, flags);
- pending_irq_cpumask[irq] = cpumask_of_cpu(new_cpu);
- spin_unlock_irqrestore(&desc->lock, flags);
+ set_pending_irq(irq, cpumask_of_cpu(new_cpu));
}
}
@@ -534,16 +529,12 @@ tryanotherirq:
cpus_and(tmp, target_cpu_mask, allowed_mask);
if (!cpus_empty(tmp)) {
- irq_desc_t *desc = irq_desc + selected_irq;
- unsigned long flags;
Dprintk("irq = %d moved to cpu = %d\n",
selected_irq, min_loaded);
/* mark for change destination */
- spin_lock_irqsave(&desc->lock, flags);
- pending_irq_cpumask[selected_irq] =
- cpumask_of_cpu(min_loaded);
- spin_unlock_irqrestore(&desc->lock, flags);
+ set_pending_irq(selected_irq, cpumask_of_cpu(min_loaded));
+
/* Since we made a change, come back sooner to
* check for more variation.
*/
@@ -575,6 +566,7 @@ static int balanced_irq(void *unused)
/* push everything to CPU 0 to give us a starting point. */
for (i = 0 ; i < NR_IRQS ; i++) {
pending_irq_cpumask[i] = cpumask_of_cpu(0);
+ set_pending_irq(i, cpumask_of_cpu(0));
}
for ( ; ; ) {
diff -puN include/linux/irq.h~optimize-move-irq include/linux/irq.h
--- linux-2.6.12-rc3-mm2/include/linux/irq.h~optimize-move-irq 2005-05-03 11:03:46.000000000 -0700
+++ linux-2.6.12-rc3-mm2-araj/include/linux/irq.h 2005-05-03 11:08:52.000000000 -0700
@@ -67,6 +67,9 @@ typedef struct irq_desc {
unsigned int irq_count; /* For detecting broken interrupts */
unsigned int irqs_unhandled;
spinlock_t lock;
+#if defined (CONFIG_GENERIC_PENDING_IRQ) || defined (CONFIG_IRQBALANCE)
+ unsigned int move_irq; /* Flag need to re-target intr dest*/
+#endif
} ____cacheline_aligned irq_desc_t;
extern irq_desc_t irq_desc [NR_IRQS];
@@ -78,7 +81,6 @@ irq_descp (int irq)
return irq_desc + irq;
}
-
#include <asm/hw_irq.h> /* the arch dependent stuff */
extern int setup_irq(unsigned int irq, struct irqaction * new);
@@ -101,19 +103,33 @@ static inline void set_native_irq_info(i
#if defined (CONFIG_GENERIC_PENDING_IRQ) || defined (CONFIG_IRQBALANCE)
extern cpumask_t pending_irq_cpumask[NR_IRQS];
-#endif
-#ifdef CONFIG_GENERIC_PENDING_IRQ
+static inline void set_pending_irq(unsigned int irq, cpumask_t mask)
+{
+ irq_desc_t *desc = irq_desc + irq;
+ unsigned long flags;
+
+ spin_lock_irqsave(&desc->lock, flags);
+ desc->move_irq = 1;
+ pending_irq_cpumask[irq] = mask;
+ spin_unlock_irqrestore(&desc->lock, flags);
+}
+
static inline void
move_native_irq(int irq)
{
cpumask_t tmp;
irq_desc_t *desc = irq_descp(irq);
+ if (likely (!desc->move_irq))
+ return;
+
+ desc->move_irq = 0;
+
if (likely(cpus_empty(pending_irq_cpumask[irq])))
return;
- if (unlikely(!desc->handler->set_affinity))
+ if (!desc->handler->set_affinity)
return;
/* note - we hold the desc->lock */
@@ -165,10 +181,11 @@ static inline void set_irq_info(int irq,
}
#endif // CONFIG_PCI_MSI
-#else // CONFIG_GENERIC_PENDING_IRQ
+#else // CONFIG_GENERIC_PENDING_IRQ || CONFIG_IRQBALANCE
#define move_irq(x)
#define move_native_irq(x)
+#define set_pending_irq(x,y)
static inline void set_irq_info(int irq, cpumask_t mask)
{
set_native_irq_info(irq, mask);
diff -puN kernel/irq/proc.c~optimize-move-irq kernel/irq/proc.c
--- linux-2.6.12-rc3-mm2/kernel/irq/proc.c~optimize-move-irq 2005-05-03 11:03:46.000000000 -0700
+++ linux-2.6.12-rc3-mm2-araj/kernel/irq/proc.c 2005-05-03 11:03:46.000000000 -0700
@@ -22,16 +22,11 @@ static struct proc_dir_entry *smp_affini
#ifdef CONFIG_GENERIC_PENDING_IRQ
void proc_set_irq_affinity(unsigned int irq, cpumask_t mask_val)
{
- irq_desc_t *desc = irq_descp(irq);
- unsigned long flags;
-
/*
* Save these away for later use. Re-progam when the
* interrupt is pending
*/
- spin_lock_irqsave(&desc->lock, flags);
- pending_irq_cpumask[irq] = mask_val;
- spin_unlock_irqrestore(&desc->lock, flags);
+ set_pending_irq(irq, mask_val);
}
#else
void proc_set_irq_affinity(unsigned int irq, cpumask_t mask_val)
_
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[Index of Archives]
[Kernel Newbies]
[Netfilter]
[Bugtraq]
[Photo]
[Stuff]
[Gimp]
[Yosemite News]
[MIPS Linux]
[ARM Linux]
[Linux Security]
[Linux RAID]
[Video 4 Linux]
[Linux for the blind]
[Linux Resources]