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 * * 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 (aclass < 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 -### -### 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 * * 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 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 + +#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. + * + * + * If list elements contain dynamically-allocated memory, + * you should either use g_list_free_full() or free them manually + * first. + * + */ +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. + * + * + * The return value is the new start of the list, which + * may have changed, so make sure you store the new value. + * + * + * + * 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. + * + * + * |[ + * /* 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. + * + * + * This function iterates over the whole list to + * count its elements. + * + * + * 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= +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=