diff options
-rw-r--r-- | init/Kconfig | 27 | ||||
-rw-r--r-- | kernel/rcutree.c | 2 | ||||
-rw-r--r-- | kernel/rcutree.h | 10 |
3 files changed, 31 insertions, 8 deletions
diff --git a/init/Kconfig b/init/Kconfig index 85c6870ed476..6d18ef8071b5 100644 --- a/init/Kconfig +++ b/init/Kconfig | |||
@@ -458,6 +458,33 @@ config RCU_FANOUT | |||
458 | Select a specific number if testing RCU itself. | 458 | Select a specific number if testing RCU itself. |
459 | Take the default if unsure. | 459 | Take the default if unsure. |
460 | 460 | ||
461 | config RCU_FANOUT_LEAF | ||
462 | int "Tree-based hierarchical RCU leaf-level fanout value" | ||
463 | range 2 RCU_FANOUT if 64BIT | ||
464 | range 2 RCU_FANOUT if !64BIT | ||
465 | depends on TREE_RCU || TREE_PREEMPT_RCU | ||
466 | default 16 | ||
467 | help | ||
468 | This option controls the leaf-level fanout of hierarchical | ||
469 | implementations of RCU, and allows trading off cache misses | ||
470 | against lock contention. Systems that synchronize their | ||
471 | scheduling-clock interrupts for energy-efficiency reasons will | ||
472 | want the default because the smaller leaf-level fanout keeps | ||
473 | lock contention levels acceptably low. Very large systems | ||
474 | (hundreds or thousands of CPUs) will instead want to set this | ||
475 | value to the maximum value possible in order to reduce the | ||
476 | number of cache misses incurred during RCU's grace-period | ||
477 | initialization. These systems tend to run CPU-bound, and thus | ||
478 | are not helped by synchronized interrupts, and thus tend to | ||
479 | skew them, which reduces lock contention enough that large | ||
480 | leaf-level fanouts work well. | ||
481 | |||
482 | Select a specific number if testing RCU itself. | ||
483 | |||
484 | Select the maximum permissible value for large systems. | ||
485 | |||
486 | Take the default if unsure. | ||
487 | |||
461 | config RCU_FANOUT_EXACT | 488 | config RCU_FANOUT_EXACT |
462 | bool "Disable tree-based hierarchical RCU auto-balancing" | 489 | bool "Disable tree-based hierarchical RCU auto-balancing" |
463 | depends on TREE_RCU || TREE_PREEMPT_RCU | 490 | depends on TREE_RCU || TREE_PREEMPT_RCU |
diff --git a/kernel/rcutree.c b/kernel/rcutree.c index 1050d6d3922c..780acf8e15e9 100644 --- a/kernel/rcutree.c +++ b/kernel/rcutree.c | |||
@@ -2418,7 +2418,7 @@ static void __init rcu_init_levelspread(struct rcu_state *rsp) | |||
2418 | 2418 | ||
2419 | for (i = NUM_RCU_LVLS - 1; i > 0; i--) | 2419 | for (i = NUM_RCU_LVLS - 1; i > 0; i--) |
2420 | rsp->levelspread[i] = CONFIG_RCU_FANOUT; | 2420 | rsp->levelspread[i] = CONFIG_RCU_FANOUT; |
2421 | rsp->levelspread[0] = RCU_FANOUT_LEAF; | 2421 | rsp->levelspread[0] = CONFIG_RCU_FANOUT_LEAF; |
2422 | } | 2422 | } |
2423 | #else /* #ifdef CONFIG_RCU_FANOUT_EXACT */ | 2423 | #else /* #ifdef CONFIG_RCU_FANOUT_EXACT */ |
2424 | static void __init rcu_init_levelspread(struct rcu_state *rsp) | 2424 | static void __init rcu_init_levelspread(struct rcu_state *rsp) |
diff --git a/kernel/rcutree.h b/kernel/rcutree.h index cdd1be0a4072..a905c200405c 100644 --- a/kernel/rcutree.h +++ b/kernel/rcutree.h | |||
@@ -29,18 +29,14 @@ | |||
29 | #include <linux/seqlock.h> | 29 | #include <linux/seqlock.h> |
30 | 30 | ||
31 | /* | 31 | /* |
32 | * Define shape of hierarchy based on NR_CPUS and CONFIG_RCU_FANOUT. | 32 | * Define shape of hierarchy based on NR_CPUS, CONFIG_RCU_FANOUT, and |
33 | * CONFIG_RCU_FANOUT_LEAF. | ||
33 | * In theory, it should be possible to add more levels straightforwardly. | 34 | * In theory, it should be possible to add more levels straightforwardly. |
34 | * In practice, this did work well going from three levels to four. | 35 | * In practice, this did work well going from three levels to four. |
35 | * Of course, your mileage may vary. | 36 | * Of course, your mileage may vary. |
36 | */ | 37 | */ |
37 | #define MAX_RCU_LVLS 4 | 38 | #define MAX_RCU_LVLS 4 |
38 | #if CONFIG_RCU_FANOUT > 16 | 39 | #define RCU_FANOUT_1 (CONFIG_RCU_FANOUT_LEAF) |
39 | #define RCU_FANOUT_LEAF 16 | ||
40 | #else /* #if CONFIG_RCU_FANOUT > 16 */ | ||
41 | #define RCU_FANOUT_LEAF (CONFIG_RCU_FANOUT) | ||
42 | #endif /* #else #if CONFIG_RCU_FANOUT > 16 */ | ||
43 | #define RCU_FANOUT_1 (RCU_FANOUT_LEAF) | ||
44 | #define RCU_FANOUT_2 (RCU_FANOUT_1 * CONFIG_RCU_FANOUT) | 40 | #define RCU_FANOUT_2 (RCU_FANOUT_1 * CONFIG_RCU_FANOUT) |
45 | #define RCU_FANOUT_3 (RCU_FANOUT_2 * CONFIG_RCU_FANOUT) | 41 | #define RCU_FANOUT_3 (RCU_FANOUT_2 * CONFIG_RCU_FANOUT) |
46 | #define RCU_FANOUT_4 (RCU_FANOUT_3 * CONFIG_RCU_FANOUT) | 42 | #define RCU_FANOUT_4 (RCU_FANOUT_3 * CONFIG_RCU_FANOUT) |