diff --git a/classify.c b/classify.c index 49212d4..6a20480 100644 --- a/classify.c +++ b/classify.c @@ -313,13 +313,10 @@ void migrate_irq(GList **from, GList **to, struct irq_info *info) GList *entry; struct irq_info find, *tmp;; - if (from != NULL) { - find.irq = info->irq; - entry = g_list_find_custom(*from, &find, compare_ints); - tmp = entry->data; - *from = g_list_delete_link(*from, entry); - } else - tmp = info; + find.irq = info->irq; + entry = g_list_find_custom(*from, &find, compare_ints); + tmp = entry->data; + *from = g_list_delete_link(*from, entry); *to = g_list_append(*to, tmp); diff --git a/irqbalance.c b/irqbalance.c index 072a554..c229b9d 100644 --- a/irqbalance.c +++ b/irqbalance.c @@ -143,8 +143,11 @@ static void force_rebalance_irq(struct irq_info *info, void *data __attribute__( if (info->level == BALANCE_NONE) return; - migrate_irq((info->assigned_obj ? &info->assigned_obj->interrupts : NULL), - &rebalance_irq_list, info); + if (info->assigned_obj == NULL) + rebalance_irq_list = g_list_append(rebalance_irq_list, info); + else + migrate_irq(&info->assigned_obj->interrupts, &rebalance_irq_list, info); + info->assigned_obj = NULL; } diff --git a/placement.c b/placement.c index 6071601..0e0a998 100644 --- a/placement.c +++ b/placement.c @@ -181,16 +181,13 @@ static void validate_object_tree_placement() void calculate_placement(void) { - /* first clear old data */ - clear_work_stats(); - sort_irq_list(&rebalance_irq_list); - - for_each_irq(rebalance_irq_list, place_irq_in_node, NULL); - for_each_object(numa_nodes, place_irq_in_object, NULL); - for_each_object(packages, place_irq_in_object, NULL); - for_each_object(cache_domains, place_irq_in_object, NULL); - + if (g_list_length(rebalance_irq_list) > 0) { + for_each_irq(rebalance_irq_list, place_irq_in_node, NULL); + for_each_object(numa_nodes, place_irq_in_object, NULL); + for_each_object(packages, place_irq_in_object, NULL); + for_each_object(cache_domains, place_irq_in_object, NULL); + } if (debug_mode) validate_object_tree_placement(); } diff --git a/procinterrupts.c b/procinterrupts.c index 1f24a72..d5555f2 100644 --- a/procinterrupts.c +++ b/procinterrupts.c @@ -128,16 +128,45 @@ static void assign_load_slice(struct irq_info *info, void *data) info->load = (info->irq_count - info->last_irq_count) * *load_slice; } -static void compute_irq_load_share(struct topo_obj *d, void *data __attribute__((unused))) +/* + * Recursive helper to estimate the number of irqs shared between + * multiple topology objects that was handled by this particular object + */ +static uint64_t get_parent_branch_irq_count_share(struct topo_obj *d) +{ + uint64_t total_irq_count = 0; + + if (d->parent) { + total_irq_count = get_parent_branch_irq_count_share(d->parent); + total_irq_count /= g_list_length(*d->obj_type_list); + } + + if (g_list_length(d->interrupts) > 0) + for_each_irq(d->interrupts, accumulate_irq_count, &total_irq_count); + + return total_irq_count; +} + +static void compute_irq_branch_load_share(struct topo_obj *d, void *data __attribute__((unused))) { uint64_t total_irq_counts = 0; + uint64_t local_irq_counts = 0; + uint64_t load_slice; - for_each_irq(d->interrupts, accumulate_irq_count, &total_irq_counts); + total_irq_counts = get_parent_branch_irq_count_share(d); - load_slice = total_irq_counts ? (d->load / total_irq_counts) : 1; + load_slice = local_irq_counts ? (d->load / local_irq_counts) : 1; - for_each_irq(d->interrupts, assign_load_slice, &load_slice); + if (g_list_length(d->interrupts) > 0) { + for_each_irq(d->interrupts, accumulate_irq_count, &local_irq_counts); + for_each_irq(d->interrupts, assign_load_slice, &load_slice); + } + + if (d->parent) { + load_slice = total_irq_counts ? (d->load / total_irq_counts) : 1; + d->parent->load += (total_irq_counts - local_irq_counts) * load_slice; + } } void parse_proc_stat() @@ -189,9 +218,6 @@ void parse_proc_stat() * all the way up the device tree */ cpu->load = irq_load + softirq_load; - cpu_cache_domain(cpu)->load += cpu->load; - cpu_package(cpu)->load += cpu->load; - cpu_numa_node(cpu)->load += cpu->load; } fclose(file); @@ -204,6 +230,9 @@ void parse_proc_stat() * Now that we have load for each cpu attribute a fair share of the load * to each irq on that cpu */ - for_each_object(cpus, compute_irq_load_share, NULL); + for_each_object(cpus, compute_irq_branch_load_share, NULL); + for_each_object(cache_domains, compute_irq_branch_load_share, NULL); + for_each_object(packages, compute_irq_branch_load_share, NULL); + for_each_object(numa_nodes, compute_irq_branch_load_share, NULL); }