1196 lines · 57.3 KB · Text
RawDownload
===================================================A Tour Through TREE_RCU's Data Structures [LWN.net]=================================================== December 18, 2016 This article was contributed by Paul E. McKenney Introduction============ This document describes RCU's major data structures and their relationshipto each other. Data-Structure Relationships============================ RCU is for all intents and purposes a large state machine, and itsdata structures maintain the state in such a way as to allow RCU readersto execute extremely quickly, while also processing the RCU grace periodsrequested by updaters in an efficient and extremely scalable fashion.The efficiency and scalability of RCU updaters is provided primarilyby a combining tree, as shown below: .. kernel-figure:: BigTreeClassicRCU.svg This diagram shows an enclosing ``rcu_state`` structure containing a treeof ``rcu_node`` structures. Each leaf node of the ``rcu_node`` tree has upto 16 ``rcu_data`` structures associated with it, so that there are``NR_CPUS`` number of ``rcu_data`` structures, one for each possible CPU.This structure is adjusted at boot time, if needed, to handle the commoncase where ``nr_cpu_ids`` is much less than ``NR_CPUs``.For example, a number of Linux distributions set ``NR_CPUs=4096``,which results in a three-level ``rcu_node`` tree.If the actual hardware has only 16 CPUs, RCU will adjust itselfat boot time, resulting in an ``rcu_node`` tree with only a single node. The purpose of this combining tree is to allow per-CPU eventssuch as quiescent states, dyntick-idle transitions,and CPU hotplug operations to be processed efficientlyand scalably.Quiescent states are recorded by the per-CPU ``rcu_data`` structures,and other events are recorded by the leaf-level ``rcu_node``structures.All of these events are combined at each level of the tree until finallygrace periods are completed at the tree's root ``rcu_node``structure.A grace period can be completed at the root once every CPU(or, in the case of ``CONFIG_PREEMPT_RCU``, task)has passed through a quiescent state.Once a grace period has completed, record of that fact is propagatedback down the tree. As can be seen from the diagram, on a 64-bit systema two-level tree with 64 leaves can accommodate 1,024 CPUs, with a fanoutof 64 at the root and a fanout of 16 at the leaves. +-----------------------------------------------------------------------+| **Quick Quiz**:                                                       |+-----------------------------------------------------------------------+| Why isn't the fanout at the leaves also 64?                           |+-----------------------------------------------------------------------+| **Answer**:                                                           |+-----------------------------------------------------------------------+| Because there are more types of events that affect the leaf-level     || ``rcu_node`` structures than further up the tree. Therefore, if the   || leaf ``rcu_node`` structures have fanout of 64, the contention on     || these structures' ``->structures`` becomes excessive. Experimentation || on a wide variety of systems has shown that a fanout of 16 works well || for the leaves of the ``rcu_node`` tree.                              ||                                                                       || Of course, further experience with systems having hundreds or         || thousands of CPUs may demonstrate that the fanout for the non-leaf    || ``rcu_node`` structures must also be reduced. Such reduction can be   || easily carried out when and if it proves necessary. In the meantime,  || if you are using such a system and running into contention problems   || on the non-leaf ``rcu_node`` structures, you may use the              || ``CONFIG_RCU_FANOUT`` kernel configuration parameter to reduce the    || non-leaf fanout as needed.                                            ||                                                                       || Kernels built for systems with strong NUMA characteristics might      || also need to adjust ``CONFIG_RCU_FANOUT`` so that the domains of      || the ``rcu_node`` structures align with hardware boundaries.           || However, there has thus far been no need for this.                    |+-----------------------------------------------------------------------+ If your system has more than 1,024 CPUs (or more than 512 CPUs on a32-bit system), then RCU will automatically add more levels to the tree.For example, if you are crazy enough to build a 64-bit system with65,536 CPUs, RCU would configure the ``rcu_node`` tree as follows: .. kernel-figure:: HugeTreeClassicRCU.svg RCU currently permits up to a four-level tree, which on a 64-bit systemaccommodates up to 4,194,304 CPUs, though only a mere 524,288 CPUs for32-bit systems. On the other hand, you can set both``CONFIG_RCU_FANOUT`` and ``CONFIG_RCU_FANOUT_LEAF`` to be as small as2, which would result in a 16-CPU test using a 4-level tree. This can beuseful for testing large-system capabilities on small test machines. This multi-level combining tree allows us to get most of the performanceand scalability benefits of partitioning, even though RCU grace-perioddetection is inherently a global operation. The trick here is that onlythe last CPU to report a quiescent state into a given ``rcu_node``structure need advance to the ``rcu_node`` structure at the next levelup the tree. This means that at the leaf-level ``rcu_node`` structure,only one access out of sixteen will progress up the tree. For theinternal ``rcu_node`` structures, the situation is even more extreme:Only one access out of sixty-four will progress up the tree. Because thevast majority of the CPUs do not progress up the tree, the lockcontention remains roughly constant up the tree. No matter how many CPUsthere are in the system, at most 64 quiescent-state reports per graceperiod will progress all the way to the root ``rcu_node`` structure,thus ensuring that the lock contention on that root ``rcu_node``structure remains acceptably low. In effect, the combining tree acts like a big shock absorber, keepinglock contention under control at all tree levels regardless of the levelof loading on the system. RCU updaters wait for normal grace periods by registering RCU callbacks,either directly via ``call_rcu()`` or indirectly via``synchronize_rcu()`` and friends. RCU callbacks are represented by``rcu_head`` structures, which are queued on ``rcu_data`` structureswhile they are waiting for a grace period to elapse, as shown in thefollowing figure: .. kernel-figure:: BigTreePreemptRCUBHdyntickCB.svg This figure shows how ``TREE_RCU``'s and ``PREEMPT_RCU``'s major datastructures are related. Lesser data structures will be introduced withthe algorithms that make use of them. Note that each of the data structures in the above figure has its ownsynchronization: #. Each ``rcu_state`` structures has a lock and a mutex, and some fields   are protected by the corresponding root ``rcu_node`` structure's lock.#. Each ``rcu_node`` structure has a spinlock.#. The fields in ``rcu_data`` are private to the corresponding CPU,   although a few can be read and written by other CPUs. It is important to note that different data structures can have verydifferent ideas about the state of RCU at any given time. For but oneexample, awareness of the start or end of a given RCU grace periodpropagates slowly through the data structures. This slow propagation isabsolutely necessary for RCU to have good read-side performance. If thisbalkanized implementation seems foreign to you, one useful trick is toconsider each instance of these data structures to be a differentperson, each having the usual slightly different view of reality. The general role of each of these data structures is as follows: #. ``rcu_state``: This structure forms the interconnection between the   ``rcu_node`` and ``rcu_data`` structures, tracks grace periods,   serves as short-term repository for callbacks orphaned by CPU-hotplug   events, maintains ``rcu_barrier()`` state, tracks expedited   grace-period state, and maintains state used to force quiescent   states when grace periods extend too long,#. ``rcu_node``: This structure forms the combining tree that propagates   quiescent-state information from the leaves to the root, and also   propagates grace-period information from the root to the leaves. It   provides local copies of the grace-period state in order to allow   this information to be accessed in a synchronized manner without   suffering the scalability limitations that would otherwise be imposed   by global locking. In ``CONFIG_PREEMPT_RCU`` kernels, it manages the   lists of tasks that have blocked while in their current RCU read-side   critical section. In ``CONFIG_PREEMPT_RCU`` with   ``CONFIG_RCU_BOOST``, it manages the per-\ ``rcu_node``   priority-boosting kernel threads (kthreads) and state. Finally, it   records CPU-hotplug state in order to determine which CPUs should be   ignored during a given grace period.#. ``rcu_data``: This per-CPU structure is the focus of quiescent-state   detection and RCU callback queuing. It also tracks its relationship   to the corresponding leaf ``rcu_node`` structure to allow   more-efficient propagation of quiescent states up the ``rcu_node``   combining tree. Like the ``rcu_node`` structure, it provides a local   copy of the grace-period information to allow for-free synchronized   access to this information from the corresponding CPU. Finally, this   structure records past dyntick-idle state for the corresponding CPU   and also tracks statistics.#. ``rcu_head``: This structure represents RCU callbacks, and is the   only structure allocated and managed by RCU users. The ``rcu_head``   structure is normally embedded within the RCU-protected data   structure. If all you wanted from this article was a general notion of how RCU'sdata structures are related, you are done. Otherwise, each of thefollowing sections give more details on the ``rcu_state``, ``rcu_node``and ``rcu_data`` data structures. The ``rcu_state`` Structure~~~~~~~~~~~~~~~~~~~~~~~~~~~ The ``rcu_state`` structure is the base structure that represents thestate of RCU in the system. This structure forms the interconnectionbetween the ``rcu_node`` and ``rcu_data`` structures, tracks graceperiods, contains the lock used to synchronize with CPU-hotplug events,and maintains state used to force quiescent states when grace periodsextend too long, A few of the ``rcu_state`` structure's fields are discussed, singly andin groups, in the following sections. The more specialized fields arecovered in the discussion of their use. Relationship to rcu_node and rcu_data Structures'''''''''''''''''''''''''''''''''''''''''''''''' This portion of the ``rcu_state`` structure is declared as follows: ::      1   struct rcu_node node[NUM_RCU_NODES];     2   struct rcu_node *level[NUM_RCU_LVLS + 1];     3   struct rcu_data __percpu *rda; +-----------------------------------------------------------------------+| **Quick Quiz**:                                                       |+-----------------------------------------------------------------------+| Wait a minute! You said that the ``rcu_node`` structures formed a     || tree, but they are declared as a flat array! What gives?              |+-----------------------------------------------------------------------+| **Answer**:                                                           |+-----------------------------------------------------------------------+| The tree is laid out in the array. The first node In the array is the || head, the next set of nodes in the array are children of the head     || node, and so on until the last set of nodes in the array are the      || leaves.                                                               || See the following diagrams to see how this works.                     |+-----------------------------------------------------------------------+ The ``rcu_node`` tree is embedded into the ``->node[]`` array as shownin the following figure: .. kernel-figure:: TreeMapping.svg One interesting consequence of this mapping is that a breadth-firsttraversal of the tree is implemented as a simple linear scan of thearray, which is in fact what the ``rcu_for_each_node_breadth_first()``macro does. This macro is used at the beginning and ends of graceperiods. Each entry of the ``->level`` array references the first ``rcu_node``structure on the corresponding level of the tree, for example, as shownbelow: .. kernel-figure:: TreeMappingLevel.svg The zero\ :sup:`th` element of the array references the root``rcu_node`` structure, the first element references the first child ofthe root ``rcu_node``, and finally the second element references thefirst leaf ``rcu_node`` structure. For whatever it is worth, if you draw the tree to be tree-shaped ratherthan array-shaped, it is easy to draw a planar representation: .. kernel-figure:: TreeLevel.svg Finally, the ``->rda`` field references a per-CPU pointer to thecorresponding CPU's ``rcu_data`` structure. All of these fields are constant once initialization is complete, andtherefore need no protection. Grace-Period Tracking''''''''''''''''''''' This portion of the ``rcu_state`` structure is declared as follows: ::      1   unsigned long gp_seq; RCU grace periods are numbered, and the ``->gp_seq`` field contains thecurrent grace-period sequence number. The bottom two bits are the stateof the current grace period, which can be zero for not yet started orone for in progress. In other words, if the bottom two bits of``->gp_seq`` are zero, then RCU is idle. Any other value in the bottomtwo bits indicates that something is broken. This field is protected bythe root ``rcu_node`` structure's ``->lock`` field. There are ``->gp_seq`` fields in the ``rcu_node`` and ``rcu_data``structures as well. The fields in the ``rcu_state`` structure representthe most current value, and those of the other structures are comparedin order to detect the beginnings and ends of grace periods in adistributed fashion. The values flow from ``rcu_state`` to ``rcu_node``(down the tree from the root to the leaves) to ``rcu_data``. +-----------------------------------------------------------------------+| **Quick Quiz**:                                                       |+-----------------------------------------------------------------------+| Given that the root rcu_node structure has a gp_seq field,            || why does RCU maintain a separate gp_seq in the rcu_state structure?   || Why not just use the root rcu_node's gp_seq as the official record    || and update it directly when starting a new grace period?              |+-----------------------------------------------------------------------+| **Answer**:                                                           |+-----------------------------------------------------------------------+| On single-node RCU trees (where the root node is also a leaf),        || updating the root node's gp_seq immediately would create unnecessary  || lock contention. Here's why:                                          ||                                                                       || If we did rcu_seq_start() directly on the root node's gp_seq:         ||                                                                       || 1. All CPUs would immediately see their node's gp_seq from their rdp's||    gp_seq, in rcu_pending(). They would all then invoke the RCU-core. || 2. Which calls note_gp_changes() and try to acquire the node lock.    || 3. But rnp->qsmask isn't initialized yet (happens later in            ||    rcu_gp_init())                                                     || 4. So each CPU would acquire the lock, find it can't determine if it  ||    needs to report quiescent state (no qsmask), update rdp->gp_seq,   ||    and release the lock.                                              || 5. Result: Lots of lock acquisitions with no grace period progress    ||                                                                       || By having a separate rcu_state.gp_seq, we can increment the official  || grace period counter without immediately affecting what CPUs see in   || their nodes. The hierarchical propagation in rcu_gp_init() then       || updates the root node's gp_seq and qsmask together under the same lock|| acquisition, avoiding this useless contention.                        |+-----------------------------------------------------------------------+ Miscellaneous''''''''''''' This portion of the ``rcu_state`` structure is declared as follows: ::      1   unsigned long gp_max;     2   char abbr;     3   char *name; The ``->gp_max`` field tracks the duration of the longest grace periodin jiffies. It is protected by the root ``rcu_node``'s ``->lock``. The ``->name`` and ``->abbr`` fields distinguish between preemptible RCU(“rcu_preempt” and “p”) and non-preemptible RCU (“rcu_sched” and “s”).These fields are used for diagnostic and tracing purposes. The ``rcu_node`` Structure~~~~~~~~~~~~~~~~~~~~~~~~~~ The ``rcu_node`` structures form the combining tree that propagatesquiescent-state information from the leaves to the root and also thatpropagates grace-period information from the root down to the leaves.They provides local copies of the grace-period state in order to allowthis information to be accessed in a synchronized manner withoutsuffering the scalability limitations that would otherwise be imposed byglobal locking. In ``CONFIG_PREEMPT_RCU`` kernels, they manage the listsof tasks that have blocked while in their current RCU read-side criticalsection. In ``CONFIG_PREEMPT_RCU`` with ``CONFIG_RCU_BOOST``, theymanage the per-\ ``rcu_node`` priority-boosting kernel threads(kthreads) and state. Finally, they record CPU-hotplug state in order todetermine which CPUs should be ignored during a given grace period. The ``rcu_node`` structure's fields are discussed, singly and in groups,in the following sections. Connection to Combining Tree'''''''''''''''''''''''''''' This portion of the ``rcu_node`` structure is declared as follows: ::      1   struct rcu_node *parent;     2   u8 level;     3   u8 grpnum;     4   unsigned long grpmask;     5   int grplo;     6   int grphi; The ``->parent`` pointer references the ``rcu_node`` one level up in thetree, and is ``NULL`` for the root ``rcu_node``. The RCU implementationmakes heavy use of this field to push quiescent states up the tree. The``->level`` field gives the level in the tree, with the root being atlevel zero, its children at level one, and so on. The ``->grpnum`` fieldgives this node's position within the children of its parent, so thisnumber can range between 0 and 31 on 32-bit systems and between 0 and 63on 64-bit systems. The ``->level`` and ``->grpnum`` fields are used onlyduring initialization and for tracing. The ``->grpmask`` field is thebitmask counterpart of ``->grpnum``, and therefore always has exactlyone bit set. This mask is used to clear the bit corresponding to this``rcu_node`` structure in its parent's bitmasks, which are describedlater. Finally, the ``->grplo`` and ``->grphi`` fields contain thelowest and highest numbered CPU served by this ``rcu_node`` structure,respectively. All of these fields are constant, and thus do not require anysynchronization. Synchronization''''''''''''''' This field of the ``rcu_node`` structure is declared as follows: ::      1   raw_spinlock_t lock; This field is used to protect the remaining fields in this structure,unless otherwise stated. That said, all of the fields in this structurecan be accessed without locking for tracing purposes. Yes, this canresult in confusing traces, but better some tracing confusion than to beheisenbugged out of existence. .. _grace-period-tracking-1: Grace-Period Tracking''''''''''''''''''''' This portion of the ``rcu_node`` structure is declared as follows: ::      1   unsigned long gp_seq;     2   unsigned long gp_seq_needed; The ``rcu_node`` structures' ``->gp_seq`` fields are the counterparts ofthe field of the same name in the ``rcu_state`` structure. They each maylag up to one step behind their ``rcu_state`` counterpart. If the bottomtwo bits of a given ``rcu_node`` structure's ``->gp_seq`` field is zero,then this ``rcu_node`` structure believes that RCU is idle. The ``>gp_seq`` field of each ``rcu_node`` structure is updated at thebeginning and the end of each grace period. The ``->gp_seq_needed`` fields record the furthest-in-the-future graceperiod request seen by the corresponding ``rcu_node`` structure. Therequest is considered fulfilled when the value of the ``->gp_seq`` fieldequals or exceeds that of the ``->gp_seq_needed`` field. +-----------------------------------------------------------------------+| **Quick Quiz**:                                                       |+-----------------------------------------------------------------------+| Suppose that this ``rcu_node`` structure doesn't see a request for a  || very long time. Won't wrapping of the ``->gp_seq`` field cause        || problems?                                                             |+-----------------------------------------------------------------------+| **Answer**:                                                           |+-----------------------------------------------------------------------+| No, because if the ``->gp_seq_needed`` field lags behind the          || ``->gp_seq`` field, the ``->gp_seq_needed`` field will be updated at  || the end of the grace period. Modulo-arithmetic comparisons therefore  || will always get the correct answer, even with wrapping.               |+-----------------------------------------------------------------------+ Quiescent-State Tracking'''''''''''''''''''''''' These fields manage the propagation of quiescent states up the combiningtree. This portion of the ``rcu_node`` structure has fields as follows: ::      1   unsigned long qsmask;     2   unsigned long expmask;     3   unsigned long qsmaskinit;     4   unsigned long expmaskinit; The ``->qsmask`` field tracks which of this ``rcu_node`` structure'schildren still need to report quiescent states for the current normalgrace period. Such children will have a value of 1 in theircorresponding bit. Note that the leaf ``rcu_node`` structures should bethought of as having ``rcu_data`` structures as their children.Similarly, the ``->expmask`` field tracks which of this ``rcu_node``structure's children still need to report quiescent states for thecurrent expedited grace period. An expedited grace period has the sameconceptual properties as a normal grace period, but the expeditedimplementation accepts extreme CPU overhead to obtain much lowergrace-period latency, for example, consuming a few tens of microsecondsworth of CPU time to reduce grace-period duration from milliseconds totens of microseconds. The ``->qsmaskinit`` field tracks which of this``rcu_node`` structure's children cover for at least one online CPU.This mask is used to initialize ``->qsmask``, and ``->expmaskinit`` isused to initialize ``->expmask`` and the beginning of the normal andexpedited grace periods, respectively. +-----------------------------------------------------------------------+| **Quick Quiz**:                                                       |+-----------------------------------------------------------------------+| Why are these bitmasks protected by locking? Come on, haven't you     || heard of atomic instructions???                                       |+-----------------------------------------------------------------------+| **Answer**:                                                           |+-----------------------------------------------------------------------+| Lockless grace-period computation! Such a tantalizing possibility!    || But consider the following sequence of events:                        ||                                                                       || #. CPU 0 has been in dyntick-idle mode for quite some time. When it   ||    wakes up, it notices that the current RCU grace period needs it to ||    report in, so it sets a flag where the scheduling clock interrupt  ||    will find it.                                                      || #. Meanwhile, CPU 1 is running ``force_quiescent_state()``, and       ||    notices that CPU 0 has been in dyntick idle mode, which qualifies  ||    as an extended quiescent state.                                    || #. CPU 0's scheduling clock interrupt fires in the middle of an RCU   ||    read-side critical section, and notices that the RCU core needs    |

Lines 1–500 of 1196.