Browse Source

Link IRQs to CPUs using current affinity

Serj Kalichev 9 years ago
parent
commit
bccdb19126
6 changed files with 55 additions and 5 deletions
  1. 4 3
      balance.c
  2. 2 0
      balance.h
  3. 2 0
      birq.c
  4. 1 1
      irq.c
  5. 45 1
      statistics.c
  6. 1 0
      statistics.h

+ 4 - 3
balance.c

@@ -37,7 +37,7 @@ static int dec_weight(cpu_t *cpu, int value)
 }
 
 /* Remove IRQ from specified CPU */
-static int remove_irq_from_cpu(irq_t *irq, cpu_t *cpu)
+int remove_irq_from_cpu(irq_t *irq, cpu_t *cpu)
 {
 	lub_list_node_t *node;
 
@@ -55,8 +55,9 @@ static int remove_irq_from_cpu(irq_t *irq, cpu_t *cpu)
 }
 
 /* Move IRQ to specified CPU. Remove IRQ from the IRQ list
-   of old CPU. */
-static int move_irq_to_cpu(irq_t *irq, cpu_t *cpu)
+ * of old CPU.
+ */
+int move_irq_to_cpu(irq_t *irq, cpu_t *cpu)
 {
 	if (!irq || !cpu)
 		return -1;

+ 2 - 0
balance.h

@@ -11,6 +11,8 @@ typedef enum {
 	BIRQ_CHOOSE_RND
 } birq_choose_strategy_e;
 
+int remove_irq_from_cpu(irq_t *irq, cpu_t *cpu);
+int move_irq_to_cpu(irq_t *irq, cpu_t *cpu);
 int balance(lub_list_t *cpus, lub_list_t *balance_irqs, float threshold);
 int apply_affinity(lub_list_t *balance_irqs);
 int choose_irqs_to_move(lub_list_t *cpus, lub_list_t *balance_irqs,

+ 2 - 0
birq.c

@@ -175,6 +175,8 @@ int main(int argc, char **argv)
 		scan_irqs(irqs, balance_irqs, pxms);
 		if (opts->verbose)
 			irq_list_show(irqs);
+		/* Link IRQs to CPUs due to real current smp affinity. */
+		link_irqs_to_cpus(cpus, irqs);
 
 		/* Gather statistics on CPU load and number of interrupts. */
 		gather_statistics(cpus, irqs);

+ 1 - 1
irq.c

@@ -276,7 +276,7 @@ int scan_irqs(lub_list_t *irqs, lub_list_t *balance_irqs, lub_list_t *pxms)
 		/* Doesn't refresh info for blacklisted IRQs */
 		if (irq->blacklisted)
 			continue;
-
+	
 		/* Find IRQ type - first non-digital and non-space */
 		while (*endptr && !isalpha(*endptr))
 			endptr++;

+ 45 - 1
statistics.c

@@ -13,9 +13,53 @@
 #include "statistics.h"
 #include "cpu.h"
 #include "irq.h"
+#include "balance.h"
+
+/* The setting of smp affinity is not reliable due to problems with some
+ * APIC hw/driver. So we need to relink IRQs to CPUs on each iteration.
+ * The linkage is based on current smp affinity value.
+ */
+void link_irqs_to_cpus(lub_list_t *cpus, lub_list_t *irqs)
+{
+	lub_list_node_t *iter;
+
+	/* Clear all CPU's irq lists. These lists are probably out of date. */
+	for (iter = lub_list_iterator_init(cpus); iter;
+		iter = lub_list_iterator_next(iter)) {
+		cpu_t *cpu = (cpu_t *)lub_list_node__get_data(iter);
+		lub_list_node_t *node;
+		while ((node = lub_list__get_tail(cpu->irqs))) {
+			lub_list_del(cpu->irqs, node);
+			lub_list_node_free(node);
+		}
+	}
+
+	/* Iterate through IRQ list */
+	for (iter = lub_list_iterator_init(irqs); iter;
+		iter = lub_list_iterator_next(iter)) {
+		irq_t *irq = (irq_t *)lub_list_node__get_data(iter);
+		int cpu_num;
+		cpu_t *cpu;
+
+		/* Ignore blacklisted IRQs */
+		if (irq->blacklisted)
+			continue;
+		/* Ignore IRQs with multi-affinity. */
+		if (cpus_weight(irq->affinity) > 1)
+			continue;
+
+		cpu_num = first_cpu(irq->affinity);
+		if (NR_CPUS == cpu_num) /* Something went wrong. No bits set. */
+			continue;
+		if (!(cpu = cpu_list_search(cpus, cpu_num)))
+			continue;
+		move_irq_to_cpu(irq, cpu);
+	}
+}
 
 /* Gather load statistics for CPUs and number of interrupts
-   for current iteration. */
+ * for current iteration.
+ */
 void gather_statistics(lub_list_t *cpus, lub_list_t *irqs)
 {
 	FILE *file;

+ 1 - 0
statistics.h

@@ -3,6 +3,7 @@
 
 #include "lub/list.h"
 
+void link_irqs_to_cpus(lub_list_t *cpus, lub_list_t *irqs);
 void gather_statistics(lub_list_t *cpus, lub_list_t *irqs);
 void show_statistics(lub_list_t *cpus, int verbose);