Figure
shows the code for the rcu_init_levelspread() function, which controls
the fanout, or the number of children per parent,
in the rcu_node hierarchy.
There are two versions of this function, one shown on lines 2-9 that
enforces the exact fanout (specified by CONFIG_RCU_FANOUT),
and the other on lines 11-25 that determines the number of child nodes
based indirectly on the specified fanout, but then balances the tree.
The CONFIG_RCU_FANOUT_EXACT kernel parameter selects which version
to use for a given kernel build.
The exact-fanout version simply assigns all of the elements of the specified rcu_state structure's ->levelspread array to the CONFIG_RCU_FANOUT kernel parameter, as shown by the loop on lines 7 and 8.
The hierarchy-balancing version on lines 11-24 uses a pair of local variables ccur and cprv which track the number of rcu_node structures on the current and previous levels, respectively. This function works from the leaf level up the hierarchy, so cprv is initialized by line 18 to NR_CPUS, which corresponds to the number of rcu_data structures that feed into the leaf level. Lines 19-23 iterate from the leaf to the root. Within this loop, line 20 picking up the number of rcu_node structures for the current level into ccur. Line 21 then rounds up the ratio of the number of nodes on the previous (lower) level (be they rcu_node or rcu_data) to the number of rcu_node structures on the current level, placing the result in the specified rcu_state structure's ->levelspread array. Line 22 then sets up for the next pass through the loop.
After a call to either function, the ->levelspread array contains the number of children for each level of the rcu_node hierarchy.
Paul E. McKenney 2011-12-16