diff --git a/activate.c b/activate.c index b201e9b..292c44a 100644 --- a/activate.c +++ b/activate.c @@ -36,6 +36,7 @@ static void activate_mapping(struct irq_info *info, void *data __attribute__((un { char buf[PATH_MAX]; FILE *file; + cpumask_t applied_mask; /* * only activate mappings for irqs that have moved @@ -52,7 +53,13 @@ static void activate_mapping(struct irq_info *info, void *data __attribute__((un if (!file) return; - cpumask_scnprintf(buf, PATH_MAX, info->assigned_obj->mask); + if ((hint_policy == HINT_POLICY_EXACT) && + (!cpus_empty(info->affinity_hint))) + applied_mask = info->affinity_hint; + else + applied_mask = info->assigned_obj->mask; + + cpumask_scnprintf(buf, PATH_MAX, applied_mask); fprintf(file, "%s", buf); fclose(file); info->moved = 0; /*migration is done*/ diff --git a/classify.c b/classify.c index 14c17d4..0a4d46c 100644 --- a/classify.c +++ b/classify.c @@ -25,8 +25,6 @@ int map_class_to_level[7] = { BALANCE_PACKAGE, BALANCE_CACHE, BALANCE_CACHE, BALANCE_NONE, BALANCE_CORE, BALANCE_CORE, BALANCE_CORE }; -int class_counts[7]; - #define MAX_CLASS 0x12 /* * Class codes lifted from pci spec, appendix D. diff --git a/irqbalance.1 b/irqbalance.1 index c26c709..8fbc48d 100755 --- a/irqbalance.1 +++ b/irqbalance.1 @@ -41,6 +41,19 @@ Causes irqbalance to be run once, after which the daemon exits .B --debug Causes irqbalance to run in the foreground and extra debug information to be printed +.TP +.B --hintpolicy=[exact | subset | ignore] +Set the policy for how irq kernel affinity hinting is treated. Can be one of: +.P +.I exact +irq affinity hint is applied unilaterally and never violated +.P +.I subset +irq is balanced, but the assigned object will be a subset of the affintiy hint +.P +.I ignore +irq affinity hint value is completely ignored + .SH "ENVIRONMENT VARIABLES" .TP .B IRQBALANCE_ONESHOT diff --git a/irqbalance.c b/irqbalance.c index 6607d38..9f08bce 100644 --- a/irqbalance.c +++ b/irqbalance.c @@ -38,12 +38,10 @@ int one_shot_mode; int debug_mode; int numa_avail; - int need_cpu_rescan; - extern cpumask_t banned_cpus; - static int counter; +enum hp_e hint_policy = HINT_POLICY_SUBSET; void sleep_approx(int seconds) @@ -64,12 +62,13 @@ void sleep_approx(int seconds) struct option lopts[] = { {"oneshot", 0, NULL, 'o'}, {"debug", 0, NULL, 'd'}, + {"hintpolicy", 1, NULL, 'h'}, {0, 0, 0, 0} }; static void usage(void) { - printf("irqbalance [--oneshot | -o] [--debug | -d]"); + printf("irqbalance [--oneshot | -o] [--debug | -d] [--hintpolicy= | -h [exact|subset|ignore]]"); } static void parse_command_line(int argc, char **argv) @@ -78,7 +77,7 @@ static void parse_command_line(int argc, char **argv) int longind; while ((opt = getopt_long(argc, argv, - "", + "odh:", lopts, &longind)) != -1) { switch(opt) { @@ -88,6 +87,18 @@ static void parse_command_line(int argc, char **argv) case 'd': debug_mode=1; break; + case 'h': + if (!strncmp(optarg, "exact", strlen(optarg))) + hint_policy = HINT_POLICY_EXACT; + else if (!strncmp(optarg, "subset", strlen(optarg))) + hint_policy = HINT_POLICY_SUBSET; + else if (!strncmp(optarg, "ignore", strlen(optarg))) + hint_policy = HINT_POLICY_IGNORE; + else { + usage(); + exit(1); + } + break; case 'o': one_shot_mode=1; break; diff --git a/irqbalance.h b/irqbalance.h index 1321219..e4ebf95 100644 --- a/irqbalance.h +++ b/irqbalance.h @@ -16,12 +16,6 @@ extern int package_count; extern int cache_domain_count; extern int core_count; extern char *classes[]; -extern int map_class_to_level[7]; -extern int class_counts[7]; -extern int debug_mode; -extern int power_mode; -extern int need_cpu_rescan; -extern int one_shot_mode; extern void parse_cpu_tree(void); extern void clear_work_stats(void); @@ -46,6 +40,18 @@ void clear_cpu_tree(void); void pci_numa_scan(void); /*===================NEW BALANCER FUNCTIONS============================*/ +enum hp_e { + HINT_POLICY_IGNORE, + HINT_POLICY_SUBSET, + HINT_POLICY_EXACT +}; + +extern int debug_mode; +extern int one_shot_mode; +extern int power_mode; +extern int need_cpu_rescan; +extern enum hp_e hint_policy; + /* * Numa node access routines */ diff --git a/irqlist.c b/irqlist.c index 462f1b8..898b64d 100644 --- a/irqlist.c +++ b/irqlist.c @@ -68,6 +68,13 @@ static void move_candidate_irqs(struct irq_info *info, void *data) { int *remaining_deviation = (int *)data; + /* never move an irq that has an afinity hint when + * hint_policy is HINT_POLICY_EXACT + */ + if (hint_policy == HINT_POLICY_EXACT) + if (!cpus_empty(info->affinity_hint)) + return; + /* Don't rebalance irqs that don't want it */ if (info->level == BALANCE_NONE) return; diff --git a/placement.c b/placement.c index 8f5623a..835226a 100644 --- a/placement.c +++ b/placement.c @@ -43,6 +43,20 @@ static void find_best_object(struct common_obj_data *d, void *data) { struct obj_placement *best = (struct obj_placement *)data; uint64_t newload; + cpumask_t subset; + + /* + * If the hint policy is subset, then we only want + * to consider objects that are within the irqs hint, but + * only if that irq in fact has published a hint + */ + if (hint_policy == HINT_POLICY_SUBSET) { + if (!cpus_empty(best->info->affinity_hint)) { + cpus_and(subset, best->info->affinity_hint, d->mask); + if (cpus_empty(subset)) + return; + } + } newload = d->load; if (newload < best->best_cost) { diff --git a/types.h b/types.h index 3c13759..4fad7bb 100644 --- a/types.h +++ b/types.h @@ -26,7 +26,6 @@ #define IRQ_TYPE_MSI 1 #define IRQ_TYPE_MSIX 2 - struct common_obj_data { uint64_t load; int number;