linux/include/linux/rcu_node_tree.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0+ */
   2/*
   3 * RCU node combining tree definitions.  These are used to compute
   4 * global attributes while avoiding common-case global contention.  A key
   5 * property that these computations rely on is a tournament-style approach
   6 * where only one of the tasks contending a lower level in the tree need
   7 * advance to the next higher level.  If properly configured, this allows
   8 * unlimited scalability while maintaining a constant level of contention
   9 * on the root node.
  10 *
  11 * This seemingly RCU-private file must be available to SRCU users
  12 * because the size of the TREE SRCU srcu_struct structure depends
  13 * on these definitions.
  14 *
  15 * Copyright IBM Corporation, 2017
  16 *
  17 * Author: Paul E. McKenney <paulmck@linux.ibm.com>
  18 */
  19
  20#ifndef __LINUX_RCU_NODE_TREE_H
  21#define __LINUX_RCU_NODE_TREE_H
  22
  23/*
  24 * Define shape of hierarchy based on NR_CPUS, CONFIG_RCU_FANOUT, and
  25 * CONFIG_RCU_FANOUT_LEAF.
  26 * In theory, it should be possible to add more levels straightforwardly.
  27 * In practice, this did work well going from three levels to four.
  28 * Of course, your mileage may vary.
  29 */
  30
  31#ifdef CONFIG_RCU_FANOUT
  32#define RCU_FANOUT CONFIG_RCU_FANOUT
  33#else /* #ifdef CONFIG_RCU_FANOUT */
  34# ifdef CONFIG_64BIT
  35# define RCU_FANOUT 64
  36# else
  37# define RCU_FANOUT 32
  38# endif
  39#endif /* #else #ifdef CONFIG_RCU_FANOUT */
  40
  41#ifdef CONFIG_RCU_FANOUT_LEAF
  42#define RCU_FANOUT_LEAF CONFIG_RCU_FANOUT_LEAF
  43#else /* #ifdef CONFIG_RCU_FANOUT_LEAF */
  44#define RCU_FANOUT_LEAF 16
  45#endif /* #else #ifdef CONFIG_RCU_FANOUT_LEAF */
  46
  47#define RCU_FANOUT_1          (RCU_FANOUT_LEAF)
  48#define RCU_FANOUT_2          (RCU_FANOUT_1 * RCU_FANOUT)
  49#define RCU_FANOUT_3          (RCU_FANOUT_2 * RCU_FANOUT)
  50#define RCU_FANOUT_4          (RCU_FANOUT_3 * RCU_FANOUT)
  51
  52#if NR_CPUS <= RCU_FANOUT_1
  53#  define RCU_NUM_LVLS        1
  54#  define NUM_RCU_LVL_0       1
  55#  define NUM_RCU_NODES       NUM_RCU_LVL_0
  56#  define NUM_RCU_LVL_INIT    { NUM_RCU_LVL_0 }
  57#  define RCU_NODE_NAME_INIT  { "rcu_node_0" }
  58#  define RCU_FQS_NAME_INIT   { "rcu_node_fqs_0" }
  59#elif NR_CPUS <= RCU_FANOUT_2
  60#  define RCU_NUM_LVLS        2
  61#  define NUM_RCU_LVL_0       1
  62#  define NUM_RCU_LVL_1       DIV_ROUND_UP(NR_CPUS, RCU_FANOUT_1)
  63#  define NUM_RCU_NODES       (NUM_RCU_LVL_0 + NUM_RCU_LVL_1)
  64#  define NUM_RCU_LVL_INIT    { NUM_RCU_LVL_0, NUM_RCU_LVL_1 }
  65#  define RCU_NODE_NAME_INIT  { "rcu_node_0", "rcu_node_1" }
  66#  define RCU_FQS_NAME_INIT   { "rcu_node_fqs_0", "rcu_node_fqs_1" }
  67#elif NR_CPUS <= RCU_FANOUT_3
  68#  define RCU_NUM_LVLS        3
  69#  define NUM_RCU_LVL_0       1
  70#  define NUM_RCU_LVL_1       DIV_ROUND_UP(NR_CPUS, RCU_FANOUT_2)
  71#  define NUM_RCU_LVL_2       DIV_ROUND_UP(NR_CPUS, RCU_FANOUT_1)
  72#  define NUM_RCU_NODES       (NUM_RCU_LVL_0 + NUM_RCU_LVL_1 + NUM_RCU_LVL_2)
  73#  define NUM_RCU_LVL_INIT    { NUM_RCU_LVL_0, NUM_RCU_LVL_1, NUM_RCU_LVL_2 }
  74#  define RCU_NODE_NAME_INIT  { "rcu_node_0", "rcu_node_1", "rcu_node_2" }
  75#  define RCU_FQS_NAME_INIT   { "rcu_node_fqs_0", "rcu_node_fqs_1", "rcu_node_fqs_2" }
  76#elif NR_CPUS <= RCU_FANOUT_4
  77#  define RCU_NUM_LVLS        4
  78#  define NUM_RCU_LVL_0       1
  79#  define NUM_RCU_LVL_1       DIV_ROUND_UP(NR_CPUS, RCU_FANOUT_3)
  80#  define NUM_RCU_LVL_2       DIV_ROUND_UP(NR_CPUS, RCU_FANOUT_2)
  81#  define NUM_RCU_LVL_3       DIV_ROUND_UP(NR_CPUS, RCU_FANOUT_1)
  82#  define NUM_RCU_NODES       (NUM_RCU_LVL_0 + NUM_RCU_LVL_1 + NUM_RCU_LVL_2 + NUM_RCU_LVL_3)
  83#  define NUM_RCU_LVL_INIT    { NUM_RCU_LVL_0, NUM_RCU_LVL_1, NUM_RCU_LVL_2, NUM_RCU_LVL_3 }
  84#  define RCU_NODE_NAME_INIT  { "rcu_node_0", "rcu_node_1", "rcu_node_2", "rcu_node_3" }
  85#  define RCU_FQS_NAME_INIT   { "rcu_node_fqs_0", "rcu_node_fqs_1", "rcu_node_fqs_2", "rcu_node_fqs_3" }
  86#else
  87# error "CONFIG_RCU_FANOUT insufficient for NR_CPUS"
  88#endif /* #if (NR_CPUS) <= RCU_FANOUT_1 */
  89
  90#endif /* __LINUX_RCU_NODE_TREE_H */
  91