Browse Source

Add irq choose strategy

Serj Kalichev 10 years ago
parent
commit
1be921fddb
3 changed files with 79 additions and 24 deletions
  1. 49 21
      balance.c
  2. 8 1
      balance.h
  3. 22 2
      birq.c

+ 49 - 21
balance.c

@@ -13,6 +13,7 @@
 #include "statistics.h"
 #include "statistics.h"
 #include "cpu.h"
 #include "cpu.h"
 #include "irq.h"
 #include "irq.h"
+#include "balance.h"
 
 
 /* Drop the dont_move flag on all IRQs for specified CPU */
 /* Drop the dont_move flag on all IRQs for specified CPU */
 static int dec_weight(cpu_t *cpu, int value)
 static int dec_weight(cpu_t *cpu, int value)
@@ -201,23 +202,35 @@ int apply_affinity(lub_list_t *balance_irqs)
 
 
 
 
 /* Count the number of intr-not-null IRQs and minimal IRQ weight */
 /* Count the number of intr-not-null IRQs and minimal IRQ weight */
-static int irq_list_info(lub_list_t *irqs, int *min_weight, unsigned int *irq_num)
+static int irq_list_info(lub_list_t *irqs, int *min_weight,
+	unsigned int *irq_num, unsigned int *candidates_num)
 {
 {
 	lub_list_node_t *iter;
 	lub_list_node_t *iter;
 
 
 	if (!irqs)
 	if (!irqs)
 		return -1;
 		return -1;
 
 
-	*min_weight = -1;
-	*irq_num = 0;
+	if (min_weight)
+		*min_weight = -1;
+	if (irq_num)
+		*irq_num = 0;
+	if (candidates_num)
+		*candidates_num = 0;
 	for (iter = lub_list_iterator_init(irqs); iter;
 	for (iter = lub_list_iterator_init(irqs); iter;
 		iter = lub_list_iterator_next(iter)) {
 		iter = lub_list_iterator_next(iter)) {
 		irq_t *irq = (irq_t *)lub_list_node__get_data(iter);
 		irq_t *irq = (irq_t *)lub_list_node__get_data(iter);
 		if (irq->intr == 0)
 		if (irq->intr == 0)
 			continue;
 			continue;
-		if ((*min_weight < 0) || (irq->weight < *min_weight))
-			*min_weight = irq->weight;
-		*irq_num += 1;
+		if (min_weight) {
+			if ((*min_weight < 0) || (irq->weight < *min_weight))
+				*min_weight = irq->weight;
+		}
+		if (irq_num)
+			*irq_num += 1;
+		if (irq->weight)
+			continue;
+		if (candidates_num)
+			*candidates_num += 1;
 	}
 	}
 
 
 	return 0;
 	return 0;
@@ -247,7 +260,7 @@ static cpu_t * most_overloaded_cpu(lub_list_t *cpus, float threshold)
 		if (lub_list_len(cpu->irqs) <= 1)
 		if (lub_list_len(cpu->irqs) <= 1)
 			continue;
 			continue;
 
 
-		irq_list_info(cpu->irqs, &min_weight, &irq_num);
+		irq_list_info(cpu->irqs, &min_weight, &irq_num, NULL);
 		/* All IRQs has intr=0 */
 		/* All IRQs has intr=0 */
 		if (irq_num == 0)
 		if (irq_num == 0)
 			continue;
 			continue;
@@ -266,20 +279,29 @@ static cpu_t * most_overloaded_cpu(lub_list_t *cpus, float threshold)
    another CPU. The best IRQ is IRQ with maximum number of interrupts.
    another CPU. The best IRQ is IRQ with maximum number of interrupts.
    The IRQs with small number of interrupts have very low load or very
    The IRQs with small number of interrupts have very low load or very
    high load (in a case of NAPI). */
    high load (in a case of NAPI). */
-int choose_irqs_to_move(lub_list_t *cpus, lub_list_t *balance_irqs, float threshold)
+int choose_irqs_to_move(lub_list_t *cpus, lub_list_t *balance_irqs,
+	float threshold, birq_choose_strategy_e strategy)
 {
 {
 	lub_list_node_t *iter;
 	lub_list_node_t *iter;
 	cpu_t *overloaded_cpu = NULL;
 	cpu_t *overloaded_cpu = NULL;
-	irq_t *max_irq = NULL;
-	irq_t *min_irq = NULL;
 	irq_t *irq_to_move = NULL;
 	irq_t *irq_to_move = NULL;
 	unsigned long long max_intr = 0;
 	unsigned long long max_intr = 0;
 	unsigned long long min_intr = (unsigned long long)(-1);
 	unsigned long long min_intr = (unsigned long long)(-1);
+	unsigned int choose = 0;
+	unsigned int current = 0;
 
 
 	/* Search for overloaded CPUs */
 	/* Search for overloaded CPUs */
 	if (!(overloaded_cpu = most_overloaded_cpu(cpus, threshold)))
 	if (!(overloaded_cpu = most_overloaded_cpu(cpus, threshold)))
 		return 0;
 		return 0;
 
 
+	if (strategy == BIRQ_CHOOSE_RND) {
+		unsigned int candidates = 0;
+		irq_list_info(overloaded_cpu->irqs, NULL, NULL, &candidates);
+		if (candidates == 0)
+			return 0;
+		choose = rand() % candidates;
+	}
+
 	/* Search for the IRQ (owned by overloaded CPU) with
 	/* Search for the IRQ (owned by overloaded CPU) with
 	   maximum/minimum number of interrupts. */
 	   maximum/minimum number of interrupts. */
 	for (iter = lub_list_iterator_init(overloaded_cpu->irqs); iter;
 	for (iter = lub_list_iterator_init(overloaded_cpu->irqs); iter;
@@ -292,20 +314,26 @@ int choose_irqs_to_move(lub_list_t *cpus, lub_list_t *balance_irqs, float thresh
 			continue;
 			continue;
 		if (irq->weight)
 		if (irq->weight)
 			continue;
 			continue;
-		/* Get IRQ with max intr */
-		if (irq->intr > max_intr) {
-			max_intr = irq->intr;
-			max_irq = irq;
-		}
-		/* Get IRQ with min intr */
-		if (irq->intr < min_intr) {
-			min_intr = irq->intr;
-			min_irq = irq;
+		if (strategy == BIRQ_CHOOSE_MAX) {
+			/* Get IRQ with max intr */
+			if (irq->intr > max_intr) {
+				max_intr = irq->intr;
+				irq_to_move = irq;
+			}
+		} else if (strategy == BIRQ_CHOOSE_MIN) {
+			/* Get IRQ with min intr */
+			if (irq->intr < min_intr) {
+				min_intr = irq->intr;
+				irq_to_move = irq;
+			}
+		} else if (strategy == BIRQ_CHOOSE_RND) {
+			if (current == choose)
+				irq_to_move = irq;
+			break;
 		}
 		}
+		current++;
 	}
 	}
 
 
-	irq_to_move = min_irq;
-	irq_to_move = max_irq;
 	if (irq_to_move) {
 	if (irq_to_move) {
 		/* Don't move this IRQ while next iteration. */
 		/* Don't move this IRQ while next iteration. */
 		irq_to_move->weight = 1;
 		irq_to_move->weight = 1;

+ 8 - 1
balance.h

@@ -5,8 +5,15 @@
 #include "irq.h"
 #include "irq.h"
 #include "cpu.h"
 #include "cpu.h"
 
 
+typedef enum {
+	BIRQ_CHOOSE_MAX,
+	BIRQ_CHOOSE_MIN,
+	BIRQ_CHOOSE_RND
+} birq_choose_strategy_e;
+
 int balance(lub_list_t *cpus, lub_list_t *balance_irqs, float threshold);
 int balance(lub_list_t *cpus, lub_list_t *balance_irqs, float threshold);
 int apply_affinity(lub_list_t *balance_irqs);
 int apply_affinity(lub_list_t *balance_irqs);
-int choose_irqs_to_move(lub_list_t *cpus, lub_list_t *balance_irqs, float threshold);
+int choose_irqs_to_move(lub_list_t *cpus, lub_list_t *balance_irqs,
+	float threshold, birq_choose_strategy_e strategy);
 
 
 #endif
 #endif

+ 22 - 2
birq.c

@@ -55,6 +55,7 @@ struct options {
 	int ht;
 	int ht;
 	unsigned int long_interval;
 	unsigned int long_interval;
 	unsigned int short_interval;
 	unsigned int short_interval;
+	birq_choose_strategy_e strategy;
 };
 };
 
 
 /*--------------------------------------------------------- */
 /*--------------------------------------------------------- */
@@ -122,6 +123,9 @@ int main(int argc, char **argv)
 	sigaction(SIGINT, &sig_act, NULL);
 	sigaction(SIGINT, &sig_act, NULL);
 	sigaction(SIGQUIT, &sig_act, NULL);
 	sigaction(SIGQUIT, &sig_act, NULL);
 
 
+	/* Randomize */
+	srand(time(NULL));
+
 	/* Scan CPUs */
 	/* Scan CPUs */
 	cpus = lub_list_new(cpu_list_compare);
 	cpus = lub_list_new(cpu_list_compare);
 	scan_cpus(cpus, opts->ht);
 	scan_cpus(cpus, opts->ht);
@@ -157,7 +161,7 @@ int main(int argc, char **argv)
 		   Don't choose IRQ if we already have new IRQs to balance */
 		   Don't choose IRQ if we already have new IRQs to balance */
 		if (lub_list_len(balance_irqs) == 0) {
 		if (lub_list_len(balance_irqs) == 0) {
 			choose_irqs_to_move(cpus, balance_irqs,
 			choose_irqs_to_move(cpus, balance_irqs,
-				opts->threshold);
+				opts->threshold, opts->strategy);
 		}
 		}
 		/* If nothing to balance */
 		/* If nothing to balance */
 		if (lub_list_len(balance_irqs) != 0) {
 		if (lub_list_len(balance_irqs) != 0) {
@@ -228,6 +232,7 @@ static struct options *opts_init(void)
 	opts->ht = 0;
 	opts->ht = 0;
 	opts->long_interval = BIRQ_LONG_INTERVAL;
 	opts->long_interval = BIRQ_LONG_INTERVAL;
 	opts->short_interval = BIRQ_SHORT_INTERVAL;
 	opts->short_interval = BIRQ_SHORT_INTERVAL;
+	opts->strategy = BIRQ_CHOOSE_MAX;
 
 
 	return opts;
 	return opts;
 }
 }
@@ -245,7 +250,7 @@ static void opts_free(struct options *opts)
 /* Parse command line options */
 /* Parse command line options */
 static int opts_parse(int argc, char *argv[], struct options *opts)
 static int opts_parse(int argc, char *argv[], struct options *opts)
 {
 {
-	static const char *shortopts = "hp:dO:t:vri:I:";
+	static const char *shortopts = "hp:dO:t:vri:I:c:";
 #ifdef HAVE_GETOPT_H
 #ifdef HAVE_GETOPT_H
 	static const struct option longopts[] = {
 	static const struct option longopts[] = {
 		{"help",		0, NULL, 'h'},
 		{"help",		0, NULL, 'h'},
@@ -257,6 +262,7 @@ static int opts_parse(int argc, char *argv[], struct options *opts)
 		{"ht",			0, NULL, 'r'},
 		{"ht",			0, NULL, 'r'},
 		{"short-interval",	1, NULL, 'i'},
 		{"short-interval",	1, NULL, 'i'},
 		{"long-interval",	1, NULL, 'i'},
 		{"long-interval",	1, NULL, 'i'},
+		{"choose",		1, NULL, 'c'},
 		{NULL,			0, NULL, 0}
 		{NULL,			0, NULL, 0}
 	};
 	};
 #endif
 #endif
@@ -325,6 +331,19 @@ static int opts_parse(int argc, char *argv[], struct options *opts)
 				opts->long_interval = val;
 				opts->long_interval = val;
 			}
 			}
 			break;
 			break;
+		case 'c':
+			if (!strcmp(optarg, "max"))
+				opts->strategy = BIRQ_CHOOSE_MAX;
+			else if (!strcmp(optarg, "min"))
+				opts->strategy = BIRQ_CHOOSE_MIN;
+			else if (!strcmp(optarg, "rnd"))
+				opts->strategy = BIRQ_CHOOSE_RND;
+			else {
+				fprintf(stderr, "Error: Illegal strategy value %s.\n", optarg);
+				help(-1, argv[0]);
+				exit(-1);
+			}
+			break;
 		case 'h':
 		case 'h':
 			help(0, argv[0]);
 			help(0, argv[0]);
 			exit(0);
 			exit(0);
@@ -373,5 +392,6 @@ static void help(int status, const char *argv0)
 		printf("\t-t <float>, --threshold=<float>\tThreshold to consider CPU is overloaded, in percents.\n");
 		printf("\t-t <float>, --threshold=<float>\tThreshold to consider CPU is overloaded, in percents.\n");
 		printf("\t-i <sec>, --short-interval=<sec>\tShort iteration interval.\n");
 		printf("\t-i <sec>, --short-interval=<sec>\tShort iteration interval.\n");
 		printf("\t-I <sec>, --long-interval=<sec>\tLong iteration interval.\n");
 		printf("\t-I <sec>, --long-interval=<sec>\tLong iteration interval.\n");
+		printf("\t-c <strategy>, --choose=<strategy>\tStrategy to choose IRQ to move (min/max/rnd).\n");
 	}
 	}
 }
 }