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