xref: /linux-6.15/include/linux/rcu_node_tree.h (revision f2425b4e)
1*f2425b4eSPaul E. McKenney /*
2*f2425b4eSPaul E. McKenney  * RCU node combining tree definitions.  These are used to compute
3*f2425b4eSPaul E. McKenney  * global attributes while avoiding common-case global contention.  A key
4*f2425b4eSPaul E. McKenney  * property that these computations rely on is a tournament-style approach
5*f2425b4eSPaul E. McKenney  * where only one of the tasks contending a lower level in the tree need
6*f2425b4eSPaul E. McKenney  * advance to the next higher level.  If properly configured, this allows
7*f2425b4eSPaul E. McKenney  * unlimited scalability while maintaining a constant level of contention
8*f2425b4eSPaul E. McKenney  * on the root node.
9*f2425b4eSPaul E. McKenney  *
10*f2425b4eSPaul E. McKenney  * This program is free software; you can redistribute it and/or modify
11*f2425b4eSPaul E. McKenney  * it under the terms of the GNU General Public License as published by
12*f2425b4eSPaul E. McKenney  * the Free Software Foundation; either version 2 of the License, or
13*f2425b4eSPaul E. McKenney  * (at your option) any later version.
14*f2425b4eSPaul E. McKenney  *
15*f2425b4eSPaul E. McKenney  * This program is distributed in the hope that it will be useful,
16*f2425b4eSPaul E. McKenney  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17*f2425b4eSPaul E. McKenney  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18*f2425b4eSPaul E. McKenney  * GNU General Public License for more details.
19*f2425b4eSPaul E. McKenney  *
20*f2425b4eSPaul E. McKenney  * You should have received a copy of the GNU General Public License
21*f2425b4eSPaul E. McKenney  * along with this program; if not, you can access it online at
22*f2425b4eSPaul E. McKenney  * http://www.gnu.org/licenses/gpl-2.0.html.
23*f2425b4eSPaul E. McKenney  *
24*f2425b4eSPaul E. McKenney  * Copyright IBM Corporation, 2017
25*f2425b4eSPaul E. McKenney  *
26*f2425b4eSPaul E. McKenney  * Author: Paul E. McKenney <[email protected]>
27*f2425b4eSPaul E. McKenney  */
28*f2425b4eSPaul E. McKenney 
29*f2425b4eSPaul E. McKenney #ifndef __LINUX_RCU_NODE_TREE_H
30*f2425b4eSPaul E. McKenney #define __LINUX_RCU_NODE_TREE_H
31*f2425b4eSPaul E. McKenney 
32*f2425b4eSPaul E. McKenney /*
33*f2425b4eSPaul E. McKenney  * Define shape of hierarchy based on NR_CPUS, CONFIG_RCU_FANOUT, and
34*f2425b4eSPaul E. McKenney  * CONFIG_RCU_FANOUT_LEAF.
35*f2425b4eSPaul E. McKenney  * In theory, it should be possible to add more levels straightforwardly.
36*f2425b4eSPaul E. McKenney  * In practice, this did work well going from three levels to four.
37*f2425b4eSPaul E. McKenney  * Of course, your mileage may vary.
38*f2425b4eSPaul E. McKenney  */
39*f2425b4eSPaul E. McKenney 
40*f2425b4eSPaul E. McKenney #ifdef CONFIG_RCU_FANOUT
41*f2425b4eSPaul E. McKenney #define RCU_FANOUT CONFIG_RCU_FANOUT
42*f2425b4eSPaul E. McKenney #else /* #ifdef CONFIG_RCU_FANOUT */
43*f2425b4eSPaul E. McKenney # ifdef CONFIG_64BIT
44*f2425b4eSPaul E. McKenney # define RCU_FANOUT 64
45*f2425b4eSPaul E. McKenney # else
46*f2425b4eSPaul E. McKenney # define RCU_FANOUT 32
47*f2425b4eSPaul E. McKenney # endif
48*f2425b4eSPaul E. McKenney #endif /* #else #ifdef CONFIG_RCU_FANOUT */
49*f2425b4eSPaul E. McKenney 
50*f2425b4eSPaul E. McKenney #ifdef CONFIG_RCU_FANOUT_LEAF
51*f2425b4eSPaul E. McKenney #define RCU_FANOUT_LEAF CONFIG_RCU_FANOUT_LEAF
52*f2425b4eSPaul E. McKenney #else /* #ifdef CONFIG_RCU_FANOUT_LEAF */
53*f2425b4eSPaul E. McKenney #define RCU_FANOUT_LEAF 16
54*f2425b4eSPaul E. McKenney #endif /* #else #ifdef CONFIG_RCU_FANOUT_LEAF */
55*f2425b4eSPaul E. McKenney 
56*f2425b4eSPaul E. McKenney #define RCU_FANOUT_1	      (RCU_FANOUT_LEAF)
57*f2425b4eSPaul E. McKenney #define RCU_FANOUT_2	      (RCU_FANOUT_1 * RCU_FANOUT)
58*f2425b4eSPaul E. McKenney #define RCU_FANOUT_3	      (RCU_FANOUT_2 * RCU_FANOUT)
59*f2425b4eSPaul E. McKenney #define RCU_FANOUT_4	      (RCU_FANOUT_3 * RCU_FANOUT)
60*f2425b4eSPaul E. McKenney 
61*f2425b4eSPaul E. McKenney #if NR_CPUS <= RCU_FANOUT_1
62*f2425b4eSPaul E. McKenney #  define RCU_NUM_LVLS	      1
63*f2425b4eSPaul E. McKenney #  define NUM_RCU_LVL_0	      1
64*f2425b4eSPaul E. McKenney #  define NUM_RCU_NODES	      NUM_RCU_LVL_0
65*f2425b4eSPaul E. McKenney #  define NUM_RCU_LVL_INIT    { NUM_RCU_LVL_0 }
66*f2425b4eSPaul E. McKenney #  define RCU_NODE_NAME_INIT  { "rcu_node_0" }
67*f2425b4eSPaul E. McKenney #  define RCU_FQS_NAME_INIT   { "rcu_node_fqs_0" }
68*f2425b4eSPaul E. McKenney #elif NR_CPUS <= RCU_FANOUT_2
69*f2425b4eSPaul E. McKenney #  define RCU_NUM_LVLS	      2
70*f2425b4eSPaul E. McKenney #  define NUM_RCU_LVL_0	      1
71*f2425b4eSPaul E. McKenney #  define NUM_RCU_LVL_1	      DIV_ROUND_UP(NR_CPUS, RCU_FANOUT_1)
72*f2425b4eSPaul E. McKenney #  define NUM_RCU_NODES	      (NUM_RCU_LVL_0 + NUM_RCU_LVL_1)
73*f2425b4eSPaul E. McKenney #  define NUM_RCU_LVL_INIT    { NUM_RCU_LVL_0, NUM_RCU_LVL_1 }
74*f2425b4eSPaul E. McKenney #  define RCU_NODE_NAME_INIT  { "rcu_node_0", "rcu_node_1" }
75*f2425b4eSPaul E. McKenney #  define RCU_FQS_NAME_INIT   { "rcu_node_fqs_0", "rcu_node_fqs_1" }
76*f2425b4eSPaul E. McKenney #elif NR_CPUS <= RCU_FANOUT_3
77*f2425b4eSPaul E. McKenney #  define RCU_NUM_LVLS	      3
78*f2425b4eSPaul E. McKenney #  define NUM_RCU_LVL_0	      1
79*f2425b4eSPaul E. McKenney #  define NUM_RCU_LVL_1	      DIV_ROUND_UP(NR_CPUS, RCU_FANOUT_2)
80*f2425b4eSPaul E. McKenney #  define NUM_RCU_LVL_2	      DIV_ROUND_UP(NR_CPUS, RCU_FANOUT_1)
81*f2425b4eSPaul E. McKenney #  define NUM_RCU_NODES	      (NUM_RCU_LVL_0 + NUM_RCU_LVL_1 + NUM_RCU_LVL_2)
82*f2425b4eSPaul E. McKenney #  define NUM_RCU_LVL_INIT    { NUM_RCU_LVL_0, NUM_RCU_LVL_1, NUM_RCU_LVL_2 }
83*f2425b4eSPaul E. McKenney #  define RCU_NODE_NAME_INIT  { "rcu_node_0", "rcu_node_1", "rcu_node_2" }
84*f2425b4eSPaul E. McKenney #  define RCU_FQS_NAME_INIT   { "rcu_node_fqs_0", "rcu_node_fqs_1", "rcu_node_fqs_2" }
85*f2425b4eSPaul E. McKenney #elif NR_CPUS <= RCU_FANOUT_4
86*f2425b4eSPaul E. McKenney #  define RCU_NUM_LVLS	      4
87*f2425b4eSPaul E. McKenney #  define NUM_RCU_LVL_0	      1
88*f2425b4eSPaul E. McKenney #  define NUM_RCU_LVL_1	      DIV_ROUND_UP(NR_CPUS, RCU_FANOUT_3)
89*f2425b4eSPaul E. McKenney #  define NUM_RCU_LVL_2	      DIV_ROUND_UP(NR_CPUS, RCU_FANOUT_2)
90*f2425b4eSPaul E. McKenney #  define NUM_RCU_LVL_3	      DIV_ROUND_UP(NR_CPUS, RCU_FANOUT_1)
91*f2425b4eSPaul E. McKenney #  define NUM_RCU_NODES	      (NUM_RCU_LVL_0 + NUM_RCU_LVL_1 + NUM_RCU_LVL_2 + NUM_RCU_LVL_3)
92*f2425b4eSPaul E. McKenney #  define NUM_RCU_LVL_INIT    { NUM_RCU_LVL_0, NUM_RCU_LVL_1, NUM_RCU_LVL_2, NUM_RCU_LVL_3 }
93*f2425b4eSPaul E. McKenney #  define RCU_NODE_NAME_INIT  { "rcu_node_0", "rcu_node_1", "rcu_node_2", "rcu_node_3" }
94*f2425b4eSPaul E. McKenney #  define RCU_FQS_NAME_INIT   { "rcu_node_fqs_0", "rcu_node_fqs_1", "rcu_node_fqs_2", "rcu_node_fqs_3" }
95*f2425b4eSPaul E. McKenney #else
96*f2425b4eSPaul E. McKenney # error "CONFIG_RCU_FANOUT insufficient for NR_CPUS"
97*f2425b4eSPaul E. McKenney #endif /* #if (NR_CPUS) <= RCU_FANOUT_1 */
98*f2425b4eSPaul E. McKenney 
99*f2425b4eSPaul E. McKenney extern int rcu_num_lvls;
100*f2425b4eSPaul E. McKenney extern int rcu_num_nodes;
101*f2425b4eSPaul E. McKenney 
102*f2425b4eSPaul E. McKenney #endif /* __LINUX_RCU_NODE_TREE_H */
103