Browse Source

Some functions for balance

Serj Kalichev 10 years ago
parent
commit
3312f2a906
13 changed files with 158 additions and 13 deletions
  1. 4 2
      Makefile.am
  2. 91 0
      balance.c
  3. 11 0
      balance.h
  4. 13 1
      birq.c
  5. 1 0
      cpu.h
  6. 13 0
      cpu_parse.c
  7. 1 1
      irq.h
  8. 4 2
      irq_parse.c
  9. 2 1
      lub/list.h
  10. 12 0
      lub/list/list.c
  11. 1 0
      lub/list/private.h
  12. 3 1
      nl.c
  13. 2 5
      statistics.c

+ 4 - 2
Makefile.am

@@ -20,7 +20,8 @@ noinst_HEADERS = \
 	bitmap.h \
 	non-atomic.h \
 	cpu.h \
-	statistics.h
+	statistics.h \
+	balance.h
 
 birq_SOURCES = \
 	birq.c \
@@ -28,7 +29,8 @@ birq_SOURCES = \
 	irq_parse.c \
 	cpu_parse.c \
 	statistics.c \
-	bitmap.c
+	bitmap.c \
+	balance.c
 
 birq_LDADD = liblub.a
 birq_DEPENDENCIES = liblub.a

+ 91 - 0
balance.c

@@ -0,0 +1,91 @@
+/* balance.c
+ * Balance IRQs.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <limits.h>
+#include <ctype.h>
+
+#include "statistics.h"
+#include "cpu.h"
+#include "irq.h"
+
+static int move_irq_to_cpu(irq_t *irq, cpu_t *cpu)
+{
+	if (!irq || !cpu)
+		return -1;
+
+	if (irq->cpu) {
+		cpu_t *old_cpu = irq->cpu;
+		lub_list_node_t *node;
+		node = lub_list_search(old_cpu->irqs, irq);
+		if (node) {
+			lub_list_del(old_cpu->irqs, node);
+			lub_list_node_free(node);
+		}
+	}
+	lub_list_add(cpu->irqs, irq);
+	irq->cpu = cpu;
+	return 0;
+}
+
+static cpu_t *choose_cpu(lub_list_t *cpus, irq_t *irq)
+{
+	lub_list_node_t *iter;
+	lub_list_t * min_cpus = NULL;
+	float min_load = 100.00;
+	lub_list_node_t *node;
+	cpu_t *cpu = NULL;
+
+	for (iter = lub_list_iterator_init(cpus); iter;
+		iter = lub_list_iterator_next(iter)) {
+		cpu = (cpu_t *)lub_list_node__get_data(iter);
+		if (!cpu_isset(cpu->id, irq->local_cpus))
+			continue;
+		if ((!min_cpus) || (cpu->load < min_load)) {
+			min_load = cpu->load;
+			if (!min_cpus)
+				min_cpus = lub_list_new(cpu_list_compare_len);
+			while ((node = lub_list__get_tail(min_cpus))) {
+				lub_list_del(min_cpus, node);
+				lub_list_node_free(node);
+			}
+			lub_list_add(min_cpus, cpu);
+		}
+		if (cpu->load == min_load)
+			lub_list_add(min_cpus, cpu);
+	}
+	if (!min_cpus)
+		return NULL;
+	node = lub_list__get_head(min_cpus);
+	cpu = (cpu_t *)lub_list_node__get_data(node);
+	while ((node = lub_list__get_tail(min_cpus))) {
+		lub_list_del(min_cpus, node);
+		lub_list_node_free(node);
+	}
+	lub_list_free(min_cpus);
+
+	return cpu;
+}
+
+int balance(lub_list_t *cpus, lub_list_t *balance_irqs)
+{
+	lub_list_node_t *iter;
+
+	for (iter = lub_list_iterator_init(balance_irqs); iter;
+		iter = lub_list_iterator_next(iter)) {
+		irq_t *irq;
+		cpu_t *cpu;
+		irq = (irq_t *)lub_list_node__get_data(iter);
+		cpu = choose_cpu(cpus, irq);
+		if (cpu) {
+			move_irq_to_cpu(irq, cpu);
+			printf("Move IRQ %u to CPU%u\n", irq->irq, cpu->id);
+		}
+	}
+	return 0;
+}

+ 11 - 0
balance.h

@@ -0,0 +1,11 @@
+#ifndef _balance_h
+#define _balance_h
+
+#include "lub/list.h"
+#include "irq.h"
+#include "cpu.h"
+
+int balance(lub_list_t *cpus, lub_list_t *balance_irqs);
+//int move_irq_to_cpu(irq_t *irq, cpu_t *cpu);
+
+#endif

+ 13 - 1
birq.c

@@ -34,6 +34,7 @@
 #include "cpu.h"
 #include "nl.h"
 #include "statistics.h"
+#include "balance.h"
 
 #define BIRQ_PIDFILE "/var/run/birq.pid"
 #define BIRQ_INTERVAL 3 /* in seconds */
@@ -79,6 +80,8 @@ int main(int argc, char **argv)
 
 	/* IRQ list. It contain all found irqs. */
 	lub_list_t *irqs;
+	/* IRQs to balance */
+	lub_list_t *balance_irqs;
 	/* CPU list. It contain all found CPUs. */
 	lub_list_t *cpus;
 
@@ -151,16 +154,18 @@ int main(int argc, char **argv)
 
 	/* Prepare data structures */
 	irqs = lub_list_new(irq_list_compare);
+	balance_irqs = lub_list_new(irq_list_compare);
 
 	/* Main loop */
 	while (!sigterm) {
+		lub_list_node_t *node;
 		int n;
 
 		if (rescan) {
 			if (opts->debug)
 				fprintf(stdout, "Scanning hardware...\n");
 			rescan = 0;
-			irq_list_populate(irqs);
+			irq_list_populate(irqs, balance_irqs);
 			if (opts->debug)
 				irq_list_show(irqs);
 		}
@@ -184,11 +189,18 @@ int main(int argc, char **argv)
 			printf("Some balancing...\n");
 		parse_proc_stat(cpus, irqs);
 		show_statistics(cpus);
+		balance(cpus, balance_irqs);
+		/* TODO: Apply changes here */
+		while ((node = lub_list__get_tail(balance_irqs))) {
+			lub_list_del(balance_irqs, node);
+			lub_list_node_free(node);
+		}
 	}
 
 end:
 	/* Free data structures */
 	irq_list_free(irqs);
+	lub_list_free(balance_irqs);
 	cpu_list_free(cpus);
 
 	retval = 0;

+ 1 - 0
cpu.h

@@ -20,6 +20,7 @@ typedef struct cpu_s cpu_t;
 
 /* CPU IDs compare function */
 int cpu_list_compare(const void *first, const void *second);
+int cpu_list_compare_len(const void *first, const void *second);
 
 /* CPU list functions */
 int cpu_list_populate(lub_list_t *cpus);

+ 13 - 0
cpu_parse.c

@@ -25,6 +25,13 @@ int cpu_list_compare(const void *first, const void *second)
 	return (f->id - s->id);
 }
 
+int cpu_list_compare_len(const void *first, const void *second)
+{
+	const cpu_t *f = (const cpu_t *)first;
+	const cpu_t *s = (const cpu_t *)second;
+	return (lub_list_len(f->irqs) - lub_list_len(s->irqs));
+}
+
 static cpu_t * cpu_new(unsigned int id)
 {
 	cpu_t *new;
@@ -42,6 +49,12 @@ static cpu_t * cpu_new(unsigned int id)
 
 static void cpu_free(cpu_t *cpu)
 {
+	lub_list_node_t *node;
+
+	while ((node = lub_list__get_tail(cpu->irqs))) {
+		lub_list_del(cpu->irqs, node);
+		lub_list_node_free(node);
+	}
 	lub_list_free(cpu->irqs);
 	free(cpu);
 }

+ 1 - 1
irq.h

@@ -24,7 +24,7 @@ typedef struct irq_s irq_t;
 int irq_list_compare(const void *first, const void *second);
 
 /* IRQ list functions */
-int irq_list_populate(lub_list_t *irqs);
+int irq_list_populate(lub_list_t *irqs, lub_list_t *balance_irqs);
 int irq_list_free(lub_list_t *irqs);
 int irq_list_show(lub_list_t *irqs);
 irq_t * irq_list_search(lub_list_t *irqs, unsigned int num);

+ 4 - 2
irq_parse.c

@@ -195,7 +195,7 @@ static int scan_sysfs(lub_list_t *irqs)
 }
 
 /* Parse /proc/interrupts to get actual IRQ list */
-int irq_list_populate(lub_list_t *irqs)
+int irq_list_populate(lub_list_t *irqs, lub_list_t *balance_irqs)
 {
 	FILE *fd;
 	unsigned int num;
@@ -242,8 +242,10 @@ int irq_list_populate(lub_list_t *irqs)
 		/* By default all CPUs are local for IRQ */
 		cpus_setall(irq->local_cpus);
 
-		if (new)
+		if (new) {
+			lub_list_add(balance_irqs, irq);
 			printf("Add IRQ %3d %s\n", irq->irq, STR(irq->desc));
+		}
 	}
 	free(str);
 	fclose(fd);

+ 2 - 1
lub/list.h

@@ -27,7 +27,8 @@ lub_list_node_t *lub_list_iterator_next(lub_list_node_t *node);
 lub_list_node_t *lub_list_iterator_prev(lub_list_node_t *node);
 lub_list_node_t *lub_list_add(lub_list_t *list, void *data);
 void lub_list_del(lub_list_t *list, lub_list_node_t *node);
-lub_list_node_t *lub_list_search(lub_list_t *this, void *data);
+lub_list_node_t *lub_list_search(lub_list_t *list, void *data);
+unsigned int lub_list_len(lub_list_t *list);
 
 _END_C_DECL
 #endif				/* _lub_list_h */

+ 12 - 0
lub/list/list.c

@@ -9,7 +9,9 @@ static inline void lub_list_init(lub_list_t * this,
 	lub_list_compare_fn compareFn)
 {
 	this->head = NULL;
+	this->tail = NULL;
 	this->compareFn = compareFn;
+	this->len = 0;
 }
 
 /*--------------------------------------------------------- */
@@ -110,6 +112,8 @@ lub_list_node_t *lub_list_add(lub_list_t *this, void *data)
 	lub_list_node_t *node = lub_list_node_new(data);
 	lub_list_node_t *iter;
 
+	this->len++;
+
 	/* Empty list */
 	if (!this->head) {
 		this->head = node;
@@ -163,6 +167,8 @@ void lub_list_del(lub_list_t *this, lub_list_node_t *node)
 		node->next->prev = node->prev;
 	else
 		this->tail = node->prev;
+
+	this->len--;
 }
 
 /*--------------------------------------------------------- */
@@ -195,3 +201,9 @@ lub_list_node_t *lub_list_search(lub_list_t *this, void *data)
 }
 
 /*--------------------------------------------------------- */
+inline unsigned int lub_list_len(lub_list_t *this)
+{
+	return this->len;
+}
+
+/*--------------------------------------------------------- */

+ 1 - 0
lub/list/private.h

@@ -10,4 +10,5 @@ struct lub_list_s {
 	lub_list_node_t *head;
 	lub_list_node_t *tail;
 	lub_list_compare_fn *compareFn;
+	int len;
 };

+ 3 - 1
nl.c

@@ -109,8 +109,10 @@ int nl_poll(nl_fds_t *nl_fds, int timeout)
 	/* Service all the sockets with input pending. */
 	for (i = 0; i < NL_FDS_LEN; i++) {
 		char *evtype = NULL;
+		if (nl_fds[i] < 0)
+			continue;
 		if (!FD_ISSET(nl_fds[i], &fd_set))
-				continue;
+			continue;
 		switch (i) {
 		case 0:
 			evtype = "kernel";

+ 2 - 5
statistics.c

@@ -14,8 +14,6 @@
 #include "cpu.h"
 #include "irq.h"
 
-#define STR(str) ( str ? str : "" )
-
 void parse_proc_stat(lub_list_t *cpus, lub_list_t *irqs)
 {
 	FILE *file;
@@ -119,13 +117,13 @@ void show_statistics(lub_list_t *cpus)
 {
 	lub_list_node_t *iter;
 
+	printf("--------------------------------------------------------------------------------\n");
 	for (iter = lub_list_iterator_init(cpus); iter;
 		iter = lub_list_iterator_next(iter)) {
 		cpu_t *cpu;
 		lub_list_node_t *irq_iter;
 
 		cpu = (cpu_t *)lub_list_node__get_data(iter);
-		printf("--------------------------------------------------------------------------------\n");
 		printf("CPU%u package %u, core %u, load %.2f%%\n",
 			cpu->id, cpu->package_id, cpu->core_id, cpu->load);
 
@@ -133,8 +131,7 @@ void show_statistics(lub_list_t *cpus)
 		irq_iter = lub_list_iterator_next(irq_iter)) {
 			irq_t *irq;
 			irq = (irq_t *)lub_list_node__get_data(irq_iter);
-			printf("IRQ %u %llu %s\n", irq->irq, irq->intr, irq->desc);
+			printf("    IRQ %u %llu %s\n", irq->irq, irq->intr, irq->desc);
 		}
 	}
 }
-