add scheduler domains for ia64
PATCH 1/1 add scheduler domains for ia64
Nick, how does this look? It adds scheduler domain code for ia64 and replaces the patch in Andrew's tree. It also adds SD_NODE_INIT macros to each arch that has ARCH_HAS_SCHED_DOMAIN so that the balance values are more easily tweaked. Since the cpu span of the nodes on ia64 is smaller than the whole system, I also removed a WARN_ON in active_load_balance, but I'm not sure if that's correct.
Thanks,
Jesse
===== arch/ia64/kernel/smpboot.c 1.56 vs edited =====
arch/ia64/kernel/smpboot.c +179 -0
@@ -719,3 +719,182 @@printk (KERN_ERR "SMP: Can't set SAL AP Boot Rendezvous: %s\n" ,ia64_sal_strerror (sal_ret)); } + +#ifdef CONFIG_NUMA + +/** +* find_next_best_node - find the next node to include in a sched_domain +* @node: node whose sched_domain we're building +* @used_nodes: nodes already in the sched_domain +* +* Find the next node to include in a given scheduling domain. Simply +* finds the closest node not already in the @used_nodes map. +* +* Should use nodemask_t. +*/ +static int __init find_next_best_node (int node,unsigned long *used_nodes) +{ +int i, n, val, min_val, best_node =0 ; + + min_val =INT_MAX ; + +for (i =0 ; i < numnodes; i++) { +/* Start at @node */ + n = (node + i) % numnodes; + +/* Skip already used nodes */ +if (test_bit (n, used_nodes)) +continue ; + +/* Simple min distance search */ + val =node_distance (node, i); + +if (val < min_val) { + min_val = val; + best_node = n; + } + } + +set_bit (best_node, used_nodes); +return best_node; +} + +/** +* sched_domain_node_span - get a cpumask for a node's sched_domain +* @node: node whose cpumask we're constructing +* @size: number of nodes to include in this span +* +* Given a node, construct a good cpumask for its sched_domain to span. It +* should be one that prevents unnecessary balancing, but also spreads tasks +* out optimally. +*/ +cpumask_t __init sched_domain_node_span (int node,int size) +{ +int i; +cpumask_t span; +DECLARE_BITMAP (used_nodes,MAX_NUMNODES ); + +cpus_clear (span); +bitmap_zero (used_nodes,MAX_NUMNODES ); + +for (i =0 ; i < size; i++) { +int next_node =find_next_best_node (node, used_nodes); +cpus_or (span, span,node_to_cpumask (next_node)); + } + +return span; +} + +static struct sched_group sched_group_cpus[NR_CPUS ]; +static DEFINE_PER_CPU(struct sched_domain, cpu_domains); + +/* Number of nearby nodes in a node's scheduling domain */ +#define SD_NODES_PER_DOMAIN 4 + +static struct sched_group sched_group_nodes[MAX_NUMNODES ]; +static DEFINE_PER_CPU(struct sched_domain, node_domains); +void __init arch_init_sched_domains (void ) +{ +int i; +struct sched_group *first_node =NULL , *last_node =NULL ; + +/* Set up domains */ +for_each_cpu (i) { +int node =cpu_to_node (i); +cpumask_t nodemask =node_to_cpumask (node); +struct sched_domain *node_sd = &per_cpu (node_domains, i); +struct sched_domain *cpu_sd = &per_cpu (cpu_domains, i); + + *node_sd =SD_NODE_INIT ; + node_sd->span =sched_domain_node_span (i,SD_NODES_PER_DOMAIN ); + node_sd->groups = &sched_group_nodes[cpu_to_node (i)]; + + *cpu_sd =SD_CPU_INIT ; +cpus_and (cpu_sd->span, nodemask, cpu_possible_map); + cpu_sd->groups = &sched_group_cpus[i]; + cpu_sd->parent = node_sd; + } + +/* Set up groups */ +for (i =0 ; i <MAX_NUMNODES ; i++) { +cpumask_t tmp =node_to_cpumask (i); +cpumask_t nodemask; +struct sched_group *first_cpu =NULL , *last_cpu =NULL ; +struct sched_group *node = &sched_group_nodes[i]; +int j; + +cpus_and (nodemask, tmp, cpu_possible_map); + +if (cpus_empty (nodemask)) +continue ; + + node->cpumask = nodemask; + node->cpu_power =SCHED_LOAD_SCALE *cpus_weight (node->cpumask); + +for_each_cpu_mask (j, node->cpumask) { +struct sched_group *cpu = &sched_group_cpus[j]; + +cpus_clear (cpu->cpumask); +cpu_set (j, cpu->cpumask); + cpu->cpu_power =SCHED_LOAD_SCALE ; + +if (!first_cpu) + first_cpu = cpu; +if (last_cpu) + last_cpu->next = cpu; + last_cpu = cpu; + } + last_cpu->next = first_cpu; + +if (!first_node) + first_node = node; +if (last_node) + last_node->next = node; + last_node = node; + } + last_node->next = first_node; + +mb (); +for_each_cpu (i) { +struct sched_domain *cpu_sd = &per_cpu (cpu_domains, i); +cpu_attach_domain (cpu_sd, i); + } +} +#else /* !CONFIG_NUMA */ +static void __init arch_init_sched_domains (void ) +{ +int i; +struct sched_group *first_cpu =NULL , *last_cpu =NULL ; + +/* Set up domains */ +for_each_cpu (i) { +struct sched_domain *cpu_sd = &per_cpu (cpu_domains, i); + + *cpu_sd =SD_CPU_INIT ; + cpu_sd->span = cpu_possible_map; + cpu_sd->groups = &sched_group_cpus[i]; + } + +/* Set up CPU groups */ +for_each_cpu_mask (i, cpu_possible_map) { +struct sched_group *cpu = &sched_group_cpus[i]; + +cpus_clear (cpu->cpumask); +cpu_set (i, cpu->cpumask); + cpu->cpu_power =SCHED_LOAD_SCALE ; + +if (!first_cpu) + first_cpu = cpu; +if (last_cpu) + last_cpu->next = cpu; + last_cpu = cpu; + } + last_cpu->next = first_cpu; + +mb ();/* domains were modified outside the lock */ +for_each_cpu (i) { +struct sched_domain *cpu_sd = &per_cpu (cpu_domains, i); +cpu_attach_domain (cpu_sd, i); + } +} +#endif /* CONFIG_NUMA */
===== include/asm-i386/processor.h 1.67 vs edited =====
include/asm-i386/processor.h +18 -0
@@ -647,6 +647,24 @@#ifdef CONFIG_SCHED_SMT #define ARCH_HAS_SCHED_DOMAIN +#define SD_NODE_INIT (struct sched_domain) { \ + .span = CPU_MASK_NONE, \ + .parent = NULL, \ + .groups = NULL, \ + .min_interval = 8, \ + .max_interval = 32, \ + .busy_factor = 32, \ + .imbalance_pct = 125, \ + .cache_hot_time = (10*1000000), \ + .cache_nice_tries = 1, \ + .per_cpu_gain = 100, \ + .flags = SD_BALANCE_EXEC \ + | SD_BALANCE_CLONE \ + | SD_WAKE_BALANCE, \ + .last_balance = jiffies, \ + .balance_interval = 1, \ + .nr_balance_failed = 0, \ +}#define ARCH_HAS_SCHED_WAKE_IDLE #endif
===== include/asm-ia64/processor.h 1.61 vs edited =====
include/asm-ia64/processor.h +23 -0
@@ -334,6 +334,29 @@/* Prepare to copy thread state - unlazy all lazy status */ #define prepare_to_copy (tsk) do { } while (0) +#ifdef CONFIG_NUMA +/* smpboot.c defines a numa specific scheduler domain routine */ +#define ARCH_HAS_SCHED_DOMAIN +#define SD_NODE_INIT (struct sched_domain) { \ + .span = CPU_MASK_NONE, \ + .parent = NULL, \ + .groups = NULL, \ + .min_interval = 80, \ + .max_interval = 320, \ + .busy_factor = 320, \ + .imbalance_pct = 125, \ + .cache_hot_time = (10*1000000), \ + .cache_nice_tries = 1, \ + .per_cpu_gain = 100, \ + .flags = SD_BALANCE_EXEC \ + | SD_BALANCE_CLONE \ + | SD_WAKE_BALANCE, \ + .last_balance = jiffies, \ + .balance_interval = 10, \ + .nr_balance_failed = 0, \ +} +#endif +/* * This is the mechanism for creating a new kernel thread. *
===== include/asm-ppc64/processor.h 1.48 vs edited =====
include/asm-ppc64/processor.h +18 -0
@@ -628,6 +628,24 @@#ifdef CONFIG_SCHED_SMT #define ARCH_HAS_SCHED_DOMAIN +#define SD_NODE_INIT (struct sched_domain) { \ + .span = CPU_MASK_NONE, \ + .parent = NULL, \ + .groups = NULL, \ + .min_interval = 8, \ + .max_interval = 32, \ + .busy_factor = 32, \ + .imbalance_pct = 125, \ + .cache_hot_time = (10*1000000), \ + .cache_nice_tries = 1, \ + .per_cpu_gain = 100, \ + .flags = SD_BALANCE_EXEC \ + | SD_BALANCE_CLONE \ + | SD_WAKE_BALANCE, \ + .last_balance = jiffies, \ + .balance_interval = 1, \ + .nr_balance_failed = 0, \ +}#define ARCH_HAS_SCHED_WAKE_IDLE #endif
===== include/asm-x86_64/processor.h 1.36 vs edited =====
include/asm-x86_64/processor.h +18 -0
@@ -458,6 +458,24 @@#ifdef CONFIG_SCHED_SMT #define ARCH_HAS_SCHED_DOMAIN +#define SD_NODE_INIT (struct sched_domain) { \ + .span = CPU_MASK_NONE, \ + .parent = NULL, \ + .groups = NULL, \ + .min_interval = 8, \ + .max_interval = 32, \ + .busy_factor = 32, \ + .imbalance_pct = 125, \ + .cache_hot_time = (10*1000000), \ + .cache_nice_tries = 1, \ + .per_cpu_gain = 100, \ + .flags = SD_BALANCE_EXEC \ + | SD_BALANCE_CLONE \ + | SD_WAKE_BALANCE, \ + .last_balance = jiffies, \ + .balance_interval = 1, \ + .nr_balance_failed = 0, \ +}#define ARCH_HAS_SCHED_WAKE_IDLE #endif
===== include/linux/sched.h 1.228 vs edited =====
include/linux/sched.h +3 -0
@@ -17,6 +17,7 @@#include <asm/system.h> #include <asm/semaphore.h> #include <asm/page.h> +#include <asm/processor.h> #include <asm/ptrace.h> #include <asm/mmu.h>
@@ -654,6 +655,7 @@ }#ifdef CONFIG_NUMA +#ifndef ARCH_HAS_SCHED_DOMAIN /* Common values for NUMA nodes */ #define SD_NODE_INIT (struct sched_domain) { \ .span = CPU_MASK_NONE, \
@@ -673,6 +675,7 @@ .balance_interval = 1, \ .nr_balance_failed = 0, \ } +#endif #endif extern void cpu_attach_domain (struct sched_domain *sd,int cpu);
===== kernel/sched.c 1.319 vs edited =====
kernel/sched.c +1 -3
@@ -1826,10 +1826,8 @@for_each_domain (busiest_cpu, sd)if (cpu_isset (busiest->push_cpu, sd->span))break ; -if (!sd) { -WARN_ON (1 ); +if (!sd)return ; - } group = sd->groups;while (!cpu_isset (busiest_cpu, group->cpumask))
Quoted 6 lines · Jesse Barnes
Nick, how does this look? It adds scheduler domain code for ia64 and replaces the patch in Andrew's tree. It also adds
SD_NODE_INITmacros to each arch that hasARCH_HAS_SCHED_DOMAINso that the balance values are more easily tweaked. Since the cpu span of the nodes on ia64 is smaller than the whole system, I also removed aWARN_ONinactive_load_balance, but I'm not sure if that's correct.
Hi Jesse,
Andrew's latest tree should have a number of improvements and changes to the sched domains code which you will need to synch up to.
One issue you may have is that Ingo removed the ability to have arch code override the domain structure due to it being too hazardous for architectures to use in this form (which I don't entirely disagree with).
Now I guess your patch could go into the generic code because it is pretty general - however are you guys going to want to do anything more fancy with these things?
Nick
Quoted 2 lines · Nick Piggin
Andrew's latest tree should have a number of improvements and changes to the sched domains code which you will need to synch up to.
Yeah, I forgot about those. I'll respin against your consolidation stuff.
Quoted 7 lines
One issue you may have is that Ingo removed the ability to have arch code override the domain structure due to it being too hazardous for architectures to use in this form (which I don't entirely disagree with).
Now I guess your patch could go into the generic code because it is pretty general - however are you guys going to want to do anything more fancy with these things?
Maybe, we haven't figured out the best way to schedule on a 512p yet, but most or all of this code is generic. In order for things to work at all though, we'll need to change some of the SD_NODE_INIT values, maybe we can keep that as per-arch?
Thanks,
Jesse
Quoted 8 lines · Jesse Barnes
Quoted 2 lines · Nick Piggin
Andrew's latest tree should have a number of improvements and changes to the sched domains code which you will need to synch up to.
Yeah, I forgot about those. I'll respin against your consolidation stuff.
Thanks.
Quoted 10 lines
Quoted 8 lines
One issue you may have is that Ingo removed the ability to have arch code override the domain structure due to it being too hazardous for architectures to use in this form (which I don't entirely disagree with).
Now I guess your patch could go into the generic code because it is pretty general - however are you guys going to want to do anything more fancy with these things?
Quoted 5 lines
Maybe, we haven't figured out the best way to schedule on a 512p yet, but most or all of this code is generic. In order for things to work at all though, we'll need to change some of the
SD_NODE_INITvalues, maybe we can keep that as per-arch?
Yeah, all the SD_*_INIT values are overridable. We could even say, put in an SD_NODE2_INIT for a 2nd level NUMA domain in the generic code, for example.
I'd say your closest-node setup would probably get close to what you want. The main thing you want is to not do huge amounts of balancing work in interrupt context, and also not to move a task from one side of the system to the other when one node is a little bit out of balance.
I guess if you want to do anything fancier then we can take a look at re-exporting the domain setup.
Quoted 3 lines · Nick Piggin
Yeah, all the SD_*_INIT values are overridable. We could even say, put in an
SD_NODE2_INITfor a 2nd level NUMA domain in the generic code, for example.
Yeah, we'll need different values for each level in the hierarchy.
Quoted 7 lines
I'd say your closest-node setup would probably get close to what you want. The main thing you want is to not do huge amounts of balancing work in interrupt context, and also not to move a task from one side of the system to the other when one node is a little bit out of balance.
I guess if you want to do anything fancier then we can take a look at re-exporting the domain setup.
Ok, sounds good. How does this look? It sits on top of 2.6.8.1-mm1, ripping out the ia64 specific bits and moving things to sched.c. I've also added an ia64 specific SD_NODE_INIT and an #if !defined to sched.c
Jesse
arch/ia64/kernel/smpboot.c +0 -66
@@ -707,69 +707,3 @@ init_smp_config(void) ia64_sal_strerror(sal_ret)); } -#ifdef CONFIG_NUMA - -/** -* find_next_best_node - find the next node to include in a sched_domain -* @node: node whose sched_domain we're building -* @used_nodes: nodes already in the sched_domain -* -* Find the next node to include in a given scheduling domain. Simply -* finds the closest node not already in the @used_nodes map. -* -* Should use nodemask_t. -*/ -static int __init find_next_best_node (int node,unsigned long *used_nodes) -{ -int i, n, val, min_val, best_node =0 ; - - min_val =INT_MAX ; - -for (i =0 ; i < numnodes; i++) { -/* Start at @node */ - n = (node + i) % numnodes; - -/* Skip already used nodes */ -if (test_bit (n, used_nodes)) -continue ; - -/* Simple min distance search */ - val =node_distance (node, i); - -if (val < min_val) { - min_val = val; - best_node = n; - } - } - -set_bit (best_node, used_nodes); -return best_node; -} - -/** -* sched_domain_node_span - get a cpumask for a node's sched_domain -* @node: node whose cpumask we're constructing -* @size: number of nodes to include in this span -* -* Given a node, construct a good cpumask for its sched_domain to span. It -* should be one that prevents unnecessary balancing, but also spreads tasks -* out optimally. -*/ -cpumask_t __init sched_domain_node_span (int node,int size) -{ -int i; -cpumask_t span; -DECLARE_BITMAP (used_nodes,MAX_NUMNODES ); - -cpus_clear (span); -bitmap_zero (used_nodes,MAX_NUMNODES ); - -for (i =0 ; i < size; i++) { -int next_node =find_next_best_node (node, used_nodes); -cpus_or (span, span,node_to_cpumask (next_node)); - } - -return span; -} -#endif /* CONFIG_NUMA */ -
include/asm-ia64/processor.h +17 -2
@@ -335,8 +335,23 @@ struct task_struct;#define prepare_to_copy (tsk) do { } while (0)#ifdef CONFIG_NUMA -/* smpboot.c defines a numa specific scheduler domain routine */ -#define ARCH_HAS_SCHED_DOMAIN +#define SD_NODE_INIT (struct sched_domain) { \ + .span = CPU_MASK_NONE, \ + .parent = NULL, \ + .groups = NULL, \ + .min_interval = 80, \ + .max_interval = 320, \ + .busy_factor = 320, \ + .imbalance_pct = 125, \ + .cache_hot_time = (10*1000000), \ + .cache_nice_tries = 1, \ + .per_cpu_gain = 100, \ + .flags = SD_BALANCE_EXEC \ + | SD_WAKE_BALANCE, \ + .last_balance = jiffies, \ + .balance_interval = 10, \ + .nr_balance_failed = 0, \ +}#endif /*
kernel/sched.c +67 -9
99 lines not on this page · raw message
Quoted 15 lines · Jesse Barnes
Quoted 3 lines · Nick Piggin
Yeah, all the SD_*_INIT values are overridable. We could even say, put in an
SD_NODE2_INITfor a 2nd level NUMA domain in the generic code, for example.Yeah, we'll need different values for each level in the hierarchy.
Quoted 5 lines
I'd say your closest-node setup would probably get close to what you want. The main thing you want is to not do huge amounts of balancing work in interrupt context, and also not to move a task from one side of the system to the other when one node is a little bit out of balance.
Quoted 8 lines
Quoted 2 lines
I guess if you want to do anything fancier then we can take a look at re-exporting the domain setup.
Ok, sounds good. How does this look? It sits on top of 2.6.8.1-mm1, ripping out the ia64 specific bits and moving things to
sched.c. I've also added an ia64 specificSD_NODE_INITand an #if !defined tosched.c
Sorry I haven't replied earlier. I think this looks good, provided it does the right thing for you (I can't test it myself). Send it to Andrew to get merged if you'd like.
Quoted 3 lines · Nick Piggin
Sorry I haven't replied earlier. I think this looks good, provided it does the right thing for you (I can't test it myself). Send it to Andrew to get merged if you'd like.
Yep, it's been working ok so far. There's still more we can do, but this is a good start I think. Andrew, this version applies on top of 2.6.8.1-mm2 but overwrites most of the earlier node-span patch by moving bits from arch/ia64 to kernel/sched.c, so let me know if you want the patch in a different format.
This patch adds some more NUMA specific logic to the creation of scheduler domains. Domains spanning all CPUs in a large system are too large to schedule across efficiently, leading to livelocks and inordinate amounts of time being spent in scheduler routines. With this patch applied, the node scheduling domains for NUMA platforms will only contain a specified number of nearby CPUs, based on the value of SD_NODES_PER_DOMAIN. It also allows arches to override SD_NODE_INIT, which sets the domain scheduling parameters for each node's domain. This is necessary especially for large systems.
Possible future directions:
o multilevel node hierarchy (e.g. node domains could contain 4 nodes worth
of CPUs, supernode domains could contain 32 nodes worth, etc. each with their own SD_NODE_INIT values)
o more tweaking of SD_NODE_INIT values for good load balancing vs. overhead
tradeoffs
Thanks,
Jesse
arch/ia64/kernel/smpboot.c +0 -66
@@ -707,69 +707,3 @@ init_smp_config(void) ia64_sal_strerror(sal_ret)); } -#ifdef CONFIG_NUMA - -/** -* find_next_best_node - find the next node to include in a sched_domain -* @node: node whose sched_domain we're building -* @used_nodes: nodes already in the sched_domain -* -* Find the next node to include in a given scheduling domain. Simply -* finds the closest node not already in the @used_nodes map. -* -* Should use nodemask_t. -*/ -static int __init find_next_best_node (int node,unsigned long *used_nodes) -{ -int i, n, val, min_val, best_node =0 ; - - min_val =INT_MAX ; - -for (i =0 ; i < numnodes; i++) { -/* Start at @node */ - n = (node + i) % numnodes; - -/* Skip already used nodes */ -if (test_bit (n, used_nodes)) -continue ; - -/* Simple min distance search */ - val =node_distance (node, i); - -if (val < min_val) { - min_val = val; - best_node = n; - } - } - -set_bit (best_node, used_nodes); -return best_node; -} - -/** -* sched_domain_node_span - get a cpumask for a node's sched_domain -* @node: node whose cpumask we're constructing -* @size: number of nodes to include in this span -* -* Given a node, construct a good cpumask for its sched_domain to span. It -* should be one that prevents unnecessary balancing, but also spreads tasks -* out optimally. -*/ -cpumask_t __init sched_domain_node_span (int node,int size) -{ -int i; -cpumask_t span; -DECLARE_BITMAP (used_nodes,MAX_NUMNODES ); - -cpus_clear (span); -bitmap_zero (used_nodes,MAX_NUMNODES ); - -for (i =0 ; i < size; i++) { -int next_node =find_next_best_node (node, used_nodes); -cpus_or (span, span,node_to_cpumask (next_node)); - } - -return span; -} -#endif /* CONFIG_NUMA */ -
include/asm-ia64/processor.h +17 -2
@@ -335,8 +335,23 @@ struct task_struct;#define prepare_to_copy (tsk) do { } while (0)#ifdef CONFIG_NUMA -/* smpboot.c defines a numa specific scheduler domain routine */ -#define ARCH_HAS_SCHED_DOMAIN +#define SD_NODE_INIT (struct sched_domain) { \ + .span = CPU_MASK_NONE, \ + .parent = NULL, \ + .groups = NULL, \ + .min_interval = 80, \ + .max_interval = 320, \ + .busy_factor = 320, \ + .imbalance_pct = 125, \ + .cache_hot_time = (10*1000000), \ + .cache_nice_tries = 1, \ + .per_cpu_gain = 100, \ + .flags = SD_BALANCE_EXEC \ + | SD_WAKE_BALANCE, \ + .last_balance = jiffies, \ + .balance_interval = 10, \ + .nr_balance_failed = 0, \ +}#endif /*
kernel/sched.c +67 -9
99 lines not on this page · raw message
Quoted 6 lines · Jesse Barnes
Yep, it's been working ok so far. There's still more we can do, but this is a
good start I think. Andrew, this version applies on top of 2.6.8.1-mm2 but overwrites most of the earlier node-span patch by moving bits fromarch/ia64tokernel/sched.c, so let me know if you want the patch in a different format.
Is OK. I wiggled it into the logical place so we'll end up with a sane patch series.
Watch the warnings please...
kernel/sched.c:3732: warning: `sched_domain_node_span' defined but not used
---
25-akpm/kernel/sched.c | 5 ----- 1 files changed, 5 deletions(-)
kernel/sched.c renamed from kernel/sched.c~sched-domain-node-span-4-update-warning-fix +0 -5
@@ -3727,11 +3727,6 @@ cpumask_t __init sched_domain_node_span( return span; } -#else /* !CONFIG_NUMA */ -static cpumask_t __init sched_domain_node_span (int node,int size) -{ -return cpu_possible_map; -}#endif /* CONFIG_NUMA */ #ifdef CONFIG_SCHED_SMT
_
Quoted 7 lines · Andrew Morton
Quoted 5 lines · Jesse Barnes
Yep, it's been working ok so far. There's still more we can do, but this is a good start I think. Andrew, this version applies on top of 2.6.8.1-mm2 but overwrites most of the earlier node-span patch by moving bits from
arch/ia64tokernel/sched.c, so let me know if you want the patch in a different format.
Quoted 8 lines
Is OK. I wiggled it into the logical place so we'll end up with a sane patch series.
Watch the warnings please...
kernel/sched.c:3732: warning: `sched_domain_node_span' defined but not used
Oops, sorry about that! I meant to test with CONFIG_NUMA=n but fell asleep. I'll be more careful in the future.
Jesse
Quoted 9 lines · Jesse Barnes
This patch adds some more NUMA specific logic to the creation of scheduler domains. Domains spanning all CPUs in a large system are too large to schedule across efficiently, leading to livelocks and inordinate amounts of time being spent in scheduler routines. With this patch applied, the node scheduling domains for NUMA platforms will only contain a specified number of nearby CPUs, based on the value of
SD_NODES_PER_DOMAIN. It also allows arches to overrideSD_NODE_INIT, which sets the domain scheduling parameters for each node's domain. This is necessary especially for large systems.
looks good to me too.
Ingo