irqbalance: add support for affinity_hint hook
This support is found in kernels 2.6.35 and beyond. The new affinity_hint hook found in /proc/irq/<num>/ can be populated by underlying device drivers. The cpumask in this file will be used as a preferred affinity, allowing devices with multiple interrupt sources (e.g. MSI-X enabled network devices) to better control their NUMA locality of data flows. Signed-off-by: Peter P Waskiewicz Jr <peter.p.waskiewicz.jr@intel.com> git-svn-id: https://irqbalance.googlecode.com/svn/trunk@25 46b42954-3823-0410-bd82-eb80b452c9b5
This commit is contained in:
parent
66da32e3da
commit
7cd766c0f4
|
@ -80,7 +80,6 @@ int main(int argc, char** argv)
|
||||||
if (cache_domain_count==1)
|
if (cache_domain_count==1)
|
||||||
one_shot_mode = 1;
|
one_shot_mode = 1;
|
||||||
|
|
||||||
|
|
||||||
if (!debug_mode)
|
if (!debug_mode)
|
||||||
if (daemon(0,0))
|
if (daemon(0,0))
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
|
|
24
irqlist.c
24
irqlist.c
|
@ -36,6 +36,26 @@ GList *interrupts;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void get_affinity_hint(struct interrupt *irq, int number)
|
||||||
|
{
|
||||||
|
char buf[PATH_MAX];
|
||||||
|
char *line = NULL;
|
||||||
|
size_t size = 0;
|
||||||
|
FILE *file;
|
||||||
|
sprintf(buf, "/proc/irq/%i/affinity_hint", number);
|
||||||
|
file = fopen(buf, "r");
|
||||||
|
if (!file)
|
||||||
|
return;
|
||||||
|
if (getline(&line, &size, file)==0) {
|
||||||
|
free(line);
|
||||||
|
fclose(file);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cpumask_parse_user(line, strlen(line), irq->node_mask);
|
||||||
|
fclose(file);
|
||||||
|
free(line);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This function classifies and reads various things from /proc about a specific irq
|
* This function classifies and reads various things from /proc about a specific irq
|
||||||
*/
|
*/
|
||||||
|
@ -84,6 +104,8 @@ static void investigate(struct interrupt *irq, int number)
|
||||||
cpumask_parse_user(line, strlen(line), irq->allowed_mask);
|
cpumask_parse_user(line, strlen(line), irq->allowed_mask);
|
||||||
fclose(file);
|
fclose(file);
|
||||||
free(line);
|
free(line);
|
||||||
|
} else if (strcmp(entry->d_name,"affinity_hint")==0) {
|
||||||
|
get_affinity_hint(irq, number);
|
||||||
} else {
|
} else {
|
||||||
irq->class = find_class(irq, entry->d_name);
|
irq->class = find_class(irq, entry->d_name);
|
||||||
}
|
}
|
||||||
|
@ -134,6 +156,8 @@ void set_interrupt_count(int number, uint64_t count)
|
||||||
|
|
||||||
if (irq->number == number) {
|
if (irq->number == number) {
|
||||||
irq->count = count;
|
irq->count = count;
|
||||||
|
/* see if affinity_hint changed */
|
||||||
|
get_affinity_hint(irq, number);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
item = g_list_next(item);
|
item = g_list_next(item);
|
||||||
|
|
39
placement.c
39
placement.c
|
@ -257,6 +257,30 @@ static void place_packages(GList *list)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void place_affinity_hint(GList *list)
|
||||||
|
{
|
||||||
|
/* still need to balance best workload within the affinity_hint mask */
|
||||||
|
GList *iter;
|
||||||
|
struct interrupt *irq;
|
||||||
|
|
||||||
|
iter = g_list_first(list);
|
||||||
|
while (iter) {
|
||||||
|
irq = iter->data;
|
||||||
|
if (irq->balance_level == BALANCE_NONE) {
|
||||||
|
iter = g_list_next(iter);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ((!cpus_empty(irq->node_mask)) &&
|
||||||
|
(!cpus_equal(irq->mask, irq->node_mask)) &&
|
||||||
|
(!cpus_full(irq->node_mask))) {
|
||||||
|
irq->old_mask = irq->mask;
|
||||||
|
irq->mask = irq->node_mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
iter = g_list_next(iter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void do_unroutables(void)
|
static void do_unroutables(void)
|
||||||
{
|
{
|
||||||
|
@ -276,7 +300,8 @@ static void do_unroutables(void)
|
||||||
iter = g_list_first(packages);
|
iter = g_list_first(packages);
|
||||||
while (iter) {
|
while (iter) {
|
||||||
package = iter->data;
|
package = iter->data;
|
||||||
if (cpus_intersects(package->mask, irq->mask))
|
if (cpus_intersects(package->mask, irq->node_mask) ||
|
||||||
|
cpus_intersects(package->mask, irq->mask))
|
||||||
package->workload += irq->workload;
|
package->workload += irq->workload;
|
||||||
iter = g_list_next(iter);
|
iter = g_list_next(iter);
|
||||||
}
|
}
|
||||||
|
@ -284,14 +309,16 @@ static void do_unroutables(void)
|
||||||
iter = g_list_first(cache_domains);
|
iter = g_list_first(cache_domains);
|
||||||
while (iter) {
|
while (iter) {
|
||||||
cache_domain = iter->data;
|
cache_domain = iter->data;
|
||||||
if (cpus_intersects(cache_domain->mask, irq->mask))
|
if (cpus_intersects(cache_domain->mask, irq->node_mask)
|
||||||
|
|| cpus_intersects(cache_domain->mask, irq->mask))
|
||||||
cache_domain->workload += irq->workload;
|
cache_domain->workload += irq->workload;
|
||||||
iter = g_list_next(iter);
|
iter = g_list_next(iter);
|
||||||
}
|
}
|
||||||
iter = g_list_first(cpus);
|
iter = g_list_first(cpus);
|
||||||
while (iter) {
|
while (iter) {
|
||||||
cpu = iter->data;
|
cpu = iter->data;
|
||||||
if (cpus_intersects(cpu->mask, irq->mask))
|
if (cpus_intersects(cpu->mask, irq->node_mask) ||
|
||||||
|
cpus_intersects(cpu->mask, irq->mask))
|
||||||
cpu->workload += irq->workload;
|
cpu->workload += irq->workload;
|
||||||
iter = g_list_next(iter);
|
iter = g_list_next(iter);
|
||||||
}
|
}
|
||||||
|
@ -323,4 +350,10 @@ void calculate_placement(void)
|
||||||
place_core(cache_domain);
|
place_core(cache_domain);
|
||||||
iter = g_list_next(iter);
|
iter = g_list_next(iter);
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
* if affinity_hint is populated on irq and is not set to
|
||||||
|
* all CPUs (meaning it's initialized), honor that above
|
||||||
|
* anything in the package locality/workload.
|
||||||
|
*/
|
||||||
|
place_affinity_hint(interrupts);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue