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#include <linux/math.h>
  24
  25/*
  26 * Define shape of hierarchy based on NR_CPUS, CONFIG_RCU_FANOUT, and
  27 * CONFIG_RCU_FANOUT_LEAF.
  28 * In theory, it should be possible to add more levels straightforwardly.
  29 * In practice, this did work well going from three levels to four.
  30 * Of course, your mileage may vary.
  31 */
  32
  33#ifdef CONFIG_RCU_FANOUT
  34#define RCU_FANOUT CONFIG_RCU_FANOUT
  35#else /* #ifdef CONFIG_RCU_FANOUT */
  36# ifdef CONFIG_64BIT
  37# define RCU_FANOUT 64
  38# else
  39# define RCU_FANOUT 32
  40# endif
  41#endif /* #else #ifdef CONFIG_RCU_FANOUT */
  42
  43#ifdef CONFIG_RCU_FANOUT_LEAF
  44#define RCU_FANOUT_LEAF CONFIG_RCU_FANOUT_LEAF
  45#else /* #ifdef CONFIG_RCU_FANOUT_LEAF */
  46#define RCU_FANOUT_LEAF 16
  47#endif /* #else #ifdef CONFIG_RCU_FANOUT_LEAF */
  48
  49#define RCU_FANOUT_1          (RCU_FANOUT_LEAF)
  50#define RCU_FANOUT_2          (RCU_FANOUT_1 * RCU_FANOUT)
  51#define RCU_FANOUT_3          (RCU_FANOUT_2 * RCU_FANOUT)
  52#define RCU_FANOUT_4          (RCU_FANOUT_3 * RCU_FANOUT)
  53
  54#if NR_CPUS <= RCU_FANOUT_1
  55#  define RCU_NUM_LVLS        1
  56#  define NUM_RCU_LVL_0       1
  57#  define NUM_RCU_NODES       NUM_RCU_LVL_0
  58#  define NUM_RCU_LVL_INIT    { NUM_RCU_LVL_0 }
  59#  define RCU_NODE_NAME_INIT  { "rcu_node_0" }
  60#  define RCU_FQS_NAME_INIT   { "rcu_node_fqs_0" }
  61#elif NR_CPUS <= RCU_FANOUT_2
  62#  define RCU_NUM_LVLS        2
  63#  define NUM_RCU_LVL_0       1
  64#  define NUM_RCU_LVL_1       DIV_ROUND_UP(NR_CPUS, RCU_FANOUT_1)
  65#  define NUM_RCU_NODES       (NUM_RCU_LVL_0 + NUM_RCU_LVL_1)
  66#  define NUM_RCU_LVL_INIT    { NUM_RCU_LVL_0, NUM_RCU_LVL_1 }
  67#  define RCU_NODE_NAME_INIT  { "rcu_node_0", "rcu_node_1" }
  68#  define RCU_FQS_NAME_INIT   { "rcu_node_fqs_0", "rcu_node_fqs_1" }
  69#elif NR_CPUS <= RCU_FANOUT_3
  70#  define RCU_NUM_LVLS        3
  71#  define NUM_RCU_LVL_0       1
  72#  define NUM_RCU_LVL_1       DIV_ROUND_UP(NR_CPUS, RCU_FANOUT_2)
  73#  define NUM_RCU_LVL_2       DIV_ROUND_UP(NR_CPUS, RCU_FANOUT_1)
  74#  define NUM_RCU_NODES       (NUM_RCU_LVL_0 + NUM_RCU_LVL_1 + NUM_RCU_LVL_2)
  75#  define NUM_RCU_LVL_INIT    { NUM_RCU_LVL_0, NUM_RCU_LVL_1, NUM_RCU_LVL_2 }
  76#  define RCU_NODE_NAME_INIT  { "rcu_node_0", "rcu_node_1", "rcu_node_2" }
  77#  define RCU_FQS_NAME_INIT   { "rcu_node_fqs_0", "rcu_node_fqs_1", "rcu_node_fqs_2" }
  78#elif NR_CPUS <= RCU_FANOUT_4
  79#  define RCU_NUM_LVLS        4
  80#  define NUM_RCU_LVL_0       1
  81#  define NUM_RCU_LVL_1       DIV_ROUND_UP(NR_CPUS, RCU_FANOUT_3)
  82#  define NUM_RCU_LVL_2       DIV_ROUND_UP(NR_CPUS, RCU_FANOUT_2)
  83#  define NUM_RCU_LVL_3       DIV_ROUND_UP(NR_CPUS, RCU_FANOUT_1)
  84#  define NUM_RCU_NODES       (NUM_RCU_LVL_0 + NUM_RCU_LVL_1 + NUM_RCU_LVL_2 + NUM_RCU_LVL_3)
  85#  define NUM_RCU_LVL_INIT    { NUM_RCU_LVL_0, NUM_RCU_LVL_1, NUM_RCU_LVL_2, NUM_RCU_LVL_3 }
  86#  define RCU_NODE_NAME_INIT  { "rcu_node_0", "rcu_node_1", "rcu_node_2", "rcu_node_3" }
  87#  define RCU_FQS_NAME_INIT   { "rcu_node_fqs_0", "rcu_node_fqs_1", "rcu_node_fqs_2", "rcu_node_fqs_3" }
  88#else
  89# error "CONFIG_RCU_FANOUT insufficient for NR_CPUS"
  90#endif /* #if (NR_CPUS) <= RCU_FANOUT_1 */
  91
  92#endif /* __LINUX_RCU_NODE_TREE_H */
  93