diff --git a/cputree.c b/cputree.c index c1b4950..6bbc2cb 100644 --- a/cputree.c +++ b/cputree.c @@ -176,8 +176,10 @@ static struct topo_obj* add_cache_domain_to_package(struct topo_obj *cache, if (!entry) { package = calloc(1, sizeof(struct topo_obj)); - if (!package) + if (!package) { + need_rebuild = 1; return NULL; + } package->mask = package_mask; package->obj_type = OBJ_TYPE_PACKAGE; package->obj_type_list = &packages; @@ -214,8 +216,10 @@ static struct topo_obj* add_cpu_to_cache_domain(struct topo_obj *cpu, if (!entry) { cache = calloc(1, sizeof(struct topo_obj)); - if (!cache) + if (!cache) { + need_rebuild = 1; return NULL; + } cache->obj_type = OBJ_TYPE_CACHE; cache->mask = cache_mask; cache->number = cache_domain_count; @@ -271,8 +275,10 @@ static void do_one_cpu(char *path) return; cpu = calloc(1, sizeof(struct topo_obj)); - if (!cpu) + if (!cpu) { + need_rebuild = 1; return; + } cpu->obj_type = OBJ_TYPE_CPU; @@ -372,8 +378,8 @@ static void do_one_cpu(char *path) cpus_and(package_mask, package_mask, unbanned_cpus); cache = add_cpu_to_cache_domain(cpu, cache_mask, nodeid); - add_cache_domain_to_package(cache, packageid, package_mask, - nodeid); + if (cache) + add_cache_domain_to_package(cache, packageid, package_mask, nodeid); cpu->obj_type_list = &cpus; cpus = g_list_append(cpus, cpu); diff --git a/irqbalance.c b/irqbalance.c index 3ff5f13..619f51f 100644 --- a/irqbalance.c +++ b/irqbalance.c @@ -52,6 +52,7 @@ int foreground_mode; int numa_avail; int journal_logging = 0; int need_rescan; +int need_rebuild; unsigned int log_mask = TO_ALL; const char *log_indent; unsigned long power_thresh = ULONG_MAX; @@ -260,14 +261,25 @@ gboolean scan(gpointer data __attribute__((unused))) /* cope with cpu hotplug -- detected during /proc/interrupts parsing */ - if (need_rescan) { + if (need_rescan || need_rebuild) { + int try_times = 0; + need_rescan = 0; cycle_count = 0; log(TO_CONSOLE, LOG_INFO, "Rescanning cpu topology \n"); clear_work_stats(); - free_object_tree(); - build_object_tree(); + do { + free_object_tree(); + if (++try_times > 3) { + log(TO_CONSOLE, LOG_WARNING, "Rescanning cpu topology: fail\n"); + goto out; + } + + need_rebuild = 0; + build_object_tree(); + } while (need_rebuild); + for_each_irq(NULL, force_rebalance_irq, NULL); parse_proc_interrupts(); parse_proc_stat(); @@ -284,6 +296,7 @@ gboolean scan(gpointer data __attribute__((unused))) calculate_placement(); activate_mappings(); +out: if (debug_mode) dump_tree(); if (one_shot_mode) diff --git a/irqbalance.h b/irqbalance.h index 62c7151..79f5450 100644 --- a/irqbalance.h +++ b/irqbalance.h @@ -67,6 +67,7 @@ extern int debug_mode; extern int journal_logging; extern int one_shot_mode; extern int need_rescan; +extern int need_rebuild; extern unsigned long long cycle_count; extern unsigned long power_thresh; extern unsigned long deepest_cache; diff --git a/numa.c b/numa.c index e76b6e0..9d55784 100644 --- a/numa.c +++ b/numa.c @@ -58,8 +58,10 @@ static void add_one_node(const char *nodename) struct topo_obj *new; new = calloc(1, sizeof(struct topo_obj)); - if (!new) + if (!new) { + need_rebuild = 1; return; + } cpus_clear(new->mask); sprintf(path, "%s/%s/cpumap", SYSFS_NODE_PATH, nodename);