diff options
Diffstat (limited to 'testing/irqbalance/irqbalance-2011-08-09.patch')
-rw-r--r-- | testing/irqbalance/irqbalance-2011-08-09.patch | 1584 |
1 files changed, 0 insertions, 1584 deletions
diff --git a/testing/irqbalance/irqbalance-2011-08-09.patch b/testing/irqbalance/irqbalance-2011-08-09.patch deleted file mode 100644 index fcdb8bdbf..000000000 --- a/testing/irqbalance/irqbalance-2011-08-09.patch +++ /dev/null @@ -1,1584 +0,0 @@ -diff --git a/ChangeLog b/ChangeLog -deleted file mode 100644 -index f5e9428..0000000 ---- a/ChangeLog -+++ /dev/null -@@ -1,3 +0,0 @@ --This is all tracked in the SVN repo. This file is just here to keep the --autotools from complaining -- -diff --git a/Makefile.am b/Makefile.am -index 9847232..188e34f 100644 ---- a/Makefile.am -+++ b/Makefile.am -@@ -22,17 +22,17 @@ - - AUTOMAKE_OPTIONS = no-dependencies - ACLOCAL_AMFLAGS = -I m4 --EXTRA_DIST = README INSTALL COPYING autogen.sh m4/cap-ng.m4 misc/irqbalance.service -- -+EXTRA_DIST = INSTALL COPYING autogen.sh misc/irqbalance.service -+ - INCLUDES = -I${top_srcdir} --LIBS = $(CAPNG_LDADD) $(GLIB_LIBS) @LIBS@ --AM_CFLAGS = $(GLIB_CFLAGS) -+AM_CFLAGS = $(LIBCAP_NG_CFLAGS) $(GLIB_CFLAGS) - AM_CPPFLAGS = -W -Wall -Wshadow -Wformat -Wundef -D_GNU_SOURCE - noinst_HEADERS = bitmap.h constants.h cpumask.h irqbalance.h non-atomic.h \ - types.h - sbin_PROGRAMS = irqbalance - irqbalance_SOURCES = activate.c bitmap.c classify.c cputree.c irqbalance.c \ -- irqlist.c numa.c placement.c powermode.c procinterrupts.c -+ irqlist.c numa.c placement.c procinterrupts.c -+irqbalance_LDADD = $(LIBCAP_NG_LIBS) $(GLIB_LIBS) - dist_man_MANS = irqbalance.1 - - CONFIG_CLEAN_FILES = debug*.list config/* -@@ -40,3 +40,6 @@ clean-generic: - rm -rf autom4te*.cache - rm -f *.rej *.orig *~ - -+if LOCAL_GLIB -+SUBDIRS = glib-local -+endif -diff --git a/NEWS b/NEWS -deleted file mode 100644 -index 7cc0277..0000000 ---- a/NEWS -+++ /dev/null -@@ -1 +0,0 @@ --No news currently -diff --git a/README b/README -deleted file mode 100644 -index e69de29..0000000 -diff --git a/activate.c b/activate.c -index 292c44a..02fc8dc 100644 ---- a/activate.c -+++ b/activate.c -@@ -1,5 +1,6 @@ - /* - * Copyright (C) 2006, Intel Corporation -+ * Copyright (C) 2012, Neil Horman <nhorman@tuxdriver.com> - * - * This file is part of irqbalance - * -@@ -31,34 +32,63 @@ - - #include "irqbalance.h" - -+static int check_affinity(struct irq_info *info, cpumask_t applied_mask) -+{ -+ cpumask_t current_mask; -+ char buf[PATH_MAX]; -+ char *line = NULL; -+ size_t size = 0; -+ FILE *file; -+ -+ sprintf(buf, "/proc/irq/%i/smp_affinity", info->irq); -+ file = fopen(buf, "r"); -+ if (!file) -+ return 1; -+ if (getline(&line, &size, file)==0) { -+ free(line); -+ fclose(file); -+ return 1; -+ } -+ cpumask_parse_user(line, strlen(line), current_mask); -+ fclose(file); -+ free(line); -+ -+ return cpus_equal(applied_mask, current_mask); -+} - - static void activate_mapping(struct irq_info *info, void *data __attribute__((unused))) - { - char buf[PATH_MAX]; - FILE *file; - cpumask_t applied_mask; -+ int valid_mask = 0; -+ -+ if ((hint_policy == HINT_POLICY_EXACT) && -+ (!cpus_empty(info->affinity_hint))) { -+ applied_mask = info->affinity_hint; -+ valid_mask = 1; -+ } else if (info->assigned_obj) { -+ applied_mask = info->assigned_obj->mask; -+ valid_mask = 1; -+ if ((hint_policy == HINT_POLICY_SUBSET) && -+ (!cpus_empty(info->affinity_hint))) -+ cpus_and(applied_mask, applied_mask, info->affinity_hint); -+ } - - /* - * only activate mappings for irqs that have moved - */ -- if (!info->moved) -+ if (!info->moved && (!valid_mask || check_affinity(info, applied_mask))) - return; - - if (!info->assigned_obj) - return; - -- - sprintf(buf, "/proc/irq/%i/smp_affinity", info->irq); - file = fopen(buf, "w"); - if (!file) - return; - -- 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); -diff --git a/autogen.sh b/autogen.sh -index 5ad9f14..b792e8b 100755 ---- a/autogen.sh -+++ b/autogen.sh -@@ -1,4 +1,5 @@ - #! /bin/sh - set -x -e -+mkdir -p m4 - # --no-recursive is available only in recent autoconf versions - autoreconf -fv --install -diff --git a/classify.c b/classify.c -index 124dab0..05b3bfb 100644 ---- a/classify.c -+++ b/classify.c -@@ -52,6 +52,8 @@ static short class_codes[MAX_CLASS] = { - }; - - static GList *interrupts_db; -+static GList *new_irq_list; -+static GList *banned_irqs; - - #define SYSDEV_DIR "/sys/bus/pci/devices" - -@@ -63,6 +65,30 @@ static gint compare_ints(gconstpointer a, gconstpointer b) - return ai->irq - bi->irq; - } - -+void add_banned_irq(int irq) -+{ -+ struct irq_info find, *new; -+ GList *entry; -+ -+ find.irq = irq; -+ entry = g_list_find_custom(banned_irqs, &find, compare_ints); -+ if (entry) -+ return; -+ -+ new = calloc(sizeof(struct irq_info), 1); -+ if (!new) { -+ if (debug_mode) -+ printf("No memory to ban irq %d\n", irq); -+ return; -+ } -+ -+ new->irq = irq; -+ -+ banned_irqs = g_list_append(banned_irqs, new); -+ return; -+} -+ -+ - /* - * Inserts an irq_info struct into the intterupts_db list - * devpath points to the device directory in sysfs for the -@@ -90,6 +116,13 @@ static struct irq_info *add_one_irq_to_db(const char *devpath, int irq) - return NULL; - } - -+ entry = g_list_find_custom(banned_irqs, &find, compare_ints); -+ if (entry) { -+ if (debug_mode) -+ printf("SKIPPING BANNED IRQ %d\n", irq); -+ return NULL; -+ } -+ - new = calloc(sizeof(struct irq_info), 1); - if (!new) - return NULL; -@@ -175,6 +208,43 @@ out: - return new; - } - -+static int check_for_irq_ban(char *path, int irq) -+{ -+ char *cmd; -+ int rc; -+ -+ if (!banscript) -+ return 0; -+ -+ cmd = alloca(strlen(path)+strlen(banscript)+32); -+ if (!cmd) -+ return 0; -+ -+ sprintf(cmd, "%s %s %d",banscript, path, irq); -+ rc = system(cmd); -+ -+ /* -+ * The system command itself failed -+ */ -+ if (rc == -1) { -+ if (debug_mode) -+ printf("%s failed, please check the --banscript option\n", cmd); -+ else -+ syslog(LOG_INFO, "%s failed, please check the --banscript option\n", cmd); -+ return 0; -+ } -+ -+ if (WEXITSTATUS(rc)) { -+ if (debug_mode) -+ printf("irq %d is baned by %s\n", irq, banscript); -+ else -+ syslog(LOG_INFO, "irq %d is baned by %s\n", irq, banscript); -+ return 1; -+ } -+ return 0; -+ -+} -+ - /* - * Figures out which interrupt(s) relate to the device we're looking at in dirname - */ -@@ -199,6 +269,10 @@ static void build_one_dev_entry(const char *dirname) - irqnum = strtol(entry->d_name, NULL, 10); - if (irqnum) { - sprintf(path, "%s/%s", SYSDEV_DIR, dirname); -+ if (check_for_irq_ban(path, irqnum)) { -+ add_banned_irq(irqnum); -+ continue; -+ } - new = add_one_irq_to_db(path, irqnum); - if (!new) - continue; -@@ -221,6 +295,11 @@ static void build_one_dev_entry(const char *dirname) - */ - if (irqnum) { - sprintf(path, "%s/%s", SYSDEV_DIR, dirname); -+ if (check_for_irq_ban(path, irqnum)) { -+ add_banned_irq(irqnum); -+ goto done; -+ } -+ - new = add_one_irq_to_db(path, irqnum); - if (!new) - goto done; -@@ -248,6 +327,8 @@ void rebuild_irq_db(void) - { - DIR *devdir = opendir(SYSDEV_DIR); - struct dirent *entry; -+ GList *gentry; -+ struct irq_info *ninfo, *iinfo; - - free_irq_db(); - -@@ -263,22 +344,46 @@ void rebuild_irq_db(void) - build_one_dev_entry(entry->d_name); - - } while (entry != NULL); -+ - closedir(devdir); -+ -+ if (!new_irq_list) -+ return; -+ gentry = g_list_first(new_irq_list); -+ while(gentry) { -+ ninfo = gentry->data; -+ iinfo = get_irq_info(ninfo->irq); -+ new_irq_list = g_list_remove(gentry, ninfo); -+ if (!iinfo) { -+ if (debug_mode) -+ printf("Adding untracked IRQ %d to database\n", ninfo->irq); -+ interrupts_db = g_list_append(interrupts_db, ninfo); -+ } else -+ free(ninfo); -+ -+ gentry = g_list_first(new_irq_list); -+ } -+ g_list_free(new_irq_list); -+ new_irq_list = NULL; -+ - } - --struct irq_info *add_misc_irq(int irq) -+struct irq_info *add_new_irq(int irq) - { -- struct irq_info *new; -+ struct irq_info *new, *nnew; - - new = calloc(sizeof(struct irq_info), 1); -- if (!new) -+ nnew = calloc(sizeof(struct irq_info), 1); -+ if (!new || !nnew) - return NULL; - - new->irq = irq; - new->type = IRQ_TYPE_LEGACY; - new->class = IRQ_OTHER; - new->numa_node = get_numa_node(-1); -+ memcpy(nnew, new, sizeof(struct irq_info)); - interrupts_db = g_list_append(interrupts_db, new); -+ new_irq_list = g_list_append(new_irq_list, nnew); - return new; - } - -@@ -307,7 +412,7 @@ struct irq_info *get_irq_info(int irq) - void migrate_irq(GList **from, GList **to, struct irq_info *info) - { - GList *entry; -- struct irq_info find, *tmp;; -+ struct irq_info find, *tmp; - - find.irq = info->irq; - entry = g_list_find_custom(*from, &find, compare_ints); -@@ -325,18 +430,9 @@ static gint sort_irqs(gconstpointer A, gconstpointer B) - a = (struct irq_info*)A; - b = (struct irq_info*)B; - -- if (a->class < b->class) -- return 1; -- if (a->class > b->class) -- return -1; -- if (a->load < b->load) -- return 1; -- if (a->load > b->load) -- return -1; -- if (a<b) -+ if (a->class < b->class || a->load < b->load || a < b) - return 1; - return -1; -- - } - - void sort_irq_list(GList **list) -diff --git a/configure.ac b/configure.ac -index eed55ba..1230d66 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -1,49 +1,12 @@ --dnl --define([AC_INIT_NOTICE], --[### Generated automatically using autoconf version] AC_ACVERSION [ --### Copyright 2009 Steve Grubb <sgrubb@redhat.com> --### --### Permission is hereby granted, free of charge, to any person obtaining a --### copy of this software and associated documentation files (the "Software"), --### to deal in the Software without restriction, including without limitation --### the rights to use, copy, modify, merge, publish, distribute, sublicense, --### and/or sell copies of the Software, and to permit persons to whom the --### Software is furnished to do so, subject to the following conditions: --### --### The above copyright notice and this permission notice shall be included --### in all copies or substantial portions of the Software. --### --### THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR --### IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, --### FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL --### THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR --### OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, --### ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR --### OTHER DEALINGS IN THE SOFTWARE. --### --### For usage, run `./configure --help' --### For more detailed information on installation, read the file `INSTALL'. --### --### If configuration succeeds, status is in the file `config.status'. --### A log of configuration tests is in `config.log'. --]) -- --AC_REVISION($Revision: 1.3 $)dnl - AC_INIT(irqbalance,1.0.3) - AC_PREREQ(2.12)dnl - AM_CONFIG_HEADER(config.h) - --echo Configuring irqbalance $VERSION -- - AC_CONFIG_MACRO_DIR([m4]) --AC_CANONICAL_TARGET --AM_INIT_AUTOMAKE -+AM_INIT_AUTOMAKE([foreign]) - AM_PROG_LIBTOOL - AC_SUBST(LIBTOOL_DEPS) - --AC_MSG_NOTICE() --AC_MSG_NOTICE([Checking for programs]) -- - AC_PROG_CC - AC_PROG_INSTALL - AC_PROG_AWK -@@ -55,9 +18,6 @@ AS_IF([test "$enable_numa" = "no"],[ - ac_cv_lib_numa_numa_available=no - ]) - --AC_MSG_NOTICE --AC_MSG_NOTICE([echo Checking for header files]) -- - AC_HEADER_STDC - AC_CHECK_HEADERS([numa.h]) - -@@ -70,10 +30,57 @@ AC_C_CONST - AC_C_INLINE - AM_PROG_CC_C_O - --PKG_CHECK_MODULES([GLIB], [glib-2.0 >= 2.28]) --LIBCAP_NG_PATH -+AC_ARG_WITH([glib2], -+ [AS_HELP_STRING([--without-glib2], -+ [Don't use system glib2 library. Use local implementation instead.])], -+ [], -+ [with_glib2=check]) -+ -+local_glib2= -+AS_IF( -+ [test "x$with_glib2" = xyes], -+ [PKG_CHECK_MODULES([GLIB], [glib-2.0 >= 2.28])], -+ -+ [test "x$with_glib2" = xno], -+ [local_glib2="yes"], -+ -+ [PKG_CHECK_MODULES([GLIB], [glib-2.0 >= 2.28], [], [local_glib2="yes"])] -+) -+ -+AS_IF( -+ [test "x$local_glib2" = xyes], -+ [ -+ GLIB_CFLAGS=-I./glib-local -+ GLIB_LIBS=glib-local/libglib.a -+ AC_SUBST(GLIB_CFLAGS) -+ AC_SUBST(GLIB_LIBS) -+ AC_MSG_WARN(Using locale implementation of GList functions) -+ ] -+) -+ -+AM_CONDITIONAL([LOCAL_GLIB], [test "x$local_glib2" = "xyes"]) -+ -+AC_ARG_WITH([libcap-ng], -+ AS_HELP_STRING([libcap-ng], [Add libcap-ng-support @<:@default=auto@:>@])) -+ -+AS_IF( -+ [test "x$libcap_ng" != "xno"], -+ [ -+ PKG_CHECK_MODULES([LIBCAP_NG], [libcap-ng], -+ [AC_DEFINE(HAVE_LIBCAP_NG,1,[libcap-ng support])], -+ [ -+ AS_IF( -+ [test "x$libcap_ng" = "xyes"], -+ [ -+ AC_MSG_ERROR([libcap-ng not found]) -+ ] -+ ) -+ ] -+ ) -+ ] -+) - --AC_OUTPUT(Makefile) -+AC_OUTPUT(Makefile glib-local/Makefile) - - AC_MSG_NOTICE() - AC_MSG_NOTICE([irqbalance Version: $VERSION]) -diff --git a/cputree.c b/cputree.c -index af4fd3a..9568967 100644 ---- a/cputree.c -+++ b/cputree.c -@@ -1,5 +1,6 @@ - /* - * Copyright (C) 2006, Intel Corporation -+ * Copyright (C) 2012, Neil Horman <nhorman@tuxdriver.com> - * - * This file is part of irqbalance - * -diff --git a/glib-local/Makefile.am b/glib-local/Makefile.am -new file mode 100644 -index 0000000..336b56e ---- /dev/null -+++ b/glib-local/Makefile.am -@@ -0,0 +1,8 @@ -+## Process this file with automake to produce Makefile.in -+noinst_LIBRARIES = libglib.a -+ -+libglib_a_SOURCES = glist.c -+ -+libglib_a_CFLAGS = @GLIB_CFLAGS@ -+ -+noinst_HEADERS = glib.h glist.h -diff --git a/glib-local/glib.h b/glib-local/glib.h -new file mode 100644 -index 0000000..5874892 ---- /dev/null -+++ b/glib-local/glib.h -@@ -0,0 +1 @@ -+#include <glist.h> -diff --git a/glib-local/glist.c b/glib-local/glist.c -new file mode 100644 -index 0000000..6fa1761 ---- /dev/null -+++ b/glib-local/glist.c -@@ -0,0 +1,381 @@ -+#include <stdlib.h> -+ -+#include "glist.h" -+ -+/** -+ * g_list_free: -+ * @list: a #GList -+ * -+ * Frees all of the memory used by a #GList. -+ * The freed elements are returned to the slice allocator. -+ * -+ * <note><para> -+ * If list elements contain dynamically-allocated memory, -+ * you should either use g_list_free_full() or free them manually -+ * first. -+ * </para></note> -+ */ -+void -+g_list_free (GList *list) -+{ -+ GList *l = list; -+ -+ while(l) { -+ GList *tmp = l->next; -+ free(l); -+ l = tmp; -+ } -+} -+ -+/** -+ * g_list_last: -+ * @list: a #GList -+ * -+ * Gets the last element in a #GList. -+ * -+ * Returns: the last element in the #GList, -+ * or %NULL if the #GList has no elements -+ */ -+GList* -+g_list_last (GList *list) -+{ -+ if (list) -+ { -+ while (list->next) -+ list = list->next; -+ } -+ -+ return list; -+} -+ -+/** -+ * g_list_append: -+ * @list: a pointer to a #GList -+ * @data: the data for the new element -+ * -+ * Adds a new element on to the end of the list. -+ * -+ * <note><para> -+ * The return value is the new start of the list, which -+ * may have changed, so make sure you store the new value. -+ * </para></note> -+ * -+ * <note><para> -+ * Note that g_list_append() has to traverse the entire list -+ * to find the end, which is inefficient when adding multiple -+ * elements. A common idiom to avoid the inefficiency is to prepend -+ * the elements and reverse the list when all elements have been added. -+ * </para></note> -+ * -+ * |[ -+ * /* Notice that these are initialized to the empty list. */ -+ * GList *list = NULL, *number_list = NULL; -+ * -+ * /* This is a list of strings. */ -+ * list = g_list_append (list, "first"); -+ * list = g_list_append (list, "second"); -+ * -+ * /* This is a list of integers. */ -+ * number_list = g_list_append (number_list, GINT_TO_POINTER (27)); -+ * number_list = g_list_append (number_list, GINT_TO_POINTER (14)); -+ * ]| -+ * -+ * Returns: the new start of the #GList -+ */ -+GList* -+g_list_append (GList *list, -+ gpointer data) -+{ -+ GList *new_list; -+ GList *last; -+ -+ new_list = malloc(sizeof(*new_list)); -+ new_list->data = data; -+ new_list->next = NULL; -+ -+ if (list) -+ { -+ last = g_list_last (list); -+ /* g_assert (last != NULL); */ -+ last->next = new_list; -+ new_list->prev = last; -+ -+ return list; -+ } -+ else -+ { -+ new_list->prev = NULL; -+ return new_list; -+ } -+} -+ -+static inline GList* -+_g_list_remove_link (GList *list, -+ GList *link) -+{ -+ if (link) -+ { -+ if (link->prev) -+ link->prev->next = link->next; -+ if (link->next) -+ link->next->prev = link->prev; -+ -+ if (link == list) -+ list = list->next; -+ -+ link->next = NULL; -+ link->prev = NULL; -+ } -+ -+ return list; -+} -+ -+/** -+ * g_list_delete_link: -+ * @list: a #GList -+ * @link_: node to delete from @list -+ * -+ * Removes the node link_ from the list and frees it. -+ * Compare this to g_list_remove_link() which removes the node -+ * without freeing it. -+ * -+ * Returns: the new head of @list -+ */ -+GList* -+g_list_delete_link (GList *list, -+ GList *link_) -+{ -+ list = _g_list_remove_link (list, link_); -+ free (link_); -+ -+ return list; -+} -+ -+/** -+ * g_list_first: -+ * @list: a #GList -+ * -+ * Gets the first element in a #GList. -+ * -+ * Returns: the first element in the #GList, -+ * or %NULL if the #GList has no elements -+ */ -+GList* -+g_list_first (GList *list) -+{ -+ if (list) -+ { -+ while (list->prev) -+ list = list->prev; -+ } -+ -+ return list; -+} -+ -+static GList * -+g_list_sort_merge (GList *l1, -+ GList *l2, -+ GFunc compare_func, -+ gpointer user_data) -+{ -+ GList list, *l, *lprev; -+ gint cmp; -+ -+ l = &list; -+ lprev = NULL; -+ -+ while (l1 && l2) -+ { -+ cmp = ((GCompareDataFunc) compare_func) (l1->data, l2->data, user_data); -+ -+ if (cmp <= 0) -+ { -+ l->next = l1; -+ l1 = l1->next; -+ } -+ else -+ { -+ l->next = l2; -+ l2 = l2->next; -+ } -+ l = l->next; -+ l->prev = lprev; -+ lprev = l; -+ } -+ l->next = l1 ? l1 : l2; -+ l->next->prev = l; -+ -+ return list.next; -+} -+ -+static GList* -+g_list_sort_real (GList *list, -+ GFunc compare_func, -+ gpointer user_data) -+{ -+ GList *l1, *l2; -+ -+ if (!list) -+ return NULL; -+ if (!list->next) -+ return list; -+ -+ l1 = list; -+ l2 = list->next; -+ -+ while ((l2 = l2->next) != NULL) -+ { -+ if ((l2 = l2->next) == NULL) -+ break; -+ l1 = l1->next; -+ } -+ l2 = l1->next; -+ l1->next = NULL; -+ -+ return g_list_sort_merge (g_list_sort_real (list, compare_func, user_data), -+ g_list_sort_real (l2, compare_func, user_data), -+ compare_func, -+ user_data); -+} -+ -+/** -+ * g_list_sort: -+ * @list: a #GList -+ * @compare_func: the comparison function used to sort the #GList. -+ * This function is passed the data from 2 elements of the #GList -+ * and should return 0 if they are equal, a negative value if the -+ * first element comes before the second, or a positive value if -+ * the first element comes after the second. -+ * -+ * Sorts a #GList using the given comparison function. -+ * -+ * Returns: the start of the sorted #GList -+ */ -+/** -+ * GCompareFunc: -+ * @a: a value. -+ * @b: a value to compare with. -+ * @Returns: negative value if @a < @b; zero if @a = @b; positive -+ * value if @a > @b. -+ * -+ * Specifies the type of a comparison function used to compare two -+ * values. The function should return a negative integer if the first -+ * value comes before the second, 0 if they are equal, or a positive -+ * integer if the first value comes after the second. -+ **/ -+GList * -+g_list_sort (GList *list, -+ GCompareFunc compare_func) -+{ -+ return g_list_sort_real (list, (GFunc) compare_func, NULL); -+ -+} -+ -+/** -+ * g_list_length: -+ * @list: a #GList -+ * -+ * Gets the number of elements in a #GList. -+ * -+ * <note><para> -+ * This function iterates over the whole list to -+ * count its elements. -+ * </para></note> -+ * -+ * Returns: the number of elements in the #GList -+ */ -+guint -+g_list_length (GList *list) -+{ -+ guint length; -+ -+ length = 0; -+ while (list) -+ { -+ length++; -+ list = list->next; -+ } -+ -+ return length; -+} -+ -+/** -+ * g_list_foreach: -+ * @list: a #GList -+ * @func: the function to call with each element's data -+ * @user_data: user data to pass to the function -+ * -+ * Calls a function for each element of a #GList. -+ */ -+/** -+ * GFunc: -+ * @data: the element's data. -+ * @user_data: user data passed to g_list_foreach() or -+ * g_slist_foreach(). -+ * -+ * Specifies the type of functions passed to g_list_foreach() and -+ * g_slist_foreach(). -+ **/ -+void -+g_list_foreach (GList *list, -+ GFunc func, -+ gpointer user_data) -+{ -+ while (list) -+ { -+ GList *next = list->next; -+ (*func) (list->data, user_data); -+ list = next; -+ } -+} -+ -+/** -+ * g_list_free_full: -+ * @list: a pointer to a #GList -+ * @free_func: the function to be called to free each element's data -+ * -+ * Convenience method, which frees all the memory used by a #GList, and -+ * calls the specified destroy function on every element's data. -+ * -+ * Since: 2.28 -+ */ -+void -+g_list_free_full (GList *list, -+ GDestroyNotify free_func) -+{ -+ g_list_foreach (list, (GFunc) free_func, NULL); -+ g_list_free (list); -+} -+ -+/** -+ * g_list_find_custom: -+ * @list: a #GList -+ * @data: user data passed to the function -+ * @func: the function to call for each element. -+ * It should return 0 when the desired element is found -+ * -+ * Finds an element in a #GList, using a supplied function to -+ * find the desired element. It iterates over the list, calling -+ * the given function which should return 0 when the desired -+ * element is found. The function takes two #gconstpointer arguments, -+ * the #GList element's data as the first argument and the -+ * given user data. -+ * -+ * Returns: the found #GList element, or %NULL if it is not found -+ */ -+GList* -+g_list_find_custom (GList *list, -+ gconstpointer data, -+ GCompareFunc func) -+{ -+ g_return_val_if_fail (func != NULL, list); -+ -+ while (list) -+ { -+ if (! func (list->data, data)) -+ return list; -+ list = list->next; -+ } -+ -+ return NULL; -+} -diff --git a/glib-local/glist.h b/glib-local/glist.h -new file mode 100644 -index 0000000..47f2cfe ---- /dev/null -+++ b/glib-local/glist.h -@@ -0,0 +1,56 @@ -+#ifndef __G_LIST_H__ -+#define __G_LIST_H__ -+ -+typedef int gint; -+typedef unsigned int guint; -+typedef void* gpointer; -+typedef const void *gconstpointer; -+typedef gint (*GCompareFunc) (gconstpointer a, -+ gconstpointer b); -+typedef gint (*GCompareDataFunc) (gconstpointer a, -+ gconstpointer b, -+ gpointer user_data); -+typedef void (*GFunc) (gpointer data, -+ gpointer user_data); -+typedef void (*GDestroyNotify) (gpointer data); -+ -+struct _GList; -+typedef struct _GList GList; -+ -+struct _GList -+{ -+ gpointer data; -+ GList *next; -+ GList *prev; -+}; -+ -+/* Doubly linked lists -+ */ -+void g_list_free (GList *list); -+GList* g_list_append (GList *list, -+ gpointer data); -+GList* g_list_delete_link (GList *list, -+ GList *link_); -+GList* g_list_first (GList *list); -+GList* g_list_sort (GList *list, -+ GCompareFunc compare_func); -+guint g_list_length (GList *list); -+void g_list_foreach (GList *list, -+ GFunc func, -+ gpointer user_data); -+void g_list_free_full (GList *list, -+ GDestroyNotify free_func); -+GList* g_list_find_custom (GList *list, -+ gconstpointer data, -+ GCompareFunc func); -+ -+#define g_list_previous(list) ((list) ? (((GList *)(list))->prev) : NULL) -+#define g_list_next(list) ((list) ? (((GList *)(list))->next) : NULL) -+ -+#define g_return_val_if_fail(expr,val) do { \ -+ if (expr) { } else \ -+ { \ -+ return (val); \ -+ } } while(0); -+ -+#endif /* __G_LIST_H__ */ -diff --git a/irqbalance.1 b/irqbalance.1 -index 55fc15f..20105bc 100644 ---- a/irqbalance.1 -+++ b/irqbalance.1 -@@ -39,7 +39,11 @@ Causes irqbalance to be run once, after which the daemon exits - .TP - - .B --debug --Causes irqbalance to run in the foreground and extra debug information to be printed -+Causes irqbalance to print extra debug information. Implies --foreground -+ -+.TP -+.B --foreground -+Causes irqbalance to run in the foreground (without --debug) - - .TP - .B --hintpolicy=[exact | subset | ignore] -@@ -62,6 +66,30 @@ average cpu softirq workload, and no cpus are more than 1 standard deviation - above (and have more than 1 irq assigned to them), attempt to place 1 cpu in - powersave mode. In powersave mode, a cpu will not have any irqs balanced to it, - in an effort to prevent that cpu from waking up without need. -+ -+.TP -+.B --banirq=<irqnum> -+Add the specified irq list to the set of banned irqs. irqbalance will not affect -+the affinity of any irqs on the banned list, allowing them to be specified -+manually. This option is addative and can be specified multiple times -+ -+.TP -+.B --banscript=<script> -+Execute the specified script for each irq that is discovered, passing the sysfs -+path to the associated device as the first argument, and the irq vector as the -+second. An exit value of 0 tells irqbalance that this interrupt should balanced -+and managed as a normal irq, while a non-zero exit code indicates this irq -+should be ignored by irqbalance completely (see --banirq above). Use of this -+script provides users the ability to dynamically select which irqs get exluded -+from balancing, and provides an opportunity for manual affinity setting in one -+single code point. -+ -+.TP -+.B --pid=<file> -+Have irqbalance write its process id to the specified file. By default no -+pidfile is written. The written pidfile is automatically unlinked when -+irqbalance exits. -+ - .SH "ENVIRONMENT VARIABLES" - .TP - .B IRQBALANCE_ONESHOT -@@ -75,9 +103,10 @@ Same as --debug - .B IRQBALANCE_BANNED_CPUS - Provides a mask of cpus which irqbalance should ignore and never assign interrupts to - -+.SH "SIGNALS" - .TP --.B IRQBALANCE_BANNED_INTERRUPTS --A list of space delimited IRQ numbers that irqbalance should not touch -+.B SIGHUP -+Forces a rescan of the available irqs and system topology - - .SH "Homepage" - http://code.google.com/p/irqbalance -diff --git a/irqbalance.c b/irqbalance.c -index 99c5db7..fbe6ac6 100644 ---- a/irqbalance.c -+++ b/irqbalance.c -@@ -1,5 +1,6 @@ - /* - * Copyright (C) 2006, Intel Corporation -+ * Copyright (C) 2012, Neil Horman <nhorman@tuxdriver.com> - * - * This file is part of irqbalance - * -@@ -27,6 +28,10 @@ - #include <syslog.h> - #include <unistd.h> - #include <signal.h> -+#include <time.h> -+#include <sys/types.h> -+#include <sys/stat.h> -+#include <fcntl.h> - #ifdef HAVE_GETOPT_LONG - #include <getopt.h> - #endif -@@ -39,12 +44,15 @@ - volatile int keep_going = 1; - int one_shot_mode; - int debug_mode; -+int foreground_mode; - int numa_avail; --int need_cpu_rescan; -+int need_rescan; - extern cpumask_t banned_cpus; - enum hp_e hint_policy = HINT_POLICY_SUBSET; - unsigned long power_thresh = ULONG_MAX; - unsigned long long cycle_count = 0; -+char *pidfile = NULL; -+char *banscript = NULL; - - void sleep_approx(int seconds) - { -@@ -64,32 +72,45 @@ void sleep_approx(int seconds) - struct option lopts[] = { - {"oneshot", 0, NULL, 'o'}, - {"debug", 0, NULL, 'd'}, -+ {"foreground", 0, NULL, 'f'}, - {"hintpolicy", 1, NULL, 'h'}, - {"powerthresh", 1, NULL, 'p'}, -+ {"banirq", 1 , NULL, 'i'}, -+ {"banscript", 1, NULL, 'b'}, -+ {"pid", 1, NULL, 's'}, - {0, 0, 0, 0} - }; - - static void usage(void) - { -- printf("irqbalance [--oneshot | -o] [--debug | -d] [--hintpolicy= | -h [exact|subset|ignore]]\n"); -- printf(" [--powerthresh= | -p <off> | <n>]\n"); -+ printf("irqbalance [--oneshot | -o] [--debug | -d] [--foreground | -f] [--hintpolicy= | -h [exact|subset|ignore]]\n"); -+ printf(" [--powerthresh= | -p <off> | <n>] [--banirq= | -i <n>]\n"); - } - - static void parse_command_line(int argc, char **argv) - { - int opt; - int longind; -+ unsigned long val; - - while ((opt = getopt_long(argc, argv, -- "odh:p:", -+ "odfh:i:p:s:", - lopts, &longind)) != -1) { - - switch(opt) { - case '?': - usage(); - exit(1); -+ break; -+ case 'b': -+ banscript = strdup(optarg); -+ break; - case 'd': - debug_mode=1; -+ foreground_mode=1; -+ break; -+ case 'f': -+ foreground_mode=1; - break; - case 'h': - if (!strncmp(optarg, "exact", strlen(optarg))) -@@ -103,6 +124,14 @@ static void parse_command_line(int argc, char **argv) - exit(1); - } - break; -+ case 'i': -+ val = strtoull(optarg, NULL, 10); -+ if (val == ULONG_MAX) { -+ usage(); -+ exit(1); -+ } -+ add_banned_irq((int)val); -+ break; - case 'p': - if (!strncmp(optarg, "off", strlen(optarg))) - power_thresh = ULONG_MAX; -@@ -117,6 +146,9 @@ static void parse_command_line(int argc, char **argv) - case 'o': - one_shot_mode=1; - break; -+ case 's': -+ pidfile = optarg; -+ break; - } - } - } -@@ -172,18 +204,34 @@ static void handler(int signum) - keep_going = 0; - } - -+static void force_rescan(int signum) -+{ -+ if (cycle_count) -+ need_rescan = 1; -+} -+ - int main(int argc, char** argv) - { -- struct sigaction action; -+ struct sigaction action, hupaction; - - #ifdef HAVE_GETOPT_LONG - parse_command_line(argc, argv); - #else -- if (argc>1 && strstr(argv[1],"--debug")) -+ if (argc>1 && strstr(argv[1],"--debug")) { - debug_mode=1; -+ foreground_mode=1; -+ } -+ if (argc>1 && strstr(argv[1],"--foreground")) -+ foreground_mode=1; - if (argc>1 && strstr(argv[1],"--oneshot")) - one_shot_mode=1; - #endif -+ -+ /* -+ * Open the syslog connection -+ */ -+ openlog(argv[0], 0, LOG_DAEMON); -+ - if (getenv("IRQBALANCE_BANNED_CPUS")) { - cpumask_parse_user(getenv("IRQBALANCE_BANNED_CPUS"), strlen(getenv("IRQBALANCE_BANNED_CPUS")), banned_cpus); - } -@@ -212,17 +260,35 @@ int main(int argc, char** argv) - - - /* On single core UP systems irqbalance obviously has no work to do */ -- if (core_count<2) -+ if (core_count<2) { -+ char *msg = "Balaincing is ineffective on systems with a " -+ "single cache domain. Shutting down\n"; -+ -+ if (debug_mode) -+ printf("%s", msg); -+ else -+ syslog(LOG_INFO, "%s", msg); - exit(EXIT_SUCCESS); -+ } - /* On dual core/hyperthreading shared cache systems just do a one shot setup */ - if (cache_domain_count==1) - one_shot_mode = 1; - -- if (!debug_mode) -+ if (!foreground_mode) { -+ int pidfd = -1; - if (daemon(0,0)) - exit(EXIT_FAILURE); -+ /* Write pidfile */ -+ if (pidfile && (pidfd = open(pidfile, -+ O_WRONLY | O_CREAT | O_EXCL | O_TRUNC, -+ S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) >= 0) { -+ char str[16]; -+ snprintf(str, sizeof(str), "%u\n", getpid()); -+ write(pidfd, str, strlen(str)); -+ close(pidfd); -+ } -+ } - -- openlog(argv[0], 0, LOG_DAEMON); - - #ifdef HAVE_LIBCAP_NG - // Drop capabilities -@@ -236,6 +302,11 @@ int main(int argc, char** argv) - parse_proc_interrupts(); - parse_proc_stat(); - -+ hupaction.sa_handler = force_rescan; -+ sigemptyset(&hupaction.sa_mask); -+ hupaction.sa_flags = 0; -+ sigaction(SIGHUP, &hupaction, NULL); -+ - while (keep_going) { - sleep_approx(SLEEP_INTERVAL); - if (debug_mode) -@@ -247,8 +318,8 @@ int main(int argc, char** argv) - parse_proc_stat(); - - /* cope with cpu hotplug -- detected during /proc/interrupts parsing */ -- if (need_cpu_rescan) { -- need_cpu_rescan = 0; -+ if (need_rescan) { -+ need_rescan = 0; - /* if there's a hotplug event we better turn off power mode for a bit until things settle */ - power_mode = 0; - if (debug_mode) -@@ -282,5 +353,10 @@ int main(int argc, char** argv) - - } - free_object_tree(); -+ -+ /* Remove pidfile */ -+ if (!foreground_mode && pidfile) -+ unlink(pidfile); -+ - return EXIT_SUCCESS; - } -diff --git a/irqbalance.h b/irqbalance.h -index 4e85325..e46f31f 100644 ---- a/irqbalance.h -+++ b/irqbalance.h -@@ -9,6 +9,7 @@ - #include <stdint.h> - #include <glib.h> - #include <syslog.h> -+#include <limits.h> - - #include "types.h" - #ifdef HAVE_NUMA_H -@@ -40,7 +41,6 @@ void dump_tree(void); - - void activate_mappings(void); - void account_for_nic_stats(void); --void check_power_mode(void); - void clear_cpu_tree(void); - void pci_numa_scan(void); - -@@ -64,10 +64,11 @@ enum hp_e { - extern int debug_mode; - extern int one_shot_mode; - extern int power_mode; --extern int need_cpu_rescan; -+extern int need_rescan; - extern enum hp_e hint_policy; - extern unsigned long long cycle_count; - extern unsigned long power_thresh; -+extern char *banscript; - - /* - * Numa node access routines -@@ -103,10 +104,11 @@ extern int get_cpu_count(void); - */ - extern void rebuild_irq_db(void); - extern void free_irq_db(void); -+extern void add_banned_irq(int irq); - extern void for_each_irq(GList *list, void (*cb)(struct irq_info *info, void *data), void *data); - extern struct irq_info *get_irq_info(int irq); - extern void migrate_irq(GList **from, GList **to, struct irq_info *info); --extern struct irq_info *add_misc_irq(int irq); -+extern struct irq_info *add_new_irq(int irq); - #define irq_numa_node(irq) ((irq)->numa_node) - - -diff --git a/irqlist.c b/irqlist.c -index c29ee84..2523173 100644 ---- a/irqlist.c -+++ b/irqlist.c -@@ -1,5 +1,6 @@ - /* - * Copyright (C) 2006, Intel Corporation -+ * Copyright (C) 2012, Neil Horman <nhorman@tuxdriver.com> - * - * This file is part of irqbalance - * -@@ -45,6 +46,7 @@ struct load_balance_info { - unsigned int num_within; - unsigned int num_over; - unsigned int num_under; -+ unsigned int num_powersave; - struct topo_obj *powersave; - }; - -@@ -106,13 +108,16 @@ static void migrate_overloaded_irqs(struct topo_obj *obj, void *data) - struct load_balance_info *info = data; - int deviation; - -+ if (obj->powersave_mode) -+ info->num_powersave++; -+ - /* - * Don't rebalance irqs on objects whos load is below the average - */ - if (obj->load <= info->avg_load) { - if ((obj->load + info->std_deviation) <= info->avg_load) { - info->num_under++; -- if (!info->powersave) -+ if (power_thresh != ULONG_MAX && !info->powersave) - if (!obj->powersave_mode) - info->powersave = obj; - } else -@@ -172,13 +177,13 @@ void update_migration_status(void) - { - struct load_balance_info info; - find_overloaded_objs(cpus, info); -- if (cycle_count > 5) { -+ if (power_thresh != ULONG_MAX && cycle_count > 5) { - if (!info.num_over && (info.num_under >= power_thresh) && info.powersave) { - syslog(LOG_INFO, "cpu %d entering powersave mode\n", info.powersave->number); - info.powersave->powersave_mode = 1; - if (g_list_length(info.powersave->interrupts) > 0) - for_each_irq(info.powersave->interrupts, force_irq_migration, NULL); -- } else if (info.num_over) { -+ } else if ((info.num_over) && (info.num_powersave)) { - syslog(LOG_INFO, "Load average increasing, re-enabling all cpus for irq balancing\n"); - for_each_object(cpus, clear_powersave_mode, NULL); - } -diff --git a/m4/cap-ng.m4 b/m4/cap-ng.m4 -deleted file mode 100644 -index 0024edc..0000000 ---- a/m4/cap-ng.m4 -+++ /dev/null -@@ -1,40 +0,0 @@ --# libcap-ng.m4 - Checks for the libcap-ng support --# Copyright (c) 2009 Steve Grubb sgrubb@redhat.com --# --AC_DEFUN([LIBCAP_NG_PATH], --[ -- AC_ARG_WITH(libcap-ng, -- [ --with-libcap-ng=[auto/yes/no] Add Libcap-ng support [default=auto]],, -- with_libcap_ng=auto) -- -- # Check for Libcap-ng API -- # -- # libcap-ng detection -- -- if test x$with_libcap_ng = xno ; then -- have_libcap_ng=no; -- else -- # Start by checking for header file -- AC_CHECK_HEADER(cap-ng.h, capng_headers=yes, capng_headers=no) -- -- # See if we have libcap-ng library -- AC_CHECK_LIB(cap-ng, capng_clear, -- CAPNG_LDADD=-lcap-ng,) -- -- # Check results are usable -- if test x$with_libcap_ng = xyes -a x$CAPNG_LDADD = x ; then -- AC_MSG_ERROR(libcap-ng support was requested and the library was not found) -- fi -- if test x$CAPNG_LDADD != x -a $capng_headers = no ; then -- AC_MSG_ERROR(libcap-ng libraries found but headers are missing) -- fi -- fi -- AC_SUBST(CAPNG_LDADD) -- AC_MSG_CHECKING(whether to use libcap-ng) -- if test x$CAPNG_LDADD != x ; then -- AC_DEFINE(HAVE_LIBCAP_NG,1,[libcap-ng support]) -- AC_MSG_RESULT(yes) -- else -- AC_MSG_RESULT(no) -- fi --]) -diff --git a/misc/irqbalance.env b/misc/irqbalance.env -new file mode 100644 -index 0000000..bd87e3d ---- /dev/null -+++ b/misc/irqbalance.env -@@ -0,0 +1,26 @@ -+# irqbalance is a daemon process that distributes interrupts across -+# CPUS on SMP systems. The default is to rebalance once every 10 -+# seconds. This is the environment file that is specified to systemd via the -+# EnvironmentFile key in the service unit file (or via whatever method the init -+# system you're using has. -+# -+# ONESHOT=yes -+# after starting, wait for a minute, then look at the interrupt -+# load and balance it once; after balancing exit and do not change -+# it again. -+#IRQBALANCE_ONESHOT= -+ -+# -+# IRQBALANCE_BANNED_CPUS -+# 64 bit bitmask which allows you to indicate which cpu's should -+# be skipped when reblancing irqs. Cpu numbers which have their -+# corresponding bits set to one in this mask will not have any -+# irq's assigned to them on rebalance -+# -+#IRQBALANCE_BANNED_CPUS= -+ -+# -+# IRQBALANCE_ARGS -+# append any args here to the irqbalance daemon as documented in the man page -+# -+#IRQBALANCE_ARGS= -diff --git a/misc/irqbalance.service b/misc/irqbalance.service -index f349616..3139a83 100644 ---- a/misc/irqbalance.service -+++ b/misc/irqbalance.service -@@ -3,9 +3,8 @@ Description=irqbalance daemon - After=syslog.target - - [Service] --EnvironmentFile=/etc/sysconfig/irqbalance --Type=forking --ExecStart=/usr/sbin/irqbalance $ONESHOT -+EnvironmentFile=/path/to/irqbalance.env -+ExecStart=/usr/sbin/irqbalance --foreground $IRQBALANCE_ARGS - - [Install] - WantedBy=multi-user.target -diff --git a/numa.c b/numa.c -index 710ed67..96703bd 100644 ---- a/numa.c -+++ b/numa.c -@@ -1,5 +1,6 @@ - /* - * Copyright (C) 2006, Intel Corporation -+ * Copyright (C) 2012, Neil Horman <nhorman@tuxdriver.com> - * - * This file is part of irqbalance - * -@@ -106,11 +107,11 @@ void build_numa_node_list(void) - static void free_numa_node(gpointer data) - { - struct topo_obj *obj = data; -- if (data == &unspecified_node) -- return; -- - g_list_free(obj->children); -- free(data); -+ g_list_free(obj->interrupts); -+ -+ if (data != &unspecified_node) -+ free(data); - } - - void free_numa_node_list(void) -diff --git a/placement.c b/placement.c -index 108ccc9..1172849 100644 ---- a/placement.c -+++ b/placement.c -@@ -1,5 +1,6 @@ - /* - * Copyright (C) 2006, Intel Corporation -+ * Copyright (C) 2012, Neil Horman <nhoramn@tuxdriver.com> - * - * This file is part of irqbalance - * -@@ -48,7 +49,7 @@ static void find_best_object(struct topo_obj *d, void *data) - /* - * Don't consider the unspecified numa node here - */ -- if ((d->obj_type == OBJ_TYPE_NODE) && (d->number == -1)) -+ if (numa_avail && (d->obj_type == OBJ_TYPE_NODE) && (d->number == -1)) - return; - - /* -diff --git a/powermode.c b/powermode.c -deleted file mode 100644 -index 82ba490..0000000 ---- a/powermode.c -+++ /dev/null -@@ -1,34 +0,0 @@ --/* -- * Copyright (C) 2006, Intel Corporation -- * -- * This file is part of irqbalance -- * -- * This program file is free software; you can redistribute it and/or modify it -- * under the terms of the GNU General Public License as published by the -- * Free Software Foundation; version 2 of the License. -- * -- * This program is distributed in the hope that it will be useful, but WITHOUT -- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -- * for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with this program in a file named COPYING; if not, write to the -- * Free Software Foundation, Inc., -- * 51 Franklin Street, Fifth Floor, -- * Boston, MA 02110-1301 USA -- */ --#include "config.h" --#include <stdio.h> --#include <stdlib.h> --#include <unistd.h> --#include <stdint.h> --#include <string.h> -- --#include "irqbalance.h" -- -- --void check_power_mode(void) --{ --} -- -diff --git a/procinterrupts.c b/procinterrupts.c -index 4d3b07b..431fffa 100644 ---- a/procinterrupts.c -+++ b/procinterrupts.c -@@ -1,5 +1,6 @@ - /* - * Copyright (C) 2006, Intel Corporation -+ * Copyright (C) 2012, Neil Horman <nhorman@tuxdriver.com> - * - * This file is part of irqbalance - * -@@ -32,6 +33,8 @@ - - #define LINESIZE 4096 - -+extern cpumask_t banned_cpus; -+ - static int proc_int_has_msi = 0; - static int msi_found_in_sysfs = 0; - -@@ -80,8 +83,12 @@ void parse_proc_interrupts(void) - c++; - number = strtoul(line, NULL, 10); - info = get_irq_info(number); -- if (!info) -- info = add_misc_irq(number); -+ if (!info) { -+ if (!cycle_count) -+ continue; -+ need_rescan = 1; -+ info = add_new_irq(number); -+ } - - count = 0; - cpunr = 0; -@@ -97,7 +104,7 @@ void parse_proc_interrupts(void) - cpunr++; - } - if (cpunr != core_count) -- need_cpu_rescan = 1; -+ need_rescan = 1; - - info->last_irq_count = info->irq_count; - info->irq_count = count; -@@ -217,6 +224,9 @@ void parse_proc_stat(void) - - cpunr = strtoul(&line[3], NULL, 10); - -+ if (cpu_isset(cpunr, banned_cpus)) -+ continue; -+ - rc = sscanf(line, "%*s %*d %*d %*d %*d %*d %d %d", &irq_load, &softirq_load); - if (rc < 2) - break; |