2761 lines
133 KiB
ReStructuredText
2761 lines
133 KiB
ReStructuredText
|
=================================
|
|||
|
A Tour Through RCU's Requirements
|
|||
|
=================================
|
|||
|
|
|||
|
Copyright IBM Corporation, 2015
|
|||
|
|
|||
|
Author: Paul E. McKenney
|
|||
|
|
|||
|
The initial version of this document appeared in the
|
|||
|
`LWN <https://lwn.net/>`_ on those articles:
|
|||
|
`part 1 <https://lwn.net/Articles/652156/>`_,
|
|||
|
`part 2 <https://lwn.net/Articles/652677/>`_, and
|
|||
|
`part 3 <https://lwn.net/Articles/653326/>`_.
|
|||
|
|
|||
|
Introduction
|
|||
|
------------
|
|||
|
|
|||
|
Read-copy update (RCU) is a synchronization mechanism that is often used
|
|||
|
as a replacement for reader-writer locking. RCU is unusual in that
|
|||
|
updaters do not block readers, which means that RCU's read-side
|
|||
|
primitives can be exceedingly fast and scalable. In addition, updaters
|
|||
|
can make useful forward progress concurrently with readers. However, all
|
|||
|
this concurrency between RCU readers and updaters does raise the
|
|||
|
question of exactly what RCU readers are doing, which in turn raises the
|
|||
|
question of exactly what RCU's requirements are.
|
|||
|
|
|||
|
This document therefore summarizes RCU's requirements, and can be
|
|||
|
thought of as an informal, high-level specification for RCU. It is
|
|||
|
important to understand that RCU's specification is primarily empirical
|
|||
|
in nature; in fact, I learned about many of these requirements the hard
|
|||
|
way. This situation might cause some consternation, however, not only
|
|||
|
has this learning process been a lot of fun, but it has also been a
|
|||
|
great privilege to work with so many people willing to apply
|
|||
|
technologies in interesting new ways.
|
|||
|
|
|||
|
All that aside, here are the categories of currently known RCU
|
|||
|
requirements:
|
|||
|
|
|||
|
#. `Fundamental Requirements`_
|
|||
|
#. `Fundamental Non-Requirements`_
|
|||
|
#. `Parallelism Facts of Life`_
|
|||
|
#. `Quality-of-Implementation Requirements`_
|
|||
|
#. `Linux Kernel Complications`_
|
|||
|
#. `Software-Engineering Requirements`_
|
|||
|
#. `Other RCU Flavors`_
|
|||
|
#. `Possible Future Changes`_
|
|||
|
|
|||
|
This is followed by a summary_, however, the answers to
|
|||
|
each quick quiz immediately follows the quiz. Select the big white space
|
|||
|
with your mouse to see the answer.
|
|||
|
|
|||
|
Fundamental Requirements
|
|||
|
------------------------
|
|||
|
|
|||
|
RCU's fundamental requirements are the closest thing RCU has to hard
|
|||
|
mathematical requirements. These are:
|
|||
|
|
|||
|
#. `Grace-Period Guarantee`_
|
|||
|
#. `Publish/Subscribe Guarantee`_
|
|||
|
#. `Memory-Barrier Guarantees`_
|
|||
|
#. `RCU Primitives Guaranteed to Execute Unconditionally`_
|
|||
|
#. `Guaranteed Read-to-Write Upgrade`_
|
|||
|
|
|||
|
Grace-Period Guarantee
|
|||
|
~~~~~~~~~~~~~~~~~~~~~~
|
|||
|
|
|||
|
RCU's grace-period guarantee is unusual in being premeditated: Jack
|
|||
|
Slingwine and I had this guarantee firmly in mind when we started work
|
|||
|
on RCU (then called “rclock”) in the early 1990s. That said, the past
|
|||
|
two decades of experience with RCU have produced a much more detailed
|
|||
|
understanding of this guarantee.
|
|||
|
|
|||
|
RCU's grace-period guarantee allows updaters to wait for the completion
|
|||
|
of all pre-existing RCU read-side critical sections. An RCU read-side
|
|||
|
critical section begins with the marker rcu_read_lock() and ends
|
|||
|
with the marker rcu_read_unlock(). These markers may be nested, and
|
|||
|
RCU treats a nested set as one big RCU read-side critical section.
|
|||
|
Production-quality implementations of rcu_read_lock() and
|
|||
|
rcu_read_unlock() are extremely lightweight, and in fact have
|
|||
|
exactly zero overhead in Linux kernels built for production use with
|
|||
|
``CONFIG_PREEMPTION=n``.
|
|||
|
|
|||
|
This guarantee allows ordering to be enforced with extremely low
|
|||
|
overhead to readers, for example:
|
|||
|
|
|||
|
::
|
|||
|
|
|||
|
1 int x, y;
|
|||
|
2
|
|||
|
3 void thread0(void)
|
|||
|
4 {
|
|||
|
5 rcu_read_lock();
|
|||
|
6 r1 = READ_ONCE(x);
|
|||
|
7 r2 = READ_ONCE(y);
|
|||
|
8 rcu_read_unlock();
|
|||
|
9 }
|
|||
|
10
|
|||
|
11 void thread1(void)
|
|||
|
12 {
|
|||
|
13 WRITE_ONCE(x, 1);
|
|||
|
14 synchronize_rcu();
|
|||
|
15 WRITE_ONCE(y, 1);
|
|||
|
16 }
|
|||
|
|
|||
|
Because the synchronize_rcu() on line 14 waits for all pre-existing
|
|||
|
readers, any instance of thread0() that loads a value of zero from
|
|||
|
``x`` must complete before thread1() stores to ``y``, so that
|
|||
|
instance must also load a value of zero from ``y``. Similarly, any
|
|||
|
instance of thread0() that loads a value of one from ``y`` must have
|
|||
|
started after the synchronize_rcu() started, and must therefore also
|
|||
|
load a value of one from ``x``. Therefore, the outcome:
|
|||
|
|
|||
|
::
|
|||
|
|
|||
|
(r1 == 0 && r2 == 1)
|
|||
|
|
|||
|
cannot happen.
|
|||
|
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
| **Quick Quiz**: |
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
| Wait a minute! You said that updaters can make useful forward |
|
|||
|
| progress concurrently with readers, but pre-existing readers will |
|
|||
|
| block synchronize_rcu()!!! |
|
|||
|
| Just who are you trying to fool??? |
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
| **Answer**: |
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
| First, if updaters do not wish to be blocked by readers, they can use |
|
|||
|
| call_rcu() or kfree_rcu(), which will be discussed later. |
|
|||
|
| Second, even when using synchronize_rcu(), the other update-side |
|
|||
|
| code does run concurrently with readers, whether pre-existing or not. |
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
|
|||
|
This scenario resembles one of the first uses of RCU in
|
|||
|
`DYNIX/ptx <https://en.wikipedia.org/wiki/DYNIX>`__, which managed a
|
|||
|
distributed lock manager's transition into a state suitable for handling
|
|||
|
recovery from node failure, more or less as follows:
|
|||
|
|
|||
|
::
|
|||
|
|
|||
|
1 #define STATE_NORMAL 0
|
|||
|
2 #define STATE_WANT_RECOVERY 1
|
|||
|
3 #define STATE_RECOVERING 2
|
|||
|
4 #define STATE_WANT_NORMAL 3
|
|||
|
5
|
|||
|
6 int state = STATE_NORMAL;
|
|||
|
7
|
|||
|
8 void do_something_dlm(void)
|
|||
|
9 {
|
|||
|
10 int state_snap;
|
|||
|
11
|
|||
|
12 rcu_read_lock();
|
|||
|
13 state_snap = READ_ONCE(state);
|
|||
|
14 if (state_snap == STATE_NORMAL)
|
|||
|
15 do_something();
|
|||
|
16 else
|
|||
|
17 do_something_carefully();
|
|||
|
18 rcu_read_unlock();
|
|||
|
19 }
|
|||
|
20
|
|||
|
21 void start_recovery(void)
|
|||
|
22 {
|
|||
|
23 WRITE_ONCE(state, STATE_WANT_RECOVERY);
|
|||
|
24 synchronize_rcu();
|
|||
|
25 WRITE_ONCE(state, STATE_RECOVERING);
|
|||
|
26 recovery();
|
|||
|
27 WRITE_ONCE(state, STATE_WANT_NORMAL);
|
|||
|
28 synchronize_rcu();
|
|||
|
29 WRITE_ONCE(state, STATE_NORMAL);
|
|||
|
30 }
|
|||
|
|
|||
|
The RCU read-side critical section in do_something_dlm() works with
|
|||
|
the synchronize_rcu() in start_recovery() to guarantee that
|
|||
|
do_something() never runs concurrently with recovery(), but with
|
|||
|
little or no synchronization overhead in do_something_dlm().
|
|||
|
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
| **Quick Quiz**: |
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
| Why is the synchronize_rcu() on line 28 needed? |
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
| **Answer**: |
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
| Without that extra grace period, memory reordering could result in |
|
|||
|
| do_something_dlm() executing do_something() concurrently with |
|
|||
|
| the last bits of recovery(). |
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
|
|||
|
In order to avoid fatal problems such as deadlocks, an RCU read-side
|
|||
|
critical section must not contain calls to synchronize_rcu().
|
|||
|
Similarly, an RCU read-side critical section must not contain anything
|
|||
|
that waits, directly or indirectly, on completion of an invocation of
|
|||
|
synchronize_rcu().
|
|||
|
|
|||
|
Although RCU's grace-period guarantee is useful in and of itself, with
|
|||
|
`quite a few use cases <https://lwn.net/Articles/573497/>`__, it would
|
|||
|
be good to be able to use RCU to coordinate read-side access to linked
|
|||
|
data structures. For this, the grace-period guarantee is not sufficient,
|
|||
|
as can be seen in function add_gp_buggy() below. We will look at the
|
|||
|
reader's code later, but in the meantime, just think of the reader as
|
|||
|
locklessly picking up the ``gp`` pointer, and, if the value loaded is
|
|||
|
non-\ ``NULL``, locklessly accessing the ``->a`` and ``->b`` fields.
|
|||
|
|
|||
|
::
|
|||
|
|
|||
|
1 bool add_gp_buggy(int a, int b)
|
|||
|
2 {
|
|||
|
3 p = kmalloc(sizeof(*p), GFP_KERNEL);
|
|||
|
4 if (!p)
|
|||
|
5 return -ENOMEM;
|
|||
|
6 spin_lock(&gp_lock);
|
|||
|
7 if (rcu_access_pointer(gp)) {
|
|||
|
8 spin_unlock(&gp_lock);
|
|||
|
9 return false;
|
|||
|
10 }
|
|||
|
11 p->a = a;
|
|||
|
12 p->b = a;
|
|||
|
13 gp = p; /* ORDERING BUG */
|
|||
|
14 spin_unlock(&gp_lock);
|
|||
|
15 return true;
|
|||
|
16 }
|
|||
|
|
|||
|
The problem is that both the compiler and weakly ordered CPUs are within
|
|||
|
their rights to reorder this code as follows:
|
|||
|
|
|||
|
::
|
|||
|
|
|||
|
1 bool add_gp_buggy_optimized(int a, int b)
|
|||
|
2 {
|
|||
|
3 p = kmalloc(sizeof(*p), GFP_KERNEL);
|
|||
|
4 if (!p)
|
|||
|
5 return -ENOMEM;
|
|||
|
6 spin_lock(&gp_lock);
|
|||
|
7 if (rcu_access_pointer(gp)) {
|
|||
|
8 spin_unlock(&gp_lock);
|
|||
|
9 return false;
|
|||
|
10 }
|
|||
|
11 gp = p; /* ORDERING BUG */
|
|||
|
12 p->a = a;
|
|||
|
13 p->b = a;
|
|||
|
14 spin_unlock(&gp_lock);
|
|||
|
15 return true;
|
|||
|
16 }
|
|||
|
|
|||
|
If an RCU reader fetches ``gp`` just after ``add_gp_buggy_optimized``
|
|||
|
executes line 11, it will see garbage in the ``->a`` and ``->b`` fields.
|
|||
|
And this is but one of many ways in which compiler and hardware
|
|||
|
optimizations could cause trouble. Therefore, we clearly need some way
|
|||
|
to prevent the compiler and the CPU from reordering in this manner,
|
|||
|
which brings us to the publish-subscribe guarantee discussed in the next
|
|||
|
section.
|
|||
|
|
|||
|
Publish/Subscribe Guarantee
|
|||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|||
|
|
|||
|
RCU's publish-subscribe guarantee allows data to be inserted into a
|
|||
|
linked data structure without disrupting RCU readers. The updater uses
|
|||
|
rcu_assign_pointer() to insert the new data, and readers use
|
|||
|
rcu_dereference() to access data, whether new or old. The following
|
|||
|
shows an example of insertion:
|
|||
|
|
|||
|
::
|
|||
|
|
|||
|
1 bool add_gp(int a, int b)
|
|||
|
2 {
|
|||
|
3 p = kmalloc(sizeof(*p), GFP_KERNEL);
|
|||
|
4 if (!p)
|
|||
|
5 return -ENOMEM;
|
|||
|
6 spin_lock(&gp_lock);
|
|||
|
7 if (rcu_access_pointer(gp)) {
|
|||
|
8 spin_unlock(&gp_lock);
|
|||
|
9 return false;
|
|||
|
10 }
|
|||
|
11 p->a = a;
|
|||
|
12 p->b = a;
|
|||
|
13 rcu_assign_pointer(gp, p);
|
|||
|
14 spin_unlock(&gp_lock);
|
|||
|
15 return true;
|
|||
|
16 }
|
|||
|
|
|||
|
The rcu_assign_pointer() on line 13 is conceptually equivalent to a
|
|||
|
simple assignment statement, but also guarantees that its assignment
|
|||
|
will happen after the two assignments in lines 11 and 12, similar to the
|
|||
|
C11 ``memory_order_release`` store operation. It also prevents any
|
|||
|
number of “interesting” compiler optimizations, for example, the use of
|
|||
|
``gp`` as a scratch location immediately preceding the assignment.
|
|||
|
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
| **Quick Quiz**: |
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
| But rcu_assign_pointer() does nothing to prevent the two |
|
|||
|
| assignments to ``p->a`` and ``p->b`` from being reordered. Can't that |
|
|||
|
| also cause problems? |
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
| **Answer**: |
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
| No, it cannot. The readers cannot see either of these two fields |
|
|||
|
| until the assignment to ``gp``, by which time both fields are fully |
|
|||
|
| initialized. So reordering the assignments to ``p->a`` and ``p->b`` |
|
|||
|
| cannot possibly cause any problems. |
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
|
|||
|
It is tempting to assume that the reader need not do anything special to
|
|||
|
control its accesses to the RCU-protected data, as shown in
|
|||
|
do_something_gp_buggy() below:
|
|||
|
|
|||
|
::
|
|||
|
|
|||
|
1 bool do_something_gp_buggy(void)
|
|||
|
2 {
|
|||
|
3 rcu_read_lock();
|
|||
|
4 p = gp; /* OPTIMIZATIONS GALORE!!! */
|
|||
|
5 if (p) {
|
|||
|
6 do_something(p->a, p->b);
|
|||
|
7 rcu_read_unlock();
|
|||
|
8 return true;
|
|||
|
9 }
|
|||
|
10 rcu_read_unlock();
|
|||
|
11 return false;
|
|||
|
12 }
|
|||
|
|
|||
|
However, this temptation must be resisted because there are a
|
|||
|
surprisingly large number of ways that the compiler (or weak ordering
|
|||
|
CPUs like the DEC Alpha) can trip this code up. For but one example, if
|
|||
|
the compiler were short of registers, it might choose to refetch from
|
|||
|
``gp`` rather than keeping a separate copy in ``p`` as follows:
|
|||
|
|
|||
|
::
|
|||
|
|
|||
|
1 bool do_something_gp_buggy_optimized(void)
|
|||
|
2 {
|
|||
|
3 rcu_read_lock();
|
|||
|
4 if (gp) { /* OPTIMIZATIONS GALORE!!! */
|
|||
|
5 do_something(gp->a, gp->b);
|
|||
|
6 rcu_read_unlock();
|
|||
|
7 return true;
|
|||
|
8 }
|
|||
|
9 rcu_read_unlock();
|
|||
|
10 return false;
|
|||
|
11 }
|
|||
|
|
|||
|
If this function ran concurrently with a series of updates that replaced
|
|||
|
the current structure with a new one, the fetches of ``gp->a`` and
|
|||
|
``gp->b`` might well come from two different structures, which could
|
|||
|
cause serious confusion. To prevent this (and much else besides),
|
|||
|
do_something_gp() uses rcu_dereference() to fetch from ``gp``:
|
|||
|
|
|||
|
::
|
|||
|
|
|||
|
1 bool do_something_gp(void)
|
|||
|
2 {
|
|||
|
3 rcu_read_lock();
|
|||
|
4 p = rcu_dereference(gp);
|
|||
|
5 if (p) {
|
|||
|
6 do_something(p->a, p->b);
|
|||
|
7 rcu_read_unlock();
|
|||
|
8 return true;
|
|||
|
9 }
|
|||
|
10 rcu_read_unlock();
|
|||
|
11 return false;
|
|||
|
12 }
|
|||
|
|
|||
|
The rcu_dereference() uses volatile casts and (for DEC Alpha) memory
|
|||
|
barriers in the Linux kernel. Should a |high-quality implementation of
|
|||
|
C11 memory_order_consume [PDF]|_
|
|||
|
ever appear, then rcu_dereference() could be implemented as a
|
|||
|
``memory_order_consume`` load. Regardless of the exact implementation, a
|
|||
|
pointer fetched by rcu_dereference() may not be used outside of the
|
|||
|
outermost RCU read-side critical section containing that
|
|||
|
rcu_dereference(), unless protection of the corresponding data
|
|||
|
element has been passed from RCU to some other synchronization
|
|||
|
mechanism, most commonly locking or reference counting
|
|||
|
(see ../../rcuref.rst).
|
|||
|
|
|||
|
.. |high-quality implementation of C11 memory_order_consume [PDF]| replace:: high-quality implementation of C11 ``memory_order_consume`` [PDF]
|
|||
|
.. _high-quality implementation of C11 memory_order_consume [PDF]: http://www.rdrop.com/users/paulmck/RCU/consume.2015.07.13a.pdf
|
|||
|
|
|||
|
In short, updaters use rcu_assign_pointer() and readers use
|
|||
|
rcu_dereference(), and these two RCU API elements work together to
|
|||
|
ensure that readers have a consistent view of newly added data elements.
|
|||
|
|
|||
|
Of course, it is also necessary to remove elements from RCU-protected
|
|||
|
data structures, for example, using the following process:
|
|||
|
|
|||
|
#. Remove the data element from the enclosing structure.
|
|||
|
#. Wait for all pre-existing RCU read-side critical sections to complete
|
|||
|
(because only pre-existing readers can possibly have a reference to
|
|||
|
the newly removed data element).
|
|||
|
#. At this point, only the updater has a reference to the newly removed
|
|||
|
data element, so it can safely reclaim the data element, for example,
|
|||
|
by passing it to kfree().
|
|||
|
|
|||
|
This process is implemented by remove_gp_synchronous():
|
|||
|
|
|||
|
::
|
|||
|
|
|||
|
1 bool remove_gp_synchronous(void)
|
|||
|
2 {
|
|||
|
3 struct foo *p;
|
|||
|
4
|
|||
|
5 spin_lock(&gp_lock);
|
|||
|
6 p = rcu_access_pointer(gp);
|
|||
|
7 if (!p) {
|
|||
|
8 spin_unlock(&gp_lock);
|
|||
|
9 return false;
|
|||
|
10 }
|
|||
|
11 rcu_assign_pointer(gp, NULL);
|
|||
|
12 spin_unlock(&gp_lock);
|
|||
|
13 synchronize_rcu();
|
|||
|
14 kfree(p);
|
|||
|
15 return true;
|
|||
|
16 }
|
|||
|
|
|||
|
This function is straightforward, with line 13 waiting for a grace
|
|||
|
period before line 14 frees the old data element. This waiting ensures
|
|||
|
that readers will reach line 7 of do_something_gp() before the data
|
|||
|
element referenced by ``p`` is freed. The rcu_access_pointer() on
|
|||
|
line 6 is similar to rcu_dereference(), except that:
|
|||
|
|
|||
|
#. The value returned by rcu_access_pointer() cannot be
|
|||
|
dereferenced. If you want to access the value pointed to as well as
|
|||
|
the pointer itself, use rcu_dereference() instead of
|
|||
|
rcu_access_pointer().
|
|||
|
#. The call to rcu_access_pointer() need not be protected. In
|
|||
|
contrast, rcu_dereference() must either be within an RCU
|
|||
|
read-side critical section or in a code segment where the pointer
|
|||
|
cannot change, for example, in code protected by the corresponding
|
|||
|
update-side lock.
|
|||
|
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
| **Quick Quiz**: |
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
| Without the rcu_dereference() or the rcu_access_pointer(), |
|
|||
|
| what destructive optimizations might the compiler make use of? |
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
| **Answer**: |
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
| Let's start with what happens to do_something_gp() if it fails to |
|
|||
|
| use rcu_dereference(). It could reuse a value formerly fetched |
|
|||
|
| from this same pointer. It could also fetch the pointer from ``gp`` |
|
|||
|
| in a byte-at-a-time manner, resulting in *load tearing*, in turn |
|
|||
|
| resulting a bytewise mash-up of two distinct pointer values. It might |
|
|||
|
| even use value-speculation optimizations, where it makes a wrong |
|
|||
|
| guess, but by the time it gets around to checking the value, an |
|
|||
|
| update has changed the pointer to match the wrong guess. Too bad |
|
|||
|
| about any dereferences that returned pre-initialization garbage in |
|
|||
|
| the meantime! |
|
|||
|
| For remove_gp_synchronous(), as long as all modifications to |
|
|||
|
| ``gp`` are carried out while holding ``gp_lock``, the above |
|
|||
|
| optimizations are harmless. However, ``sparse`` will complain if you |
|
|||
|
| define ``gp`` with ``__rcu`` and then access it without using either |
|
|||
|
| rcu_access_pointer() or rcu_dereference(). |
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
|
|||
|
In short, RCU's publish-subscribe guarantee is provided by the
|
|||
|
combination of rcu_assign_pointer() and rcu_dereference(). This
|
|||
|
guarantee allows data elements to be safely added to RCU-protected
|
|||
|
linked data structures without disrupting RCU readers. This guarantee
|
|||
|
can be used in combination with the grace-period guarantee to also allow
|
|||
|
data elements to be removed from RCU-protected linked data structures,
|
|||
|
again without disrupting RCU readers.
|
|||
|
|
|||
|
This guarantee was only partially premeditated. DYNIX/ptx used an
|
|||
|
explicit memory barrier for publication, but had nothing resembling
|
|||
|
rcu_dereference() for subscription, nor did it have anything
|
|||
|
resembling the dependency-ordering barrier that was later subsumed
|
|||
|
into rcu_dereference() and later still into READ_ONCE(). The
|
|||
|
need for these operations made itself known quite suddenly at a
|
|||
|
late-1990s meeting with the DEC Alpha architects, back in the days when
|
|||
|
DEC was still a free-standing company. It took the Alpha architects a
|
|||
|
good hour to convince me that any sort of barrier would ever be needed,
|
|||
|
and it then took me a good *two* hours to convince them that their
|
|||
|
documentation did not make this point clear. More recent work with the C
|
|||
|
and C++ standards committees have provided much education on tricks and
|
|||
|
traps from the compiler. In short, compilers were much less tricky in
|
|||
|
the early 1990s, but in 2015, don't even think about omitting
|
|||
|
rcu_dereference()!
|
|||
|
|
|||
|
Memory-Barrier Guarantees
|
|||
|
~~~~~~~~~~~~~~~~~~~~~~~~~
|
|||
|
|
|||
|
The previous section's simple linked-data-structure scenario clearly
|
|||
|
demonstrates the need for RCU's stringent memory-ordering guarantees on
|
|||
|
systems with more than one CPU:
|
|||
|
|
|||
|
#. Each CPU that has an RCU read-side critical section that begins
|
|||
|
before synchronize_rcu() starts is guaranteed to execute a full
|
|||
|
memory barrier between the time that the RCU read-side critical
|
|||
|
section ends and the time that synchronize_rcu() returns. Without
|
|||
|
this guarantee, a pre-existing RCU read-side critical section might
|
|||
|
hold a reference to the newly removed ``struct foo`` after the
|
|||
|
kfree() on line 14 of remove_gp_synchronous().
|
|||
|
#. Each CPU that has an RCU read-side critical section that ends after
|
|||
|
synchronize_rcu() returns is guaranteed to execute a full memory
|
|||
|
barrier between the time that synchronize_rcu() begins and the
|
|||
|
time that the RCU read-side critical section begins. Without this
|
|||
|
guarantee, a later RCU read-side critical section running after the
|
|||
|
kfree() on line 14 of remove_gp_synchronous() might later run
|
|||
|
do_something_gp() and find the newly deleted ``struct foo``.
|
|||
|
#. If the task invoking synchronize_rcu() remains on a given CPU,
|
|||
|
then that CPU is guaranteed to execute a full memory barrier sometime
|
|||
|
during the execution of synchronize_rcu(). This guarantee ensures
|
|||
|
that the kfree() on line 14 of remove_gp_synchronous() really
|
|||
|
does execute after the removal on line 11.
|
|||
|
#. If the task invoking synchronize_rcu() migrates among a group of
|
|||
|
CPUs during that invocation, then each of the CPUs in that group is
|
|||
|
guaranteed to execute a full memory barrier sometime during the
|
|||
|
execution of synchronize_rcu(). This guarantee also ensures that
|
|||
|
the kfree() on line 14 of remove_gp_synchronous() really does
|
|||
|
execute after the removal on line 11, but also in the case where the
|
|||
|
thread executing the synchronize_rcu() migrates in the meantime.
|
|||
|
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
| **Quick Quiz**: |
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
| Given that multiple CPUs can start RCU read-side critical sections at |
|
|||
|
| any time without any ordering whatsoever, how can RCU possibly tell |
|
|||
|
| whether or not a given RCU read-side critical section starts before a |
|
|||
|
| given instance of synchronize_rcu()? |
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
| **Answer**: |
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
| If RCU cannot tell whether or not a given RCU read-side critical |
|
|||
|
| section starts before a given instance of synchronize_rcu(), then |
|
|||
|
| it must assume that the RCU read-side critical section started first. |
|
|||
|
| In other words, a given instance of synchronize_rcu() can avoid |
|
|||
|
| waiting on a given RCU read-side critical section only if it can |
|
|||
|
| prove that synchronize_rcu() started first. |
|
|||
|
| A related question is “When rcu_read_lock() doesn't generate any |
|
|||
|
| code, why does it matter how it relates to a grace period?” The |
|
|||
|
| answer is that it is not the relationship of rcu_read_lock() |
|
|||
|
| itself that is important, but rather the relationship of the code |
|
|||
|
| within the enclosed RCU read-side critical section to the code |
|
|||
|
| preceding and following the grace period. If we take this viewpoint, |
|
|||
|
| then a given RCU read-side critical section begins before a given |
|
|||
|
| grace period when some access preceding the grace period observes the |
|
|||
|
| effect of some access within the critical section, in which case none |
|
|||
|
| of the accesses within the critical section may observe the effects |
|
|||
|
| of any access following the grace period. |
|
|||
|
| |
|
|||
|
| As of late 2016, mathematical models of RCU take this viewpoint, for |
|
|||
|
| example, see slides 62 and 63 of the `2016 LinuxCon |
|
|||
|
| EU <http://www2.rdrop.com/users/paulmck/scalability/paper/LinuxMM.201 |
|
|||
|
| 6.10.04c.LCE.pdf>`__ |
|
|||
|
| presentation. |
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
| **Quick Quiz**: |
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
| The first and second guarantees require unbelievably strict ordering! |
|
|||
|
| Are all these memory barriers *really* required? |
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
| **Answer**: |
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
| Yes, they really are required. To see why the first guarantee is |
|
|||
|
| required, consider the following sequence of events: |
|
|||
|
| |
|
|||
|
| #. CPU 1: rcu_read_lock() |
|
|||
|
| #. CPU 1: ``q = rcu_dereference(gp); /* Very likely to return p. */`` |
|
|||
|
| #. CPU 0: ``list_del_rcu(p);`` |
|
|||
|
| #. CPU 0: synchronize_rcu() starts. |
|
|||
|
| #. CPU 1: ``do_something_with(q->a);`` |
|
|||
|
| ``/* No smp_mb(), so might happen after kfree(). */`` |
|
|||
|
| #. CPU 1: rcu_read_unlock() |
|
|||
|
| #. CPU 0: synchronize_rcu() returns. |
|
|||
|
| #. CPU 0: ``kfree(p);`` |
|
|||
|
| |
|
|||
|
| Therefore, there absolutely must be a full memory barrier between the |
|
|||
|
| end of the RCU read-side critical section and the end of the grace |
|
|||
|
| period. |
|
|||
|
| |
|
|||
|
| The sequence of events demonstrating the necessity of the second rule |
|
|||
|
| is roughly similar: |
|
|||
|
| |
|
|||
|
| #. CPU 0: ``list_del_rcu(p);`` |
|
|||
|
| #. CPU 0: synchronize_rcu() starts. |
|
|||
|
| #. CPU 1: rcu_read_lock() |
|
|||
|
| #. CPU 1: ``q = rcu_dereference(gp);`` |
|
|||
|
| ``/* Might return p if no memory barrier. */`` |
|
|||
|
| #. CPU 0: synchronize_rcu() returns. |
|
|||
|
| #. CPU 0: ``kfree(p);`` |
|
|||
|
| #. CPU 1: ``do_something_with(q->a); /* Boom!!! */`` |
|
|||
|
| #. CPU 1: rcu_read_unlock() |
|
|||
|
| |
|
|||
|
| And similarly, without a memory barrier between the beginning of the |
|
|||
|
| grace period and the beginning of the RCU read-side critical section, |
|
|||
|
| CPU 1 might end up accessing the freelist. |
|
|||
|
| |
|
|||
|
| The “as if” rule of course applies, so that any implementation that |
|
|||
|
| acts as if the appropriate memory barriers were in place is a correct |
|
|||
|
| implementation. That said, it is much easier to fool yourself into |
|
|||
|
| believing that you have adhered to the as-if rule than it is to |
|
|||
|
| actually adhere to it! |
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
| **Quick Quiz**: |
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
| You claim that rcu_read_lock() and rcu_read_unlock() generate |
|
|||
|
| absolutely no code in some kernel builds. This means that the |
|
|||
|
| compiler might arbitrarily rearrange consecutive RCU read-side |
|
|||
|
| critical sections. Given such rearrangement, if a given RCU read-side |
|
|||
|
| critical section is done, how can you be sure that all prior RCU |
|
|||
|
| read-side critical sections are done? Won't the compiler |
|
|||
|
| rearrangements make that impossible to determine? |
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
| **Answer**: |
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
| In cases where rcu_read_lock() and rcu_read_unlock() generate |
|
|||
|
| absolutely no code, RCU infers quiescent states only at special |
|
|||
|
| locations, for example, within the scheduler. Because calls to |
|
|||
|
| schedule() had better prevent calling-code accesses to shared |
|
|||
|
| variables from being rearranged across the call to schedule(), if |
|
|||
|
| RCU detects the end of a given RCU read-side critical section, it |
|
|||
|
| will necessarily detect the end of all prior RCU read-side critical |
|
|||
|
| sections, no matter how aggressively the compiler scrambles the code. |
|
|||
|
| Again, this all assumes that the compiler cannot scramble code across |
|
|||
|
| calls to the scheduler, out of interrupt handlers, into the idle |
|
|||
|
| loop, into user-mode code, and so on. But if your kernel build allows |
|
|||
|
| that sort of scrambling, you have broken far more than just RCU! |
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
|
|||
|
Note that these memory-barrier requirements do not replace the
|
|||
|
fundamental RCU requirement that a grace period wait for all
|
|||
|
pre-existing readers. On the contrary, the memory barriers called out in
|
|||
|
this section must operate in such a way as to *enforce* this fundamental
|
|||
|
requirement. Of course, different implementations enforce this
|
|||
|
requirement in different ways, but enforce it they must.
|
|||
|
|
|||
|
RCU Primitives Guaranteed to Execute Unconditionally
|
|||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|||
|
|
|||
|
The common-case RCU primitives are unconditional. They are invoked, they
|
|||
|
do their job, and they return, with no possibility of error, and no need
|
|||
|
to retry. This is a key RCU design philosophy.
|
|||
|
|
|||
|
However, this philosophy is pragmatic rather than pigheaded. If someone
|
|||
|
comes up with a good justification for a particular conditional RCU
|
|||
|
primitive, it might well be implemented and added. After all, this
|
|||
|
guarantee was reverse-engineered, not premeditated. The unconditional
|
|||
|
nature of the RCU primitives was initially an accident of
|
|||
|
implementation, and later experience with synchronization primitives
|
|||
|
with conditional primitives caused me to elevate this accident to a
|
|||
|
guarantee. Therefore, the justification for adding a conditional
|
|||
|
primitive to RCU would need to be based on detailed and compelling use
|
|||
|
cases.
|
|||
|
|
|||
|
Guaranteed Read-to-Write Upgrade
|
|||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|||
|
|
|||
|
As far as RCU is concerned, it is always possible to carry out an update
|
|||
|
within an RCU read-side critical section. For example, that RCU
|
|||
|
read-side critical section might search for a given data element, and
|
|||
|
then might acquire the update-side spinlock in order to update that
|
|||
|
element, all while remaining in that RCU read-side critical section. Of
|
|||
|
course, it is necessary to exit the RCU read-side critical section
|
|||
|
before invoking synchronize_rcu(), however, this inconvenience can
|
|||
|
be avoided through use of the call_rcu() and kfree_rcu() API
|
|||
|
members described later in this document.
|
|||
|
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
| **Quick Quiz**: |
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
| But how does the upgrade-to-write operation exclude other readers? |
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
| **Answer**: |
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
| It doesn't, just like normal RCU updates, which also do not exclude |
|
|||
|
| RCU readers. |
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
|
|||
|
This guarantee allows lookup code to be shared between read-side and
|
|||
|
update-side code, and was premeditated, appearing in the earliest
|
|||
|
DYNIX/ptx RCU documentation.
|
|||
|
|
|||
|
Fundamental Non-Requirements
|
|||
|
----------------------------
|
|||
|
|
|||
|
RCU provides extremely lightweight readers, and its read-side
|
|||
|
guarantees, though quite useful, are correspondingly lightweight. It is
|
|||
|
therefore all too easy to assume that RCU is guaranteeing more than it
|
|||
|
really is. Of course, the list of things that RCU does not guarantee is
|
|||
|
infinitely long, however, the following sections list a few
|
|||
|
non-guarantees that have caused confusion. Except where otherwise noted,
|
|||
|
these non-guarantees were premeditated.
|
|||
|
|
|||
|
#. `Readers Impose Minimal Ordering`_
|
|||
|
#. `Readers Do Not Exclude Updaters`_
|
|||
|
#. `Updaters Only Wait For Old Readers`_
|
|||
|
#. `Grace Periods Don't Partition Read-Side Critical Sections`_
|
|||
|
#. `Read-Side Critical Sections Don't Partition Grace Periods`_
|
|||
|
|
|||
|
Readers Impose Minimal Ordering
|
|||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|||
|
|
|||
|
Reader-side markers such as rcu_read_lock() and
|
|||
|
rcu_read_unlock() provide absolutely no ordering guarantees except
|
|||
|
through their interaction with the grace-period APIs such as
|
|||
|
synchronize_rcu(). To see this, consider the following pair of
|
|||
|
threads:
|
|||
|
|
|||
|
::
|
|||
|
|
|||
|
1 void thread0(void)
|
|||
|
2 {
|
|||
|
3 rcu_read_lock();
|
|||
|
4 WRITE_ONCE(x, 1);
|
|||
|
5 rcu_read_unlock();
|
|||
|
6 rcu_read_lock();
|
|||
|
7 WRITE_ONCE(y, 1);
|
|||
|
8 rcu_read_unlock();
|
|||
|
9 }
|
|||
|
10
|
|||
|
11 void thread1(void)
|
|||
|
12 {
|
|||
|
13 rcu_read_lock();
|
|||
|
14 r1 = READ_ONCE(y);
|
|||
|
15 rcu_read_unlock();
|
|||
|
16 rcu_read_lock();
|
|||
|
17 r2 = READ_ONCE(x);
|
|||
|
18 rcu_read_unlock();
|
|||
|
19 }
|
|||
|
|
|||
|
After thread0() and thread1() execute concurrently, it is quite
|
|||
|
possible to have
|
|||
|
|
|||
|
::
|
|||
|
|
|||
|
(r1 == 1 && r2 == 0)
|
|||
|
|
|||
|
(that is, ``y`` appears to have been assigned before ``x``), which would
|
|||
|
not be possible if rcu_read_lock() and rcu_read_unlock() had
|
|||
|
much in the way of ordering properties. But they do not, so the CPU is
|
|||
|
within its rights to do significant reordering. This is by design: Any
|
|||
|
significant ordering constraints would slow down these fast-path APIs.
|
|||
|
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
| **Quick Quiz**: |
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
| Can't the compiler also reorder this code? |
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
| **Answer**: |
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
| No, the volatile casts in READ_ONCE() and WRITE_ONCE() |
|
|||
|
| prevent the compiler from reordering in this particular case. |
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
|
|||
|
Readers Do Not Exclude Updaters
|
|||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|||
|
|
|||
|
Neither rcu_read_lock() nor rcu_read_unlock() exclude updates.
|
|||
|
All they do is to prevent grace periods from ending. The following
|
|||
|
example illustrates this:
|
|||
|
|
|||
|
::
|
|||
|
|
|||
|
1 void thread0(void)
|
|||
|
2 {
|
|||
|
3 rcu_read_lock();
|
|||
|
4 r1 = READ_ONCE(y);
|
|||
|
5 if (r1) {
|
|||
|
6 do_something_with_nonzero_x();
|
|||
|
7 r2 = READ_ONCE(x);
|
|||
|
8 WARN_ON(!r2); /* BUG!!! */
|
|||
|
9 }
|
|||
|
10 rcu_read_unlock();
|
|||
|
11 }
|
|||
|
12
|
|||
|
13 void thread1(void)
|
|||
|
14 {
|
|||
|
15 spin_lock(&my_lock);
|
|||
|
16 WRITE_ONCE(x, 1);
|
|||
|
17 WRITE_ONCE(y, 1);
|
|||
|
18 spin_unlock(&my_lock);
|
|||
|
19 }
|
|||
|
|
|||
|
If the thread0() function's rcu_read_lock() excluded the
|
|||
|
thread1() function's update, the WARN_ON() could never fire. But
|
|||
|
the fact is that rcu_read_lock() does not exclude much of anything
|
|||
|
aside from subsequent grace periods, of which thread1() has none, so
|
|||
|
the WARN_ON() can and does fire.
|
|||
|
|
|||
|
Updaters Only Wait For Old Readers
|
|||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|||
|
|
|||
|
It might be tempting to assume that after synchronize_rcu()
|
|||
|
completes, there are no readers executing. This temptation must be
|
|||
|
avoided because new readers can start immediately after
|
|||
|
synchronize_rcu() starts, and synchronize_rcu() is under no
|
|||
|
obligation to wait for these new readers.
|
|||
|
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
| **Quick Quiz**: |
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
| Suppose that synchronize_rcu() did wait until *all* readers had |
|
|||
|
| completed instead of waiting only on pre-existing readers. For how |
|
|||
|
| long would the updater be able to rely on there being no readers? |
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
| **Answer**: |
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
| For no time at all. Even if synchronize_rcu() were to wait until |
|
|||
|
| all readers had completed, a new reader might start immediately after |
|
|||
|
| synchronize_rcu() completed. Therefore, the code following |
|
|||
|
| synchronize_rcu() can *never* rely on there being no readers. |
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
|
|||
|
Grace Periods Don't Partition Read-Side Critical Sections
|
|||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|||
|
|
|||
|
It is tempting to assume that if any part of one RCU read-side critical
|
|||
|
section precedes a given grace period, and if any part of another RCU
|
|||
|
read-side critical section follows that same grace period, then all of
|
|||
|
the first RCU read-side critical section must precede all of the second.
|
|||
|
However, this just isn't the case: A single grace period does not
|
|||
|
partition the set of RCU read-side critical sections. An example of this
|
|||
|
situation can be illustrated as follows, where ``x``, ``y``, and ``z``
|
|||
|
are initially all zero:
|
|||
|
|
|||
|
::
|
|||
|
|
|||
|
1 void thread0(void)
|
|||
|
2 {
|
|||
|
3 rcu_read_lock();
|
|||
|
4 WRITE_ONCE(a, 1);
|
|||
|
5 WRITE_ONCE(b, 1);
|
|||
|
6 rcu_read_unlock();
|
|||
|
7 }
|
|||
|
8
|
|||
|
9 void thread1(void)
|
|||
|
10 {
|
|||
|
11 r1 = READ_ONCE(a);
|
|||
|
12 synchronize_rcu();
|
|||
|
13 WRITE_ONCE(c, 1);
|
|||
|
14 }
|
|||
|
15
|
|||
|
16 void thread2(void)
|
|||
|
17 {
|
|||
|
18 rcu_read_lock();
|
|||
|
19 r2 = READ_ONCE(b);
|
|||
|
20 r3 = READ_ONCE(c);
|
|||
|
21 rcu_read_unlock();
|
|||
|
22 }
|
|||
|
|
|||
|
It turns out that the outcome:
|
|||
|
|
|||
|
::
|
|||
|
|
|||
|
(r1 == 1 && r2 == 0 && r3 == 1)
|
|||
|
|
|||
|
is entirely possible. The following figure show how this can happen,
|
|||
|
with each circled ``QS`` indicating the point at which RCU recorded a
|
|||
|
*quiescent state* for each thread, that is, a state in which RCU knows
|
|||
|
that the thread cannot be in the midst of an RCU read-side critical
|
|||
|
section that started before the current grace period:
|
|||
|
|
|||
|
.. kernel-figure:: GPpartitionReaders1.svg
|
|||
|
|
|||
|
If it is necessary to partition RCU read-side critical sections in this
|
|||
|
manner, it is necessary to use two grace periods, where the first grace
|
|||
|
period is known to end before the second grace period starts:
|
|||
|
|
|||
|
::
|
|||
|
|
|||
|
1 void thread0(void)
|
|||
|
2 {
|
|||
|
3 rcu_read_lock();
|
|||
|
4 WRITE_ONCE(a, 1);
|
|||
|
5 WRITE_ONCE(b, 1);
|
|||
|
6 rcu_read_unlock();
|
|||
|
7 }
|
|||
|
8
|
|||
|
9 void thread1(void)
|
|||
|
10 {
|
|||
|
11 r1 = READ_ONCE(a);
|
|||
|
12 synchronize_rcu();
|
|||
|
13 WRITE_ONCE(c, 1);
|
|||
|
14 }
|
|||
|
15
|
|||
|
16 void thread2(void)
|
|||
|
17 {
|
|||
|
18 r2 = READ_ONCE(c);
|
|||
|
19 synchronize_rcu();
|
|||
|
20 WRITE_ONCE(d, 1);
|
|||
|
21 }
|
|||
|
22
|
|||
|
23 void thread3(void)
|
|||
|
24 {
|
|||
|
25 rcu_read_lock();
|
|||
|
26 r3 = READ_ONCE(b);
|
|||
|
27 r4 = READ_ONCE(d);
|
|||
|
28 rcu_read_unlock();
|
|||
|
29 }
|
|||
|
|
|||
|
Here, if ``(r1 == 1)``, then thread0()'s write to ``b`` must happen
|
|||
|
before the end of thread1()'s grace period. If in addition
|
|||
|
``(r4 == 1)``, then thread3()'s read from ``b`` must happen after
|
|||
|
the beginning of thread2()'s grace period. If it is also the case
|
|||
|
that ``(r2 == 1)``, then the end of thread1()'s grace period must
|
|||
|
precede the beginning of thread2()'s grace period. This mean that
|
|||
|
the two RCU read-side critical sections cannot overlap, guaranteeing
|
|||
|
that ``(r3 == 1)``. As a result, the outcome:
|
|||
|
|
|||
|
::
|
|||
|
|
|||
|
(r1 == 1 && r2 == 1 && r3 == 0 && r4 == 1)
|
|||
|
|
|||
|
cannot happen.
|
|||
|
|
|||
|
This non-requirement was also non-premeditated, but became apparent when
|
|||
|
studying RCU's interaction with memory ordering.
|
|||
|
|
|||
|
Read-Side Critical Sections Don't Partition Grace Periods
|
|||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|||
|
|
|||
|
It is also tempting to assume that if an RCU read-side critical section
|
|||
|
happens between a pair of grace periods, then those grace periods cannot
|
|||
|
overlap. However, this temptation leads nowhere good, as can be
|
|||
|
illustrated by the following, with all variables initially zero:
|
|||
|
|
|||
|
::
|
|||
|
|
|||
|
1 void thread0(void)
|
|||
|
2 {
|
|||
|
3 rcu_read_lock();
|
|||
|
4 WRITE_ONCE(a, 1);
|
|||
|
5 WRITE_ONCE(b, 1);
|
|||
|
6 rcu_read_unlock();
|
|||
|
7 }
|
|||
|
8
|
|||
|
9 void thread1(void)
|
|||
|
10 {
|
|||
|
11 r1 = READ_ONCE(a);
|
|||
|
12 synchronize_rcu();
|
|||
|
13 WRITE_ONCE(c, 1);
|
|||
|
14 }
|
|||
|
15
|
|||
|
16 void thread2(void)
|
|||
|
17 {
|
|||
|
18 rcu_read_lock();
|
|||
|
19 WRITE_ONCE(d, 1);
|
|||
|
20 r2 = READ_ONCE(c);
|
|||
|
21 rcu_read_unlock();
|
|||
|
22 }
|
|||
|
23
|
|||
|
24 void thread3(void)
|
|||
|
25 {
|
|||
|
26 r3 = READ_ONCE(d);
|
|||
|
27 synchronize_rcu();
|
|||
|
28 WRITE_ONCE(e, 1);
|
|||
|
29 }
|
|||
|
30
|
|||
|
31 void thread4(void)
|
|||
|
32 {
|
|||
|
33 rcu_read_lock();
|
|||
|
34 r4 = READ_ONCE(b);
|
|||
|
35 r5 = READ_ONCE(e);
|
|||
|
36 rcu_read_unlock();
|
|||
|
37 }
|
|||
|
|
|||
|
In this case, the outcome:
|
|||
|
|
|||
|
::
|
|||
|
|
|||
|
(r1 == 1 && r2 == 1 && r3 == 1 && r4 == 0 && r5 == 1)
|
|||
|
|
|||
|
is entirely possible, as illustrated below:
|
|||
|
|
|||
|
.. kernel-figure:: ReadersPartitionGP1.svg
|
|||
|
|
|||
|
Again, an RCU read-side critical section can overlap almost all of a
|
|||
|
given grace period, just so long as it does not overlap the entire grace
|
|||
|
period. As a result, an RCU read-side critical section cannot partition
|
|||
|
a pair of RCU grace periods.
|
|||
|
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
| **Quick Quiz**: |
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
| How long a sequence of grace periods, each separated by an RCU |
|
|||
|
| read-side critical section, would be required to partition the RCU |
|
|||
|
| read-side critical sections at the beginning and end of the chain? |
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
| **Answer**: |
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
| In theory, an infinite number. In practice, an unknown number that is |
|
|||
|
| sensitive to both implementation details and timing considerations. |
|
|||
|
| Therefore, even in practice, RCU users must abide by the theoretical |
|
|||
|
| rather than the practical answer. |
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
|
|||
|
Parallelism Facts of Life
|
|||
|
-------------------------
|
|||
|
|
|||
|
These parallelism facts of life are by no means specific to RCU, but the
|
|||
|
RCU implementation must abide by them. They therefore bear repeating:
|
|||
|
|
|||
|
#. Any CPU or task may be delayed at any time, and any attempts to avoid
|
|||
|
these delays by disabling preemption, interrupts, or whatever are
|
|||
|
completely futile. This is most obvious in preemptible user-level
|
|||
|
environments and in virtualized environments (where a given guest
|
|||
|
OS's VCPUs can be preempted at any time by the underlying
|
|||
|
hypervisor), but can also happen in bare-metal environments due to
|
|||
|
ECC errors, NMIs, and other hardware events. Although a delay of more
|
|||
|
than about 20 seconds can result in splats, the RCU implementation is
|
|||
|
obligated to use algorithms that can tolerate extremely long delays,
|
|||
|
but where “extremely long” is not long enough to allow wrap-around
|
|||
|
when incrementing a 64-bit counter.
|
|||
|
#. Both the compiler and the CPU can reorder memory accesses. Where it
|
|||
|
matters, RCU must use compiler directives and memory-barrier
|
|||
|
instructions to preserve ordering.
|
|||
|
#. Conflicting writes to memory locations in any given cache line will
|
|||
|
result in expensive cache misses. Greater numbers of concurrent
|
|||
|
writes and more-frequent concurrent writes will result in more
|
|||
|
dramatic slowdowns. RCU is therefore obligated to use algorithms that
|
|||
|
have sufficient locality to avoid significant performance and
|
|||
|
scalability problems.
|
|||
|
#. As a rough rule of thumb, only one CPU's worth of processing may be
|
|||
|
carried out under the protection of any given exclusive lock. RCU
|
|||
|
must therefore use scalable locking designs.
|
|||
|
#. Counters are finite, especially on 32-bit systems. RCU's use of
|
|||
|
counters must therefore tolerate counter wrap, or be designed such
|
|||
|
that counter wrap would take way more time than a single system is
|
|||
|
likely to run. An uptime of ten years is quite possible, a runtime of
|
|||
|
a century much less so. As an example of the latter, RCU's
|
|||
|
dyntick-idle nesting counter allows 54 bits for interrupt nesting
|
|||
|
level (this counter is 64 bits even on a 32-bit system). Overflowing
|
|||
|
this counter requires 2\ :sup:`54` half-interrupts on a given CPU
|
|||
|
without that CPU ever going idle. If a half-interrupt happened every
|
|||
|
microsecond, it would take 570 years of runtime to overflow this
|
|||
|
counter, which is currently believed to be an acceptably long time.
|
|||
|
#. Linux systems can have thousands of CPUs running a single Linux
|
|||
|
kernel in a single shared-memory environment. RCU must therefore pay
|
|||
|
close attention to high-end scalability.
|
|||
|
|
|||
|
This last parallelism fact of life means that RCU must pay special
|
|||
|
attention to the preceding facts of life. The idea that Linux might
|
|||
|
scale to systems with thousands of CPUs would have been met with some
|
|||
|
skepticism in the 1990s, but these requirements would have otherwise
|
|||
|
have been unsurprising, even in the early 1990s.
|
|||
|
|
|||
|
Quality-of-Implementation Requirements
|
|||
|
--------------------------------------
|
|||
|
|
|||
|
These sections list quality-of-implementation requirements. Although an
|
|||
|
RCU implementation that ignores these requirements could still be used,
|
|||
|
it would likely be subject to limitations that would make it
|
|||
|
inappropriate for industrial-strength production use. Classes of
|
|||
|
quality-of-implementation requirements are as follows:
|
|||
|
|
|||
|
#. `Specialization`_
|
|||
|
#. `Performance and Scalability`_
|
|||
|
#. `Forward Progress`_
|
|||
|
#. `Composability`_
|
|||
|
#. `Corner Cases`_
|
|||
|
|
|||
|
These classes is covered in the following sections.
|
|||
|
|
|||
|
Specialization
|
|||
|
~~~~~~~~~~~~~~
|
|||
|
|
|||
|
RCU is and always has been intended primarily for read-mostly
|
|||
|
situations, which means that RCU's read-side primitives are optimized,
|
|||
|
often at the expense of its update-side primitives. Experience thus far
|
|||
|
is captured by the following list of situations:
|
|||
|
|
|||
|
#. Read-mostly data, where stale and inconsistent data is not a problem:
|
|||
|
RCU works great!
|
|||
|
#. Read-mostly data, where data must be consistent: RCU works well.
|
|||
|
#. Read-write data, where data must be consistent: RCU *might* work OK.
|
|||
|
Or not.
|
|||
|
#. Write-mostly data, where data must be consistent: RCU is very
|
|||
|
unlikely to be the right tool for the job, with the following
|
|||
|
exceptions, where RCU can provide:
|
|||
|
|
|||
|
a. Existence guarantees for update-friendly mechanisms.
|
|||
|
b. Wait-free read-side primitives for real-time use.
|
|||
|
|
|||
|
This focus on read-mostly situations means that RCU must interoperate
|
|||
|
with other synchronization primitives. For example, the add_gp() and
|
|||
|
remove_gp_synchronous() examples discussed earlier use RCU to
|
|||
|
protect readers and locking to coordinate updaters. However, the need
|
|||
|
extends much farther, requiring that a variety of synchronization
|
|||
|
primitives be legal within RCU read-side critical sections, including
|
|||
|
spinlocks, sequence locks, atomic operations, reference counters, and
|
|||
|
memory barriers.
|
|||
|
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
| **Quick Quiz**: |
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
| What about sleeping locks? |
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
| **Answer**: |
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
| These are forbidden within Linux-kernel RCU read-side critical |
|
|||
|
| sections because it is not legal to place a quiescent state (in this |
|
|||
|
| case, voluntary context switch) within an RCU read-side critical |
|
|||
|
| section. However, sleeping locks may be used within userspace RCU |
|
|||
|
| read-side critical sections, and also within Linux-kernel sleepable |
|
|||
|
| RCU `(SRCU) <Sleepable RCU_>`__ read-side critical sections. In |
|
|||
|
| addition, the -rt patchset turns spinlocks into a sleeping locks so |
|
|||
|
| that the corresponding critical sections can be preempted, which also |
|
|||
|
| means that these sleeplockified spinlocks (but not other sleeping |
|
|||
|
| locks!) may be acquire within -rt-Linux-kernel RCU read-side critical |
|
|||
|
| sections. |
|
|||
|
| Note that it *is* legal for a normal RCU read-side critical section |
|
|||
|
| to conditionally acquire a sleeping locks (as in |
|
|||
|
| mutex_trylock()), but only as long as it does not loop |
|
|||
|
| indefinitely attempting to conditionally acquire that sleeping locks. |
|
|||
|
| The key point is that things like mutex_trylock() either return |
|
|||
|
| with the mutex held, or return an error indication if the mutex was |
|
|||
|
| not immediately available. Either way, mutex_trylock() returns |
|
|||
|
| immediately without sleeping. |
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
|
|||
|
It often comes as a surprise that many algorithms do not require a
|
|||
|
consistent view of data, but many can function in that mode, with
|
|||
|
network routing being the poster child. Internet routing algorithms take
|
|||
|
significant time to propagate updates, so that by the time an update
|
|||
|
arrives at a given system, that system has been sending network traffic
|
|||
|
the wrong way for a considerable length of time. Having a few threads
|
|||
|
continue to send traffic the wrong way for a few more milliseconds is
|
|||
|
clearly not a problem: In the worst case, TCP retransmissions will
|
|||
|
eventually get the data where it needs to go. In general, when tracking
|
|||
|
the state of the universe outside of the computer, some level of
|
|||
|
inconsistency must be tolerated due to speed-of-light delays if nothing
|
|||
|
else.
|
|||
|
|
|||
|
Furthermore, uncertainty about external state is inherent in many cases.
|
|||
|
For example, a pair of veterinarians might use heartbeat to determine
|
|||
|
whether or not a given cat was alive. But how long should they wait
|
|||
|
after the last heartbeat to decide that the cat is in fact dead? Waiting
|
|||
|
less than 400 milliseconds makes no sense because this would mean that a
|
|||
|
relaxed cat would be considered to cycle between death and life more
|
|||
|
than 100 times per minute. Moreover, just as with human beings, a cat's
|
|||
|
heart might stop for some period of time, so the exact wait period is a
|
|||
|
judgment call. One of our pair of veterinarians might wait 30 seconds
|
|||
|
before pronouncing the cat dead, while the other might insist on waiting
|
|||
|
a full minute. The two veterinarians would then disagree on the state of
|
|||
|
the cat during the final 30 seconds of the minute following the last
|
|||
|
heartbeat.
|
|||
|
|
|||
|
Interestingly enough, this same situation applies to hardware. When push
|
|||
|
comes to shove, how do we tell whether or not some external server has
|
|||
|
failed? We send messages to it periodically, and declare it failed if we
|
|||
|
don't receive a response within a given period of time. Policy decisions
|
|||
|
can usually tolerate short periods of inconsistency. The policy was
|
|||
|
decided some time ago, and is only now being put into effect, so a few
|
|||
|
milliseconds of delay is normally inconsequential.
|
|||
|
|
|||
|
However, there are algorithms that absolutely must see consistent data.
|
|||
|
For example, the translation between a user-level SystemV semaphore ID
|
|||
|
to the corresponding in-kernel data structure is protected by RCU, but
|
|||
|
it is absolutely forbidden to update a semaphore that has just been
|
|||
|
removed. In the Linux kernel, this need for consistency is accommodated
|
|||
|
by acquiring spinlocks located in the in-kernel data structure from
|
|||
|
within the RCU read-side critical section, and this is indicated by the
|
|||
|
green box in the figure above. Many other techniques may be used, and
|
|||
|
are in fact used within the Linux kernel.
|
|||
|
|
|||
|
In short, RCU is not required to maintain consistency, and other
|
|||
|
mechanisms may be used in concert with RCU when consistency is required.
|
|||
|
RCU's specialization allows it to do its job extremely well, and its
|
|||
|
ability to interoperate with other synchronization mechanisms allows the
|
|||
|
right mix of synchronization tools to be used for a given job.
|
|||
|
|
|||
|
Performance and Scalability
|
|||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|||
|
|
|||
|
Energy efficiency is a critical component of performance today, and
|
|||
|
Linux-kernel RCU implementations must therefore avoid unnecessarily
|
|||
|
awakening idle CPUs. I cannot claim that this requirement was
|
|||
|
premeditated. In fact, I learned of it during a telephone conversation
|
|||
|
in which I was given “frank and open” feedback on the importance of
|
|||
|
energy efficiency in battery-powered systems and on specific
|
|||
|
energy-efficiency shortcomings of the Linux-kernel RCU implementation.
|
|||
|
In my experience, the battery-powered embedded community will consider
|
|||
|
any unnecessary wakeups to be extremely unfriendly acts. So much so that
|
|||
|
mere Linux-kernel-mailing-list posts are insufficient to vent their ire.
|
|||
|
|
|||
|
Memory consumption is not particularly important for in most situations,
|
|||
|
and has become decreasingly so as memory sizes have expanded and memory
|
|||
|
costs have plummeted. However, as I learned from Matt Mackall's
|
|||
|
`bloatwatch <http://elinux.org/Linux_Tiny-FAQ>`__ efforts, memory
|
|||
|
footprint is critically important on single-CPU systems with
|
|||
|
non-preemptible (``CONFIG_PREEMPTION=n``) kernels, and thus `tiny
|
|||
|
RCU <https://lore.kernel.org/r/20090113221724.GA15307@linux.vnet.ibm.com>`__
|
|||
|
was born. Josh Triplett has since taken over the small-memory banner
|
|||
|
with his `Linux kernel tinification <https://tiny.wiki.kernel.org/>`__
|
|||
|
project, which resulted in `SRCU <Sleepable RCU_>`__ becoming optional
|
|||
|
for those kernels not needing it.
|
|||
|
|
|||
|
The remaining performance requirements are, for the most part,
|
|||
|
unsurprising. For example, in keeping with RCU's read-side
|
|||
|
specialization, rcu_dereference() should have negligible overhead
|
|||
|
(for example, suppression of a few minor compiler optimizations).
|
|||
|
Similarly, in non-preemptible environments, rcu_read_lock() and
|
|||
|
rcu_read_unlock() should have exactly zero overhead.
|
|||
|
|
|||
|
In preemptible environments, in the case where the RCU read-side
|
|||
|
critical section was not preempted (as will be the case for the
|
|||
|
highest-priority real-time process), rcu_read_lock() and
|
|||
|
rcu_read_unlock() should have minimal overhead. In particular, they
|
|||
|
should not contain atomic read-modify-write operations, memory-barrier
|
|||
|
instructions, preemption disabling, interrupt disabling, or backwards
|
|||
|
branches. However, in the case where the RCU read-side critical section
|
|||
|
was preempted, rcu_read_unlock() may acquire spinlocks and disable
|
|||
|
interrupts. This is why it is better to nest an RCU read-side critical
|
|||
|
section within a preempt-disable region than vice versa, at least in
|
|||
|
cases where that critical section is short enough to avoid unduly
|
|||
|
degrading real-time latencies.
|
|||
|
|
|||
|
The synchronize_rcu() grace-period-wait primitive is optimized for
|
|||
|
throughput. It may therefore incur several milliseconds of latency in
|
|||
|
addition to the duration of the longest RCU read-side critical section.
|
|||
|
On the other hand, multiple concurrent invocations of
|
|||
|
synchronize_rcu() are required to use batching optimizations so that
|
|||
|
they can be satisfied by a single underlying grace-period-wait
|
|||
|
operation. For example, in the Linux kernel, it is not unusual for a
|
|||
|
single grace-period-wait operation to serve more than `1,000 separate
|
|||
|
invocations <https://www.usenix.org/conference/2004-usenix-annual-technical-conference/making-rcu-safe-deep-sub-millisecond-response>`__
|
|||
|
of synchronize_rcu(), thus amortizing the per-invocation overhead
|
|||
|
down to nearly zero. However, the grace-period optimization is also
|
|||
|
required to avoid measurable degradation of real-time scheduling and
|
|||
|
interrupt latencies.
|
|||
|
|
|||
|
In some cases, the multi-millisecond synchronize_rcu() latencies are
|
|||
|
unacceptable. In these cases, synchronize_rcu_expedited() may be
|
|||
|
used instead, reducing the grace-period latency down to a few tens of
|
|||
|
microseconds on small systems, at least in cases where the RCU read-side
|
|||
|
critical sections are short. There are currently no special latency
|
|||
|
requirements for synchronize_rcu_expedited() on large systems, but,
|
|||
|
consistent with the empirical nature of the RCU specification, that is
|
|||
|
subject to change. However, there most definitely are scalability
|
|||
|
requirements: A storm of synchronize_rcu_expedited() invocations on
|
|||
|
4096 CPUs should at least make reasonable forward progress. In return
|
|||
|
for its shorter latencies, synchronize_rcu_expedited() is permitted
|
|||
|
to impose modest degradation of real-time latency on non-idle online
|
|||
|
CPUs. Here, “modest” means roughly the same latency degradation as a
|
|||
|
scheduling-clock interrupt.
|
|||
|
|
|||
|
There are a number of situations where even
|
|||
|
synchronize_rcu_expedited()'s reduced grace-period latency is
|
|||
|
unacceptable. In these situations, the asynchronous call_rcu() can
|
|||
|
be used in place of synchronize_rcu() as follows:
|
|||
|
|
|||
|
::
|
|||
|
|
|||
|
1 struct foo {
|
|||
|
2 int a;
|
|||
|
3 int b;
|
|||
|
4 struct rcu_head rh;
|
|||
|
5 };
|
|||
|
6
|
|||
|
7 static void remove_gp_cb(struct rcu_head *rhp)
|
|||
|
8 {
|
|||
|
9 struct foo *p = container_of(rhp, struct foo, rh);
|
|||
|
10
|
|||
|
11 kfree(p);
|
|||
|
12 }
|
|||
|
13
|
|||
|
14 bool remove_gp_asynchronous(void)
|
|||
|
15 {
|
|||
|
16 struct foo *p;
|
|||
|
17
|
|||
|
18 spin_lock(&gp_lock);
|
|||
|
19 p = rcu_access_pointer(gp);
|
|||
|
20 if (!p) {
|
|||
|
21 spin_unlock(&gp_lock);
|
|||
|
22 return false;
|
|||
|
23 }
|
|||
|
24 rcu_assign_pointer(gp, NULL);
|
|||
|
25 call_rcu(&p->rh, remove_gp_cb);
|
|||
|
26 spin_unlock(&gp_lock);
|
|||
|
27 return true;
|
|||
|
28 }
|
|||
|
|
|||
|
A definition of ``struct foo`` is finally needed, and appears on
|
|||
|
lines 1-5. The function remove_gp_cb() is passed to call_rcu()
|
|||
|
on line 25, and will be invoked after the end of a subsequent grace
|
|||
|
period. This gets the same effect as remove_gp_synchronous(), but
|
|||
|
without forcing the updater to wait for a grace period to elapse. The
|
|||
|
call_rcu() function may be used in a number of situations where
|
|||
|
neither synchronize_rcu() nor synchronize_rcu_expedited() would
|
|||
|
be legal, including within preempt-disable code, local_bh_disable()
|
|||
|
code, interrupt-disable code, and interrupt handlers. However, even
|
|||
|
call_rcu() is illegal within NMI handlers and from idle and offline
|
|||
|
CPUs. The callback function (remove_gp_cb() in this case) will be
|
|||
|
executed within softirq (software interrupt) environment within the
|
|||
|
Linux kernel, either within a real softirq handler or under the
|
|||
|
protection of local_bh_disable(). In both the Linux kernel and in
|
|||
|
userspace, it is bad practice to write an RCU callback function that
|
|||
|
takes too long. Long-running operations should be relegated to separate
|
|||
|
threads or (in the Linux kernel) workqueues.
|
|||
|
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
| **Quick Quiz**: |
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
| Why does line 19 use rcu_access_pointer()? After all, |
|
|||
|
| call_rcu() on line 25 stores into the structure, which would |
|
|||
|
| interact badly with concurrent insertions. Doesn't this mean that |
|
|||
|
| rcu_dereference() is required? |
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
| **Answer**: |
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
| Presumably the ``->gp_lock`` acquired on line 18 excludes any |
|
|||
|
| changes, including any insertions that rcu_dereference() would |
|
|||
|
| protect against. Therefore, any insertions will be delayed until |
|
|||
|
| after ``->gp_lock`` is released on line 25, which in turn means that |
|
|||
|
| rcu_access_pointer() suffices. |
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
|
|||
|
However, all that remove_gp_cb() is doing is invoking kfree() on
|
|||
|
the data element. This is a common idiom, and is supported by
|
|||
|
kfree_rcu(), which allows “fire and forget” operation as shown
|
|||
|
below:
|
|||
|
|
|||
|
::
|
|||
|
|
|||
|
1 struct foo {
|
|||
|
2 int a;
|
|||
|
3 int b;
|
|||
|
4 struct rcu_head rh;
|
|||
|
5 };
|
|||
|
6
|
|||
|
7 bool remove_gp_faf(void)
|
|||
|
8 {
|
|||
|
9 struct foo *p;
|
|||
|
10
|
|||
|
11 spin_lock(&gp_lock);
|
|||
|
12 p = rcu_dereference(gp);
|
|||
|
13 if (!p) {
|
|||
|
14 spin_unlock(&gp_lock);
|
|||
|
15 return false;
|
|||
|
16 }
|
|||
|
17 rcu_assign_pointer(gp, NULL);
|
|||
|
18 kfree_rcu(p, rh);
|
|||
|
19 spin_unlock(&gp_lock);
|
|||
|
20 return true;
|
|||
|
21 }
|
|||
|
|
|||
|
Note that remove_gp_faf() simply invokes kfree_rcu() and
|
|||
|
proceeds, without any need to pay any further attention to the
|
|||
|
subsequent grace period and kfree(). It is permissible to invoke
|
|||
|
kfree_rcu() from the same environments as for call_rcu().
|
|||
|
Interestingly enough, DYNIX/ptx had the equivalents of call_rcu()
|
|||
|
and kfree_rcu(), but not synchronize_rcu(). This was due to the
|
|||
|
fact that RCU was not heavily used within DYNIX/ptx, so the very few
|
|||
|
places that needed something like synchronize_rcu() simply
|
|||
|
open-coded it.
|
|||
|
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
| **Quick Quiz**: |
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
| Earlier it was claimed that call_rcu() and kfree_rcu() |
|
|||
|
| allowed updaters to avoid being blocked by readers. But how can that |
|
|||
|
| be correct, given that the invocation of the callback and the freeing |
|
|||
|
| of the memory (respectively) must still wait for a grace period to |
|
|||
|
| elapse? |
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
| **Answer**: |
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
| We could define things this way, but keep in mind that this sort of |
|
|||
|
| definition would say that updates in garbage-collected languages |
|
|||
|
| cannot complete until the next time the garbage collector runs, which |
|
|||
|
| does not seem at all reasonable. The key point is that in most cases, |
|
|||
|
| an updater using either call_rcu() or kfree_rcu() can proceed |
|
|||
|
| to the next update as soon as it has invoked call_rcu() or |
|
|||
|
| kfree_rcu(), without having to wait for a subsequent grace |
|
|||
|
| period. |
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
|
|||
|
But what if the updater must wait for the completion of code to be
|
|||
|
executed after the end of the grace period, but has other tasks that can
|
|||
|
be carried out in the meantime? The polling-style
|
|||
|
get_state_synchronize_rcu() and cond_synchronize_rcu() functions
|
|||
|
may be used for this purpose, as shown below:
|
|||
|
|
|||
|
::
|
|||
|
|
|||
|
1 bool remove_gp_poll(void)
|
|||
|
2 {
|
|||
|
3 struct foo *p;
|
|||
|
4 unsigned long s;
|
|||
|
5
|
|||
|
6 spin_lock(&gp_lock);
|
|||
|
7 p = rcu_access_pointer(gp);
|
|||
|
8 if (!p) {
|
|||
|
9 spin_unlock(&gp_lock);
|
|||
|
10 return false;
|
|||
|
11 }
|
|||
|
12 rcu_assign_pointer(gp, NULL);
|
|||
|
13 spin_unlock(&gp_lock);
|
|||
|
14 s = get_state_synchronize_rcu();
|
|||
|
15 do_something_while_waiting();
|
|||
|
16 cond_synchronize_rcu(s);
|
|||
|
17 kfree(p);
|
|||
|
18 return true;
|
|||
|
19 }
|
|||
|
|
|||
|
On line 14, get_state_synchronize_rcu() obtains a “cookie” from RCU,
|
|||
|
then line 15 carries out other tasks, and finally, line 16 returns
|
|||
|
immediately if a grace period has elapsed in the meantime, but otherwise
|
|||
|
waits as required. The need for ``get_state_synchronize_rcu`` and
|
|||
|
cond_synchronize_rcu() has appeared quite recently, so it is too
|
|||
|
early to tell whether they will stand the test of time.
|
|||
|
|
|||
|
RCU thus provides a range of tools to allow updaters to strike the
|
|||
|
required tradeoff between latency, flexibility and CPU overhead.
|
|||
|
|
|||
|
Forward Progress
|
|||
|
~~~~~~~~~~~~~~~~
|
|||
|
|
|||
|
In theory, delaying grace-period completion and callback invocation is
|
|||
|
harmless. In practice, not only are memory sizes finite but also
|
|||
|
callbacks sometimes do wakeups, and sufficiently deferred wakeups can be
|
|||
|
difficult to distinguish from system hangs. Therefore, RCU must provide
|
|||
|
a number of mechanisms to promote forward progress.
|
|||
|
|
|||
|
These mechanisms are not foolproof, nor can they be. For one simple
|
|||
|
example, an infinite loop in an RCU read-side critical section must by
|
|||
|
definition prevent later grace periods from ever completing. For a more
|
|||
|
involved example, consider a 64-CPU system built with
|
|||
|
``CONFIG_RCU_NOCB_CPU=y`` and booted with ``rcu_nocbs=1-63``, where
|
|||
|
CPUs 1 through 63 spin in tight loops that invoke call_rcu(). Even
|
|||
|
if these tight loops also contain calls to cond_resched() (thus
|
|||
|
allowing grace periods to complete), CPU 0 simply will not be able to
|
|||
|
invoke callbacks as fast as the other 63 CPUs can register them, at
|
|||
|
least not until the system runs out of memory. In both of these
|
|||
|
examples, the Spiderman principle applies: With great power comes great
|
|||
|
responsibility. However, short of this level of abuse, RCU is required
|
|||
|
to ensure timely completion of grace periods and timely invocation of
|
|||
|
callbacks.
|
|||
|
|
|||
|
RCU takes the following steps to encourage timely completion of grace
|
|||
|
periods:
|
|||
|
|
|||
|
#. If a grace period fails to complete within 100 milliseconds, RCU
|
|||
|
causes future invocations of cond_resched() on the holdout CPUs
|
|||
|
to provide an RCU quiescent state. RCU also causes those CPUs'
|
|||
|
need_resched() invocations to return ``true``, but only after the
|
|||
|
corresponding CPU's next scheduling-clock.
|
|||
|
#. CPUs mentioned in the ``nohz_full`` kernel boot parameter can run
|
|||
|
indefinitely in the kernel without scheduling-clock interrupts, which
|
|||
|
defeats the above need_resched() strategem. RCU will therefore
|
|||
|
invoke resched_cpu() on any ``nohz_full`` CPUs still holding out
|
|||
|
after 109 milliseconds.
|
|||
|
#. In kernels built with ``CONFIG_RCU_BOOST=y``, if a given task that
|
|||
|
has been preempted within an RCU read-side critical section is
|
|||
|
holding out for more than 500 milliseconds, RCU will resort to
|
|||
|
priority boosting.
|
|||
|
#. If a CPU is still holding out 10 seconds into the grace period, RCU
|
|||
|
will invoke resched_cpu() on it regardless of its ``nohz_full``
|
|||
|
state.
|
|||
|
|
|||
|
The above values are defaults for systems running with ``HZ=1000``. They
|
|||
|
will vary as the value of ``HZ`` varies, and can also be changed using
|
|||
|
the relevant Kconfig options and kernel boot parameters. RCU currently
|
|||
|
does not do much sanity checking of these parameters, so please use
|
|||
|
caution when changing them. Note that these forward-progress measures
|
|||
|
are provided only for RCU, not for `SRCU <Sleepable RCU_>`__ or `Tasks
|
|||
|
RCU`_.
|
|||
|
|
|||
|
RCU takes the following steps in call_rcu() to encourage timely
|
|||
|
invocation of callbacks when any given non-\ ``rcu_nocbs`` CPU has
|
|||
|
10,000 callbacks, or has 10,000 more callbacks than it had the last time
|
|||
|
encouragement was provided:
|
|||
|
|
|||
|
#. Starts a grace period, if one is not already in progress.
|
|||
|
#. Forces immediate checking for quiescent states, rather than waiting
|
|||
|
for three milliseconds to have elapsed since the beginning of the
|
|||
|
grace period.
|
|||
|
#. Immediately tags the CPU's callbacks with their grace period
|
|||
|
completion numbers, rather than waiting for the ``RCU_SOFTIRQ``
|
|||
|
handler to get around to it.
|
|||
|
#. Lifts callback-execution batch limits, which speeds up callback
|
|||
|
invocation at the expense of degrading realtime response.
|
|||
|
|
|||
|
Again, these are default values when running at ``HZ=1000``, and can be
|
|||
|
overridden. Again, these forward-progress measures are provided only for
|
|||
|
RCU, not for `SRCU <Sleepable RCU_>`__ or `Tasks
|
|||
|
RCU`_. Even for RCU, callback-invocation forward
|
|||
|
progress for ``rcu_nocbs`` CPUs is much less well-developed, in part
|
|||
|
because workloads benefiting from ``rcu_nocbs`` CPUs tend to invoke
|
|||
|
call_rcu() relatively infrequently. If workloads emerge that need
|
|||
|
both ``rcu_nocbs`` CPUs and high call_rcu() invocation rates, then
|
|||
|
additional forward-progress work will be required.
|
|||
|
|
|||
|
Composability
|
|||
|
~~~~~~~~~~~~~
|
|||
|
|
|||
|
Composability has received much attention in recent years, perhaps in
|
|||
|
part due to the collision of multicore hardware with object-oriented
|
|||
|
techniques designed in single-threaded environments for single-threaded
|
|||
|
use. And in theory, RCU read-side critical sections may be composed, and
|
|||
|
in fact may be nested arbitrarily deeply. In practice, as with all
|
|||
|
real-world implementations of composable constructs, there are
|
|||
|
limitations.
|
|||
|
|
|||
|
Implementations of RCU for which rcu_read_lock() and
|
|||
|
rcu_read_unlock() generate no code, such as Linux-kernel RCU when
|
|||
|
``CONFIG_PREEMPTION=n``, can be nested arbitrarily deeply. After all, there
|
|||
|
is no overhead. Except that if all these instances of
|
|||
|
rcu_read_lock() and rcu_read_unlock() are visible to the
|
|||
|
compiler, compilation will eventually fail due to exhausting memory,
|
|||
|
mass storage, or user patience, whichever comes first. If the nesting is
|
|||
|
not visible to the compiler, as is the case with mutually recursive
|
|||
|
functions each in its own translation unit, stack overflow will result.
|
|||
|
If the nesting takes the form of loops, perhaps in the guise of tail
|
|||
|
recursion, either the control variable will overflow or (in the Linux
|
|||
|
kernel) you will get an RCU CPU stall warning. Nevertheless, this class
|
|||
|
of RCU implementations is one of the most composable constructs in
|
|||
|
existence.
|
|||
|
|
|||
|
RCU implementations that explicitly track nesting depth are limited by
|
|||
|
the nesting-depth counter. For example, the Linux kernel's preemptible
|
|||
|
RCU limits nesting to ``INT_MAX``. This should suffice for almost all
|
|||
|
practical purposes. That said, a consecutive pair of RCU read-side
|
|||
|
critical sections between which there is an operation that waits for a
|
|||
|
grace period cannot be enclosed in another RCU read-side critical
|
|||
|
section. This is because it is not legal to wait for a grace period
|
|||
|
within an RCU read-side critical section: To do so would result either
|
|||
|
in deadlock or in RCU implicitly splitting the enclosing RCU read-side
|
|||
|
critical section, neither of which is conducive to a long-lived and
|
|||
|
prosperous kernel.
|
|||
|
|
|||
|
It is worth noting that RCU is not alone in limiting composability. For
|
|||
|
example, many transactional-memory implementations prohibit composing a
|
|||
|
pair of transactions separated by an irrevocable operation (for example,
|
|||
|
a network receive operation). For another example, lock-based critical
|
|||
|
sections can be composed surprisingly freely, but only if deadlock is
|
|||
|
avoided.
|
|||
|
|
|||
|
In short, although RCU read-side critical sections are highly
|
|||
|
composable, care is required in some situations, just as is the case for
|
|||
|
any other composable synchronization mechanism.
|
|||
|
|
|||
|
Corner Cases
|
|||
|
~~~~~~~~~~~~
|
|||
|
|
|||
|
A given RCU workload might have an endless and intense stream of RCU
|
|||
|
read-side critical sections, perhaps even so intense that there was
|
|||
|
never a point in time during which there was not at least one RCU
|
|||
|
read-side critical section in flight. RCU cannot allow this situation to
|
|||
|
block grace periods: As long as all the RCU read-side critical sections
|
|||
|
are finite, grace periods must also be finite.
|
|||
|
|
|||
|
That said, preemptible RCU implementations could potentially result in
|
|||
|
RCU read-side critical sections being preempted for long durations,
|
|||
|
which has the effect of creating a long-duration RCU read-side critical
|
|||
|
section. This situation can arise only in heavily loaded systems, but
|
|||
|
systems using real-time priorities are of course more vulnerable.
|
|||
|
Therefore, RCU priority boosting is provided to help deal with this
|
|||
|
case. That said, the exact requirements on RCU priority boosting will
|
|||
|
likely evolve as more experience accumulates.
|
|||
|
|
|||
|
Other workloads might have very high update rates. Although one can
|
|||
|
argue that such workloads should instead use something other than RCU,
|
|||
|
the fact remains that RCU must handle such workloads gracefully. This
|
|||
|
requirement is another factor driving batching of grace periods, but it
|
|||
|
is also the driving force behind the checks for large numbers of queued
|
|||
|
RCU callbacks in the call_rcu() code path. Finally, high update
|
|||
|
rates should not delay RCU read-side critical sections, although some
|
|||
|
small read-side delays can occur when using
|
|||
|
synchronize_rcu_expedited(), courtesy of this function's use of
|
|||
|
smp_call_function_single().
|
|||
|
|
|||
|
Although all three of these corner cases were understood in the early
|
|||
|
1990s, a simple user-level test consisting of ``close(open(path))`` in a
|
|||
|
tight loop in the early 2000s suddenly provided a much deeper
|
|||
|
appreciation of the high-update-rate corner case. This test also
|
|||
|
motivated addition of some RCU code to react to high update rates, for
|
|||
|
example, if a given CPU finds itself with more than 10,000 RCU callbacks
|
|||
|
queued, it will cause RCU to take evasive action by more aggressively
|
|||
|
starting grace periods and more aggressively forcing completion of
|
|||
|
grace-period processing. This evasive action causes the grace period to
|
|||
|
complete more quickly, but at the cost of restricting RCU's batching
|
|||
|
optimizations, thus increasing the CPU overhead incurred by that grace
|
|||
|
period.
|
|||
|
|
|||
|
Software-Engineering Requirements
|
|||
|
---------------------------------
|
|||
|
|
|||
|
Between Murphy's Law and “To err is human”, it is necessary to guard
|
|||
|
against mishaps and misuse:
|
|||
|
|
|||
|
#. It is all too easy to forget to use rcu_read_lock() everywhere
|
|||
|
that it is needed, so kernels built with ``CONFIG_PROVE_RCU=y`` will
|
|||
|
splat if rcu_dereference() is used outside of an RCU read-side
|
|||
|
critical section. Update-side code can use
|
|||
|
rcu_dereference_protected(), which takes a `lockdep
|
|||
|
expression <https://lwn.net/Articles/371986/>`__ to indicate what is
|
|||
|
providing the protection. If the indicated protection is not
|
|||
|
provided, a lockdep splat is emitted.
|
|||
|
Code shared between readers and updaters can use
|
|||
|
rcu_dereference_check(), which also takes a lockdep expression,
|
|||
|
and emits a lockdep splat if neither rcu_read_lock() nor the
|
|||
|
indicated protection is in place. In addition,
|
|||
|
rcu_dereference_raw() is used in those (hopefully rare) cases
|
|||
|
where the required protection cannot be easily described. Finally,
|
|||
|
rcu_read_lock_held() is provided to allow a function to verify
|
|||
|
that it has been invoked within an RCU read-side critical section. I
|
|||
|
was made aware of this set of requirements shortly after Thomas
|
|||
|
Gleixner audited a number of RCU uses.
|
|||
|
#. A given function might wish to check for RCU-related preconditions
|
|||
|
upon entry, before using any other RCU API. The
|
|||
|
rcu_lockdep_assert() does this job, asserting the expression in
|
|||
|
kernels having lockdep enabled and doing nothing otherwise.
|
|||
|
#. It is also easy to forget to use rcu_assign_pointer() and
|
|||
|
rcu_dereference(), perhaps (incorrectly) substituting a simple
|
|||
|
assignment. To catch this sort of error, a given RCU-protected
|
|||
|
pointer may be tagged with ``__rcu``, after which sparse will
|
|||
|
complain about simple-assignment accesses to that pointer. Arnd
|
|||
|
Bergmann made me aware of this requirement, and also supplied the
|
|||
|
needed `patch series <https://lwn.net/Articles/376011/>`__.
|
|||
|
#. Kernels built with ``CONFIG_DEBUG_OBJECTS_RCU_HEAD=y`` will splat if
|
|||
|
a data element is passed to call_rcu() twice in a row, without a
|
|||
|
grace period in between. (This error is similar to a double free.)
|
|||
|
The corresponding ``rcu_head`` structures that are dynamically
|
|||
|
allocated are automatically tracked, but ``rcu_head`` structures
|
|||
|
allocated on the stack must be initialized with
|
|||
|
init_rcu_head_on_stack() and cleaned up with
|
|||
|
destroy_rcu_head_on_stack(). Similarly, statically allocated
|
|||
|
non-stack ``rcu_head`` structures must be initialized with
|
|||
|
init_rcu_head() and cleaned up with destroy_rcu_head().
|
|||
|
Mathieu Desnoyers made me aware of this requirement, and also
|
|||
|
supplied the needed
|
|||
|
`patch <https://lore.kernel.org/r/20100319013024.GA28456@Krystal>`__.
|
|||
|
#. An infinite loop in an RCU read-side critical section will eventually
|
|||
|
trigger an RCU CPU stall warning splat, with the duration of
|
|||
|
“eventually” being controlled by the ``RCU_CPU_STALL_TIMEOUT``
|
|||
|
``Kconfig`` option, or, alternatively, by the
|
|||
|
``rcupdate.rcu_cpu_stall_timeout`` boot/sysfs parameter. However, RCU
|
|||
|
is not obligated to produce this splat unless there is a grace period
|
|||
|
waiting on that particular RCU read-side critical section.
|
|||
|
|
|||
|
Some extreme workloads might intentionally delay RCU grace periods,
|
|||
|
and systems running those workloads can be booted with
|
|||
|
``rcupdate.rcu_cpu_stall_suppress`` to suppress the splats. This
|
|||
|
kernel parameter may also be set via ``sysfs``. Furthermore, RCU CPU
|
|||
|
stall warnings are counter-productive during sysrq dumps and during
|
|||
|
panics. RCU therefore supplies the rcu_sysrq_start() and
|
|||
|
rcu_sysrq_end() API members to be called before and after long
|
|||
|
sysrq dumps. RCU also supplies the rcu_panic() notifier that is
|
|||
|
automatically invoked at the beginning of a panic to suppress further
|
|||
|
RCU CPU stall warnings.
|
|||
|
|
|||
|
This requirement made itself known in the early 1990s, pretty much
|
|||
|
the first time that it was necessary to debug a CPU stall. That said,
|
|||
|
the initial implementation in DYNIX/ptx was quite generic in
|
|||
|
comparison with that of Linux.
|
|||
|
|
|||
|
#. Although it would be very good to detect pointers leaking out of RCU
|
|||
|
read-side critical sections, there is currently no good way of doing
|
|||
|
this. One complication is the need to distinguish between pointers
|
|||
|
leaking and pointers that have been handed off from RCU to some other
|
|||
|
synchronization mechanism, for example, reference counting.
|
|||
|
#. In kernels built with ``CONFIG_RCU_TRACE=y``, RCU-related information
|
|||
|
is provided via event tracing.
|
|||
|
#. Open-coded use of rcu_assign_pointer() and rcu_dereference()
|
|||
|
to create typical linked data structures can be surprisingly
|
|||
|
error-prone. Therefore, RCU-protected `linked
|
|||
|
lists <https://lwn.net/Articles/609973/#RCU%20List%20APIs>`__ and,
|
|||
|
more recently, RCU-protected `hash
|
|||
|
tables <https://lwn.net/Articles/612100/>`__ are available. Many
|
|||
|
other special-purpose RCU-protected data structures are available in
|
|||
|
the Linux kernel and the userspace RCU library.
|
|||
|
#. Some linked structures are created at compile time, but still require
|
|||
|
``__rcu`` checking. The RCU_POINTER_INITIALIZER() macro serves
|
|||
|
this purpose.
|
|||
|
#. It is not necessary to use rcu_assign_pointer() when creating
|
|||
|
linked structures that are to be published via a single external
|
|||
|
pointer. The RCU_INIT_POINTER() macro is provided for this task.
|
|||
|
|
|||
|
This not a hard-and-fast list: RCU's diagnostic capabilities will
|
|||
|
continue to be guided by the number and type of usage bugs found in
|
|||
|
real-world RCU usage.
|
|||
|
|
|||
|
Linux Kernel Complications
|
|||
|
--------------------------
|
|||
|
|
|||
|
The Linux kernel provides an interesting environment for all kinds of
|
|||
|
software, including RCU. Some of the relevant points of interest are as
|
|||
|
follows:
|
|||
|
|
|||
|
#. `Configuration`_
|
|||
|
#. `Firmware Interface`_
|
|||
|
#. `Early Boot`_
|
|||
|
#. `Interrupts and NMIs`_
|
|||
|
#. `Loadable Modules`_
|
|||
|
#. `Hotplug CPU`_
|
|||
|
#. `Scheduler and RCU`_
|
|||
|
#. `Tracing and RCU`_
|
|||
|
#. `Accesses to User Memory and RCU`_
|
|||
|
#. `Energy Efficiency`_
|
|||
|
#. `Scheduling-Clock Interrupts and RCU`_
|
|||
|
#. `Memory Efficiency`_
|
|||
|
#. `Performance, Scalability, Response Time, and Reliability`_
|
|||
|
|
|||
|
This list is probably incomplete, but it does give a feel for the most
|
|||
|
notable Linux-kernel complications. Each of the following sections
|
|||
|
covers one of the above topics.
|
|||
|
|
|||
|
Configuration
|
|||
|
~~~~~~~~~~~~~
|
|||
|
|
|||
|
RCU's goal is automatic configuration, so that almost nobody needs to
|
|||
|
worry about RCU's ``Kconfig`` options. And for almost all users, RCU
|
|||
|
does in fact work well “out of the box.”
|
|||
|
|
|||
|
However, there are specialized use cases that are handled by kernel boot
|
|||
|
parameters and ``Kconfig`` options. Unfortunately, the ``Kconfig``
|
|||
|
system will explicitly ask users about new ``Kconfig`` options, which
|
|||
|
requires almost all of them be hidden behind a ``CONFIG_RCU_EXPERT``
|
|||
|
``Kconfig`` option.
|
|||
|
|
|||
|
This all should be quite obvious, but the fact remains that Linus
|
|||
|
Torvalds recently had to
|
|||
|
`remind <https://lore.kernel.org/r/CA+55aFy4wcCwaL4okTs8wXhGZ5h-ibecy_Meg9C4MNQrUnwMcg@mail.gmail.com>`__
|
|||
|
me of this requirement.
|
|||
|
|
|||
|
Firmware Interface
|
|||
|
~~~~~~~~~~~~~~~~~~
|
|||
|
|
|||
|
In many cases, kernel obtains information about the system from the
|
|||
|
firmware, and sometimes things are lost in translation. Or the
|
|||
|
translation is accurate, but the original message is bogus.
|
|||
|
|
|||
|
For example, some systems' firmware overreports the number of CPUs,
|
|||
|
sometimes by a large factor. If RCU naively believed the firmware, as it
|
|||
|
used to do, it would create too many per-CPU kthreads. Although the
|
|||
|
resulting system will still run correctly, the extra kthreads needlessly
|
|||
|
consume memory and can cause confusion when they show up in ``ps``
|
|||
|
listings.
|
|||
|
|
|||
|
RCU must therefore wait for a given CPU to actually come online before
|
|||
|
it can allow itself to believe that the CPU actually exists. The
|
|||
|
resulting “ghost CPUs” (which are never going to come online) cause a
|
|||
|
number of `interesting
|
|||
|
complications <https://paulmck.livejournal.com/37494.html>`__.
|
|||
|
|
|||
|
Early Boot
|
|||
|
~~~~~~~~~~
|
|||
|
|
|||
|
The Linux kernel's boot sequence is an interesting process, and RCU is
|
|||
|
used early, even before rcu_init() is invoked. In fact, a number of
|
|||
|
RCU's primitives can be used as soon as the initial task's
|
|||
|
``task_struct`` is available and the boot CPU's per-CPU variables are
|
|||
|
set up. The read-side primitives (rcu_read_lock(),
|
|||
|
rcu_read_unlock(), rcu_dereference(), and
|
|||
|
rcu_access_pointer()) will operate normally very early on, as will
|
|||
|
rcu_assign_pointer().
|
|||
|
|
|||
|
Although call_rcu() may be invoked at any time during boot,
|
|||
|
callbacks are not guaranteed to be invoked until after all of RCU's
|
|||
|
kthreads have been spawned, which occurs at early_initcall() time.
|
|||
|
This delay in callback invocation is due to the fact that RCU does not
|
|||
|
invoke callbacks until it is fully initialized, and this full
|
|||
|
initialization cannot occur until after the scheduler has initialized
|
|||
|
itself to the point where RCU can spawn and run its kthreads. In theory,
|
|||
|
it would be possible to invoke callbacks earlier, however, this is not a
|
|||
|
panacea because there would be severe restrictions on what operations
|
|||
|
those callbacks could invoke.
|
|||
|
|
|||
|
Perhaps surprisingly, synchronize_rcu() and
|
|||
|
synchronize_rcu_expedited(), will operate normally during very early
|
|||
|
boot, the reason being that there is only one CPU and preemption is
|
|||
|
disabled. This means that the call synchronize_rcu() (or friends)
|
|||
|
itself is a quiescent state and thus a grace period, so the early-boot
|
|||
|
implementation can be a no-op.
|
|||
|
|
|||
|
However, once the scheduler has spawned its first kthread, this early
|
|||
|
boot trick fails for synchronize_rcu() (as well as for
|
|||
|
synchronize_rcu_expedited()) in ``CONFIG_PREEMPTION=y`` kernels. The
|
|||
|
reason is that an RCU read-side critical section might be preempted,
|
|||
|
which means that a subsequent synchronize_rcu() really does have to
|
|||
|
wait for something, as opposed to simply returning immediately.
|
|||
|
Unfortunately, synchronize_rcu() can't do this until all of its
|
|||
|
kthreads are spawned, which doesn't happen until some time during
|
|||
|
early_initcalls() time. But this is no excuse: RCU is nevertheless
|
|||
|
required to correctly handle synchronous grace periods during this time
|
|||
|
period. Once all of its kthreads are up and running, RCU starts running
|
|||
|
normally.
|
|||
|
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
| **Quick Quiz**: |
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
| How can RCU possibly handle grace periods before all of its kthreads |
|
|||
|
| have been spawned??? |
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
| **Answer**: |
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
| Very carefully! |
|
|||
|
| During the “dead zone” between the time that the scheduler spawns the |
|
|||
|
| first task and the time that all of RCU's kthreads have been spawned, |
|
|||
|
| all synchronous grace periods are handled by the expedited |
|
|||
|
| grace-period mechanism. At runtime, this expedited mechanism relies |
|
|||
|
| on workqueues, but during the dead zone the requesting task itself |
|
|||
|
| drives the desired expedited grace period. Because dead-zone |
|
|||
|
| execution takes place within task context, everything works. Once the |
|
|||
|
| dead zone ends, expedited grace periods go back to using workqueues, |
|
|||
|
| as is required to avoid problems that would otherwise occur when a |
|
|||
|
| user task received a POSIX signal while driving an expedited grace |
|
|||
|
| period. |
|
|||
|
| |
|
|||
|
| And yes, this does mean that it is unhelpful to send POSIX signals to |
|
|||
|
| random tasks between the time that the scheduler spawns its first |
|
|||
|
| kthread and the time that RCU's kthreads have all been spawned. If |
|
|||
|
| there ever turns out to be a good reason for sending POSIX signals |
|
|||
|
| during that time, appropriate adjustments will be made. (If it turns |
|
|||
|
| out that POSIX signals are sent during this time for no good reason, |
|
|||
|
| other adjustments will be made, appropriate or otherwise.) |
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
|
|||
|
I learned of these boot-time requirements as a result of a series of
|
|||
|
system hangs.
|
|||
|
|
|||
|
Interrupts and NMIs
|
|||
|
~~~~~~~~~~~~~~~~~~~
|
|||
|
|
|||
|
The Linux kernel has interrupts, and RCU read-side critical sections are
|
|||
|
legal within interrupt handlers and within interrupt-disabled regions of
|
|||
|
code, as are invocations of call_rcu().
|
|||
|
|
|||
|
Some Linux-kernel architectures can enter an interrupt handler from
|
|||
|
non-idle process context, and then just never leave it, instead
|
|||
|
stealthily transitioning back to process context. This trick is
|
|||
|
sometimes used to invoke system calls from inside the kernel. These
|
|||
|
“half-interrupts” mean that RCU has to be very careful about how it
|
|||
|
counts interrupt nesting levels. I learned of this requirement the hard
|
|||
|
way during a rewrite of RCU's dyntick-idle code.
|
|||
|
|
|||
|
The Linux kernel has non-maskable interrupts (NMIs), and RCU read-side
|
|||
|
critical sections are legal within NMI handlers. Thankfully, RCU
|
|||
|
update-side primitives, including call_rcu(), are prohibited within
|
|||
|
NMI handlers.
|
|||
|
|
|||
|
The name notwithstanding, some Linux-kernel architectures can have
|
|||
|
nested NMIs, which RCU must handle correctly. Andy Lutomirski `surprised
|
|||
|
me <https://lore.kernel.org/r/CALCETrXLq1y7e_dKFPgou-FKHB6Pu-r8+t-6Ds+8=va7anBWDA@mail.gmail.com>`__
|
|||
|
with this requirement; he also kindly surprised me with `an
|
|||
|
algorithm <https://lore.kernel.org/r/CALCETrXSY9JpW3uE6H8WYk81sg56qasA2aqmjMPsq5dOtzso=g@mail.gmail.com>`__
|
|||
|
that meets this requirement.
|
|||
|
|
|||
|
Furthermore, NMI handlers can be interrupted by what appear to RCU to be
|
|||
|
normal interrupts. One way that this can happen is for code that
|
|||
|
directly invokes ct_irq_enter() and ct_irq_exit() to be called
|
|||
|
from an NMI handler. This astonishing fact of life prompted the current
|
|||
|
code structure, which has ct_irq_enter() invoking
|
|||
|
ct_nmi_enter() and ct_irq_exit() invoking ct_nmi_exit().
|
|||
|
And yes, I also learned of this requirement the hard way.
|
|||
|
|
|||
|
Loadable Modules
|
|||
|
~~~~~~~~~~~~~~~~
|
|||
|
|
|||
|
The Linux kernel has loadable modules, and these modules can also be
|
|||
|
unloaded. After a given module has been unloaded, any attempt to call
|
|||
|
one of its functions results in a segmentation fault. The module-unload
|
|||
|
functions must therefore cancel any delayed calls to loadable-module
|
|||
|
functions, for example, any outstanding mod_timer() must be dealt
|
|||
|
with via timer_shutdown_sync() or similar.
|
|||
|
|
|||
|
Unfortunately, there is no way to cancel an RCU callback; once you
|
|||
|
invoke call_rcu(), the callback function is eventually going to be
|
|||
|
invoked, unless the system goes down first. Because it is normally
|
|||
|
considered socially irresponsible to crash the system in response to a
|
|||
|
module unload request, we need some other way to deal with in-flight RCU
|
|||
|
callbacks.
|
|||
|
|
|||
|
RCU therefore provides rcu_barrier(), which waits until all
|
|||
|
in-flight RCU callbacks have been invoked. If a module uses
|
|||
|
call_rcu(), its exit function should therefore prevent any future
|
|||
|
invocation of call_rcu(), then invoke rcu_barrier(). In theory,
|
|||
|
the underlying module-unload code could invoke rcu_barrier()
|
|||
|
unconditionally, but in practice this would incur unacceptable
|
|||
|
latencies.
|
|||
|
|
|||
|
Nikita Danilov noted this requirement for an analogous
|
|||
|
filesystem-unmount situation, and Dipankar Sarma incorporated
|
|||
|
rcu_barrier() into RCU. The need for rcu_barrier() for module
|
|||
|
unloading became apparent later.
|
|||
|
|
|||
|
.. important::
|
|||
|
|
|||
|
The rcu_barrier() function is not, repeat,
|
|||
|
*not*, obligated to wait for a grace period. It is instead only required
|
|||
|
to wait for RCU callbacks that have already been posted. Therefore, if
|
|||
|
there are no RCU callbacks posted anywhere in the system,
|
|||
|
rcu_barrier() is within its rights to return immediately. Even if
|
|||
|
there are callbacks posted, rcu_barrier() does not necessarily need
|
|||
|
to wait for a grace period.
|
|||
|
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
| **Quick Quiz**: |
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
| Wait a minute! Each RCU callbacks must wait for a grace period to |
|
|||
|
| complete, and rcu_barrier() must wait for each pre-existing |
|
|||
|
| callback to be invoked. Doesn't rcu_barrier() therefore need to |
|
|||
|
| wait for a full grace period if there is even one callback posted |
|
|||
|
| anywhere in the system? |
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
| **Answer**: |
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
| Absolutely not!!! |
|
|||
|
| Yes, each RCU callbacks must wait for a grace period to complete, but |
|
|||
|
| it might well be partly (or even completely) finished waiting by the |
|
|||
|
| time rcu_barrier() is invoked. In that case, rcu_barrier() |
|
|||
|
| need only wait for the remaining portion of the grace period to |
|
|||
|
| elapse. So even if there are quite a few callbacks posted, |
|
|||
|
| rcu_barrier() might well return quite quickly. |
|
|||
|
| |
|
|||
|
| So if you need to wait for a grace period as well as for all |
|
|||
|
| pre-existing callbacks, you will need to invoke both |
|
|||
|
| synchronize_rcu() and rcu_barrier(). If latency is a concern, |
|
|||
|
| you can always use workqueues to invoke them concurrently. |
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
|
|||
|
Hotplug CPU
|
|||
|
~~~~~~~~~~~
|
|||
|
|
|||
|
The Linux kernel supports CPU hotplug, which means that CPUs can come
|
|||
|
and go. It is of course illegal to use any RCU API member from an
|
|||
|
offline CPU, with the exception of `SRCU <Sleepable RCU_>`__ read-side
|
|||
|
critical sections. This requirement was present from day one in
|
|||
|
DYNIX/ptx, but on the other hand, the Linux kernel's CPU-hotplug
|
|||
|
implementation is “interesting.”
|
|||
|
|
|||
|
The Linux-kernel CPU-hotplug implementation has notifiers that are used
|
|||
|
to allow the various kernel subsystems (including RCU) to respond
|
|||
|
appropriately to a given CPU-hotplug operation. Most RCU operations may
|
|||
|
be invoked from CPU-hotplug notifiers, including even synchronous
|
|||
|
grace-period operations such as (synchronize_rcu() and
|
|||
|
synchronize_rcu_expedited()). However, these synchronous operations
|
|||
|
do block and therefore cannot be invoked from notifiers that execute via
|
|||
|
stop_machine(), specifically those between the ``CPUHP_AP_OFFLINE``
|
|||
|
and ``CPUHP_AP_ONLINE`` states.
|
|||
|
|
|||
|
In addition, all-callback-wait operations such as rcu_barrier() may
|
|||
|
not be invoked from any CPU-hotplug notifier. This restriction is due
|
|||
|
to the fact that there are phases of CPU-hotplug operations where the
|
|||
|
outgoing CPU's callbacks will not be invoked until after the CPU-hotplug
|
|||
|
operation ends, which could also result in deadlock. Furthermore,
|
|||
|
rcu_barrier() blocks CPU-hotplug operations during its execution,
|
|||
|
which results in another type of deadlock when invoked from a CPU-hotplug
|
|||
|
notifier.
|
|||
|
|
|||
|
Finally, RCU must avoid deadlocks due to interaction between hotplug,
|
|||
|
timers and grace period processing. It does so by maintaining its own set
|
|||
|
of books that duplicate the centrally maintained ``cpu_online_mask``,
|
|||
|
and also by reporting quiescent states explicitly when a CPU goes
|
|||
|
offline. This explicit reporting of quiescent states avoids any need
|
|||
|
for the force-quiescent-state loop (FQS) to report quiescent states for
|
|||
|
offline CPUs. However, as a debugging measure, the FQS loop does splat
|
|||
|
if offline CPUs block an RCU grace period for too long.
|
|||
|
|
|||
|
An offline CPU's quiescent state will be reported either:
|
|||
|
|
|||
|
1. As the CPU goes offline using RCU's hotplug notifier (rcu_report_dead()).
|
|||
|
2. When grace period initialization (rcu_gp_init()) detects a
|
|||
|
race either with CPU offlining or with a task unblocking on a leaf
|
|||
|
``rcu_node`` structure whose CPUs are all offline.
|
|||
|
|
|||
|
The CPU-online path (rcu_cpu_starting()) should never need to report
|
|||
|
a quiescent state for an offline CPU. However, as a debugging measure,
|
|||
|
it does emit a warning if a quiescent state was not already reported
|
|||
|
for that CPU.
|
|||
|
|
|||
|
During the checking/modification of RCU's hotplug bookkeeping, the
|
|||
|
corresponding CPU's leaf node lock is held. This avoids race conditions
|
|||
|
between RCU's hotplug notifier hooks, the grace period initialization
|
|||
|
code, and the FQS loop, all of which refer to or modify this bookkeeping.
|
|||
|
|
|||
|
Scheduler and RCU
|
|||
|
~~~~~~~~~~~~~~~~~
|
|||
|
|
|||
|
RCU makes use of kthreads, and it is necessary to avoid excessive CPU-time
|
|||
|
accumulation by these kthreads. This requirement was no surprise, but
|
|||
|
RCU's violation of it when running context-switch-heavy workloads when
|
|||
|
built with ``CONFIG_NO_HZ_FULL=y`` `did come as a surprise
|
|||
|
[PDF] <http://www.rdrop.com/users/paulmck/scalability/paper/BareMetal.2015.01.15b.pdf>`__.
|
|||
|
RCU has made good progress towards meeting this requirement, even for
|
|||
|
context-switch-heavy ``CONFIG_NO_HZ_FULL=y`` workloads, but there is
|
|||
|
room for further improvement.
|
|||
|
|
|||
|
There is no longer any prohibition against holding any of
|
|||
|
scheduler's runqueue or priority-inheritance spinlocks across an
|
|||
|
rcu_read_unlock(), even if interrupts and preemption were enabled
|
|||
|
somewhere within the corresponding RCU read-side critical section.
|
|||
|
Therefore, it is now perfectly legal to execute rcu_read_lock()
|
|||
|
with preemption enabled, acquire one of the scheduler locks, and hold
|
|||
|
that lock across the matching rcu_read_unlock().
|
|||
|
|
|||
|
Similarly, the RCU flavor consolidation has removed the need for negative
|
|||
|
nesting. The fact that interrupt-disabled regions of code act as RCU
|
|||
|
read-side critical sections implicitly avoids earlier issues that used
|
|||
|
to result in destructive recursion via interrupt handler's use of RCU.
|
|||
|
|
|||
|
Tracing and RCU
|
|||
|
~~~~~~~~~~~~~~~
|
|||
|
|
|||
|
It is possible to use tracing on RCU code, but tracing itself uses RCU.
|
|||
|
For this reason, rcu_dereference_raw_check() is provided for use
|
|||
|
by tracing, which avoids the destructive recursion that could otherwise
|
|||
|
ensue. This API is also used by virtualization in some architectures,
|
|||
|
where RCU readers execute in environments in which tracing cannot be
|
|||
|
used. The tracing folks both located the requirement and provided the
|
|||
|
needed fix, so this surprise requirement was relatively painless.
|
|||
|
|
|||
|
Accesses to User Memory and RCU
|
|||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|||
|
|
|||
|
The kernel needs to access user-space memory, for example, to access data
|
|||
|
referenced by system-call parameters. The get_user() macro does this job.
|
|||
|
|
|||
|
However, user-space memory might well be paged out, which means that
|
|||
|
get_user() might well page-fault and thus block while waiting for the
|
|||
|
resulting I/O to complete. It would be a very bad thing for the compiler to
|
|||
|
reorder a get_user() invocation into an RCU read-side critical section.
|
|||
|
|
|||
|
For example, suppose that the source code looked like this:
|
|||
|
|
|||
|
::
|
|||
|
|
|||
|
1 rcu_read_lock();
|
|||
|
2 p = rcu_dereference(gp);
|
|||
|
3 v = p->value;
|
|||
|
4 rcu_read_unlock();
|
|||
|
5 get_user(user_v, user_p);
|
|||
|
6 do_something_with(v, user_v);
|
|||
|
|
|||
|
The compiler must not be permitted to transform this source code into
|
|||
|
the following:
|
|||
|
|
|||
|
::
|
|||
|
|
|||
|
1 rcu_read_lock();
|
|||
|
2 p = rcu_dereference(gp);
|
|||
|
3 get_user(user_v, user_p); // BUG: POSSIBLE PAGE FAULT!!!
|
|||
|
4 v = p->value;
|
|||
|
5 rcu_read_unlock();
|
|||
|
6 do_something_with(v, user_v);
|
|||
|
|
|||
|
If the compiler did make this transformation in a ``CONFIG_PREEMPTION=n`` kernel
|
|||
|
build, and if get_user() did page fault, the result would be a quiescent
|
|||
|
state in the middle of an RCU read-side critical section. This misplaced
|
|||
|
quiescent state could result in line 4 being a use-after-free access,
|
|||
|
which could be bad for your kernel's actuarial statistics. Similar examples
|
|||
|
can be constructed with the call to get_user() preceding the
|
|||
|
rcu_read_lock().
|
|||
|
|
|||
|
Unfortunately, get_user() doesn't have any particular ordering properties,
|
|||
|
and in some architectures the underlying ``asm`` isn't even marked
|
|||
|
``volatile``. And even if it was marked ``volatile``, the above access to
|
|||
|
``p->value`` is not volatile, so the compiler would not have any reason to keep
|
|||
|
those two accesses in order.
|
|||
|
|
|||
|
Therefore, the Linux-kernel definitions of rcu_read_lock() and
|
|||
|
rcu_read_unlock() must act as compiler barriers, at least for outermost
|
|||
|
instances of rcu_read_lock() and rcu_read_unlock() within a nested set
|
|||
|
of RCU read-side critical sections.
|
|||
|
|
|||
|
Energy Efficiency
|
|||
|
~~~~~~~~~~~~~~~~~
|
|||
|
|
|||
|
Interrupting idle CPUs is considered socially unacceptable, especially
|
|||
|
by people with battery-powered embedded systems. RCU therefore conserves
|
|||
|
energy by detecting which CPUs are idle, including tracking CPUs that
|
|||
|
have been interrupted from idle. This is a large part of the
|
|||
|
energy-efficiency requirement, so I learned of this via an irate phone
|
|||
|
call.
|
|||
|
|
|||
|
Because RCU avoids interrupting idle CPUs, it is illegal to execute an
|
|||
|
RCU read-side critical section on an idle CPU. (Kernels built with
|
|||
|
``CONFIG_PROVE_RCU=y`` will splat if you try it.) The RCU_NONIDLE()
|
|||
|
macro and ``_rcuidle`` event tracing is provided to work around this
|
|||
|
restriction. In addition, rcu_is_watching() may be used to test
|
|||
|
whether or not it is currently legal to run RCU read-side critical
|
|||
|
sections on this CPU. I learned of the need for diagnostics on the one
|
|||
|
hand and RCU_NONIDLE() on the other while inspecting idle-loop code.
|
|||
|
Steven Rostedt supplied ``_rcuidle`` event tracing, which is used quite
|
|||
|
heavily in the idle loop. However, there are some restrictions on the
|
|||
|
code placed within RCU_NONIDLE():
|
|||
|
|
|||
|
#. Blocking is prohibited. In practice, this is not a serious
|
|||
|
restriction given that idle tasks are prohibited from blocking to
|
|||
|
begin with.
|
|||
|
#. Although nesting RCU_NONIDLE() is permitted, they cannot nest
|
|||
|
indefinitely deeply. However, given that they can be nested on the
|
|||
|
order of a million deep, even on 32-bit systems, this should not be a
|
|||
|
serious restriction. This nesting limit would probably be reached
|
|||
|
long after the compiler OOMed or the stack overflowed.
|
|||
|
#. Any code path that enters RCU_NONIDLE() must sequence out of that
|
|||
|
same RCU_NONIDLE(). For example, the following is grossly
|
|||
|
illegal:
|
|||
|
|
|||
|
::
|
|||
|
|
|||
|
1 RCU_NONIDLE({
|
|||
|
2 do_something();
|
|||
|
3 goto bad_idea; /* BUG!!! */
|
|||
|
4 do_something_else();});
|
|||
|
5 bad_idea:
|
|||
|
|
|||
|
|
|||
|
It is just as illegal to transfer control into the middle of
|
|||
|
RCU_NONIDLE()'s argument. Yes, in theory, you could transfer in
|
|||
|
as long as you also transferred out, but in practice you could also
|
|||
|
expect to get sharply worded review comments.
|
|||
|
|
|||
|
It is similarly socially unacceptable to interrupt an ``nohz_full`` CPU
|
|||
|
running in userspace. RCU must therefore track ``nohz_full`` userspace
|
|||
|
execution. RCU must therefore be able to sample state at two points in
|
|||
|
time, and be able to determine whether or not some other CPU spent any
|
|||
|
time idle and/or executing in userspace.
|
|||
|
|
|||
|
These energy-efficiency requirements have proven quite difficult to
|
|||
|
understand and to meet, for example, there have been more than five
|
|||
|
clean-sheet rewrites of RCU's energy-efficiency code, the last of which
|
|||
|
was finally able to demonstrate `real energy savings running on real
|
|||
|
hardware
|
|||
|
[PDF] <http://www.rdrop.com/users/paulmck/realtime/paper/AMPenergy.2013.04.19a.pdf>`__.
|
|||
|
As noted earlier, I learned of many of these requirements via angry
|
|||
|
phone calls: Flaming me on the Linux-kernel mailing list was apparently
|
|||
|
not sufficient to fully vent their ire at RCU's energy-efficiency bugs!
|
|||
|
|
|||
|
Scheduling-Clock Interrupts and RCU
|
|||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|||
|
|
|||
|
The kernel transitions between in-kernel non-idle execution, userspace
|
|||
|
execution, and the idle loop. Depending on kernel configuration, RCU
|
|||
|
handles these states differently:
|
|||
|
|
|||
|
+-----------------+------------------+------------------+-----------------+
|
|||
|
| ``HZ`` Kconfig | In-Kernel | Usermode | Idle |
|
|||
|
+=================+==================+==================+=================+
|
|||
|
| ``HZ_PERIODIC`` | Can rely on | Can rely on | Can rely on |
|
|||
|
| | scheduling-clock | scheduling-clock | RCU's |
|
|||
|
| | interrupt. | interrupt and | dyntick-idle |
|
|||
|
| | | its detection | detection. |
|
|||
|
| | | of interrupt | |
|
|||
|
| | | from usermode. | |
|
|||
|
+-----------------+------------------+------------------+-----------------+
|
|||
|
| ``NO_HZ_IDLE`` | Can rely on | Can rely on | Can rely on |
|
|||
|
| | scheduling-clock | scheduling-clock | RCU's |
|
|||
|
| | interrupt. | interrupt and | dyntick-idle |
|
|||
|
| | | its detection | detection. |
|
|||
|
| | | of interrupt | |
|
|||
|
| | | from usermode. | |
|
|||
|
+-----------------+------------------+------------------+-----------------+
|
|||
|
| ``NO_HZ_FULL`` | Can only | Can rely on | Can rely on |
|
|||
|
| | sometimes rely | RCU's | RCU's |
|
|||
|
| | on | dyntick-idle | dyntick-idle |
|
|||
|
| | scheduling-clock | detection. | detection. |
|
|||
|
| | interrupt. In | | |
|
|||
|
| | other cases, it | | |
|
|||
|
| | is necessary to | | |
|
|||
|
| | bound kernel | | |
|
|||
|
| | execution times | | |
|
|||
|
| | and/or use | | |
|
|||
|
| | IPIs. | | |
|
|||
|
+-----------------+------------------+------------------+-----------------+
|
|||
|
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
| **Quick Quiz**: |
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
| Why can't ``NO_HZ_FULL`` in-kernel execution rely on the |
|
|||
|
| scheduling-clock interrupt, just like ``HZ_PERIODIC`` and |
|
|||
|
| ``NO_HZ_IDLE`` do? |
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
| **Answer**: |
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
| Because, as a performance optimization, ``NO_HZ_FULL`` does not |
|
|||
|
| necessarily re-enable the scheduling-clock interrupt on entry to each |
|
|||
|
| and every system call. |
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
|
|||
|
However, RCU must be reliably informed as to whether any given CPU is
|
|||
|
currently in the idle loop, and, for ``NO_HZ_FULL``, also whether that
|
|||
|
CPU is executing in usermode, as discussed
|
|||
|
`earlier <Energy Efficiency_>`__. It also requires that the
|
|||
|
scheduling-clock interrupt be enabled when RCU needs it to be:
|
|||
|
|
|||
|
#. If a CPU is either idle or executing in usermode, and RCU believes it
|
|||
|
is non-idle, the scheduling-clock tick had better be running.
|
|||
|
Otherwise, you will get RCU CPU stall warnings. Or at best, very long
|
|||
|
(11-second) grace periods, with a pointless IPI waking the CPU from
|
|||
|
time to time.
|
|||
|
#. If a CPU is in a portion of the kernel that executes RCU read-side
|
|||
|
critical sections, and RCU believes this CPU to be idle, you will get
|
|||
|
random memory corruption. **DON'T DO THIS!!!**
|
|||
|
This is one reason to test with lockdep, which will complain about
|
|||
|
this sort of thing.
|
|||
|
#. If a CPU is in a portion of the kernel that is absolutely positively
|
|||
|
no-joking guaranteed to never execute any RCU read-side critical
|
|||
|
sections, and RCU believes this CPU to be idle, no problem. This
|
|||
|
sort of thing is used by some architectures for light-weight
|
|||
|
exception handlers, which can then avoid the overhead of
|
|||
|
ct_irq_enter() and ct_irq_exit() at exception entry and
|
|||
|
exit, respectively. Some go further and avoid the entireties of
|
|||
|
irq_enter() and irq_exit().
|
|||
|
Just make very sure you are running some of your tests with
|
|||
|
``CONFIG_PROVE_RCU=y``, just in case one of your code paths was in
|
|||
|
fact joking about not doing RCU read-side critical sections.
|
|||
|
#. If a CPU is executing in the kernel with the scheduling-clock
|
|||
|
interrupt disabled and RCU believes this CPU to be non-idle, and if
|
|||
|
the CPU goes idle (from an RCU perspective) every few jiffies, no
|
|||
|
problem. It is usually OK for there to be the occasional gap between
|
|||
|
idle periods of up to a second or so.
|
|||
|
If the gap grows too long, you get RCU CPU stall warnings.
|
|||
|
#. If a CPU is either idle or executing in usermode, and RCU believes it
|
|||
|
to be idle, of course no problem.
|
|||
|
#. If a CPU is executing in the kernel, the kernel code path is passing
|
|||
|
through quiescent states at a reasonable frequency (preferably about
|
|||
|
once per few jiffies, but the occasional excursion to a second or so
|
|||
|
is usually OK) and the scheduling-clock interrupt is enabled, of
|
|||
|
course no problem.
|
|||
|
If the gap between a successive pair of quiescent states grows too
|
|||
|
long, you get RCU CPU stall warnings.
|
|||
|
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
| **Quick Quiz**: |
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
| But what if my driver has a hardware interrupt handler that can run |
|
|||
|
| for many seconds? I cannot invoke schedule() from an hardware |
|
|||
|
| interrupt handler, after all! |
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
| **Answer**: |
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
| One approach is to do ``ct_irq_exit();ct_irq_enter();`` every so |
|
|||
|
| often. But given that long-running interrupt handlers can cause other |
|
|||
|
| problems, not least for response time, shouldn't you work to keep |
|
|||
|
| your interrupt handler's runtime within reasonable bounds? |
|
|||
|
+-----------------------------------------------------------------------+
|
|||
|
|
|||
|
But as long as RCU is properly informed of kernel state transitions
|
|||
|
between in-kernel execution, usermode execution, and idle, and as long
|
|||
|
as the scheduling-clock interrupt is enabled when RCU needs it to be,
|
|||
|
you can rest assured that the bugs you encounter will be in some other
|
|||
|
part of RCU or some other part of the kernel!
|
|||
|
|
|||
|
Memory Efficiency
|
|||
|
~~~~~~~~~~~~~~~~~
|
|||
|
|
|||
|
Although small-memory non-realtime systems can simply use Tiny RCU, code
|
|||
|
size is only one aspect of memory efficiency. Another aspect is the size
|
|||
|
of the ``rcu_head`` structure used by call_rcu() and
|
|||
|
kfree_rcu(). Although this structure contains nothing more than a
|
|||
|
pair of pointers, it does appear in many RCU-protected data structures,
|
|||
|
including some that are size critical. The ``page`` structure is a case
|
|||
|
in point, as evidenced by the many occurrences of the ``union`` keyword
|
|||
|
within that structure.
|
|||
|
|
|||
|
This need for memory efficiency is one reason that RCU uses hand-crafted
|
|||
|
singly linked lists to track the ``rcu_head`` structures that are
|
|||
|
waiting for a grace period to elapse. It is also the reason why
|
|||
|
``rcu_head`` structures do not contain debug information, such as fields
|
|||
|
tracking the file and line of the call_rcu() or kfree_rcu() that
|
|||
|
posted them. Although this information might appear in debug-only kernel
|
|||
|
builds at some point, in the meantime, the ``->func`` field will often
|
|||
|
provide the needed debug information.
|
|||
|
|
|||
|
However, in some cases, the need for memory efficiency leads to even
|
|||
|
more extreme measures. Returning to the ``page`` structure, the
|
|||
|
``rcu_head`` field shares storage with a great many other structures
|
|||
|
that are used at various points in the corresponding page's lifetime. In
|
|||
|
order to correctly resolve certain `race
|
|||
|
conditions <https://lore.kernel.org/r/1439976106-137226-1-git-send-email-kirill.shutemov@linux.intel.com>`__,
|
|||
|
the Linux kernel's memory-management subsystem needs a particular bit to
|
|||
|
remain zero during all phases of grace-period processing, and that bit
|
|||
|
happens to map to the bottom bit of the ``rcu_head`` structure's
|
|||
|
``->next`` field. RCU makes this guarantee as long as call_rcu() is
|
|||
|
used to post the callback, as opposed to kfree_rcu() or some future
|
|||
|
“lazy” variant of call_rcu() that might one day be created for
|
|||
|
energy-efficiency purposes.
|
|||
|
|
|||
|
That said, there are limits. RCU requires that the ``rcu_head``
|
|||
|
structure be aligned to a two-byte boundary, and passing a misaligned
|
|||
|
``rcu_head`` structure to one of the call_rcu() family of functions
|
|||
|
will result in a splat. It is therefore necessary to exercise caution
|
|||
|
when packing structures containing fields of type ``rcu_head``. Why not
|
|||
|
a four-byte or even eight-byte alignment requirement? Because the m68k
|
|||
|
architecture provides only two-byte alignment, and thus acts as
|
|||
|
alignment's least common denominator.
|
|||
|
|
|||
|
The reason for reserving the bottom bit of pointers to ``rcu_head``
|
|||
|
structures is to leave the door open to “lazy” callbacks whose
|
|||
|
invocations can safely be deferred. Deferring invocation could
|
|||
|
potentially have energy-efficiency benefits, but only if the rate of
|
|||
|
non-lazy callbacks decreases significantly for some important workload.
|
|||
|
In the meantime, reserving the bottom bit keeps this option open in case
|
|||
|
it one day becomes useful.
|
|||
|
|
|||
|
Performance, Scalability, Response Time, and Reliability
|
|||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|||
|
|
|||
|
Expanding on the `earlier
|
|||
|
discussion <Performance and Scalability_>`__, RCU is used heavily by
|
|||
|
hot code paths in performance-critical portions of the Linux kernel's
|
|||
|
networking, security, virtualization, and scheduling code paths. RCU
|
|||
|
must therefore use efficient implementations, especially in its
|
|||
|
read-side primitives. To that end, it would be good if preemptible RCU's
|
|||
|
implementation of rcu_read_lock() could be inlined, however, doing
|
|||
|
this requires resolving ``#include`` issues with the ``task_struct``
|
|||
|
structure.
|
|||
|
|
|||
|
The Linux kernel supports hardware configurations with up to 4096 CPUs,
|
|||
|
which means that RCU must be extremely scalable. Algorithms that involve
|
|||
|
frequent acquisitions of global locks or frequent atomic operations on
|
|||
|
global variables simply cannot be tolerated within the RCU
|
|||
|
implementation. RCU therefore makes heavy use of a combining tree based
|
|||
|
on the ``rcu_node`` structure. RCU is required to tolerate all CPUs
|
|||
|
continuously invoking any combination of RCU's runtime primitives with
|
|||
|
minimal per-operation overhead. In fact, in many cases, increasing load
|
|||
|
must *decrease* the per-operation overhead, witness the batching
|
|||
|
optimizations for synchronize_rcu(), call_rcu(),
|
|||
|
synchronize_rcu_expedited(), and rcu_barrier(). As a general
|
|||
|
rule, RCU must cheerfully accept whatever the rest of the Linux kernel
|
|||
|
decides to throw at it.
|
|||
|
|
|||
|
The Linux kernel is used for real-time workloads, especially in
|
|||
|
conjunction with the `-rt
|
|||
|
patchset <https://wiki.linuxfoundation.org/realtime/>`__. The
|
|||
|
real-time-latency response requirements are such that the traditional
|
|||
|
approach of disabling preemption across RCU read-side critical sections
|
|||
|
is inappropriate. Kernels built with ``CONFIG_PREEMPTION=y`` therefore use
|
|||
|
an RCU implementation that allows RCU read-side critical sections to be
|
|||
|
preempted. This requirement made its presence known after users made it
|
|||
|
clear that an earlier `real-time
|
|||
|
patch <https://lwn.net/Articles/107930/>`__ did not meet their needs, in
|
|||
|
conjunction with some `RCU
|
|||
|
issues <https://lore.kernel.org/r/20050318002026.GA2693@us.ibm.com>`__
|
|||
|
encountered by a very early version of the -rt patchset.
|
|||
|
|
|||
|
In addition, RCU must make do with a sub-100-microsecond real-time
|
|||
|
latency budget. In fact, on smaller systems with the -rt patchset, the
|
|||
|
Linux kernel provides sub-20-microsecond real-time latencies for the
|
|||
|
whole kernel, including RCU. RCU's scalability and latency must
|
|||
|
therefore be sufficient for these sorts of configurations. To my
|
|||
|
surprise, the sub-100-microsecond real-time latency budget `applies to
|
|||
|
even the largest systems
|
|||
|
[PDF] <http://www.rdrop.com/users/paulmck/realtime/paper/bigrt.2013.01.31a.LCA.pdf>`__,
|
|||
|
up to and including systems with 4096 CPUs. This real-time requirement
|
|||
|
motivated the grace-period kthread, which also simplified handling of a
|
|||
|
number of race conditions.
|
|||
|
|
|||
|
RCU must avoid degrading real-time response for CPU-bound threads,
|
|||
|
whether executing in usermode (which is one use case for
|
|||
|
``CONFIG_NO_HZ_FULL=y``) or in the kernel. That said, CPU-bound loops in
|
|||
|
the kernel must execute cond_resched() at least once per few tens of
|
|||
|
milliseconds in order to avoid receiving an IPI from RCU.
|
|||
|
|
|||
|
Finally, RCU's status as a synchronization primitive means that any RCU
|
|||
|
failure can result in arbitrary memory corruption that can be extremely
|
|||
|
difficult to debug. This means that RCU must be extremely reliable,
|
|||
|
which in practice also means that RCU must have an aggressive
|
|||
|
stress-test suite. This stress-test suite is called ``rcutorture``.
|
|||
|
|
|||
|
Although the need for ``rcutorture`` was no surprise, the current
|
|||
|
immense popularity of the Linux kernel is posing interesting—and perhaps
|
|||
|
unprecedented—validation challenges. To see this, keep in mind that
|
|||
|
there are well over one billion instances of the Linux kernel running
|
|||
|
today, given Android smartphones, Linux-powered televisions, and
|
|||
|
servers. This number can be expected to increase sharply with the advent
|
|||
|
of the celebrated Internet of Things.
|
|||
|
|
|||
|
Suppose that RCU contains a race condition that manifests on average
|
|||
|
once per million years of runtime. This bug will be occurring about
|
|||
|
three times per *day* across the installed base. RCU could simply hide
|
|||
|
behind hardware error rates, given that no one should really expect
|
|||
|
their smartphone to last for a million years. However, anyone taking too
|
|||
|
much comfort from this thought should consider the fact that in most
|
|||
|
jurisdictions, a successful multi-year test of a given mechanism, which
|
|||
|
might include a Linux kernel, suffices for a number of types of
|
|||
|
safety-critical certifications. In fact, rumor has it that the Linux
|
|||
|
kernel is already being used in production for safety-critical
|
|||
|
applications. I don't know about you, but I would feel quite bad if a
|
|||
|
bug in RCU killed someone. Which might explain my recent focus on
|
|||
|
validation and verification.
|
|||
|
|
|||
|
Other RCU Flavors
|
|||
|
-----------------
|
|||
|
|
|||
|
One of the more surprising things about RCU is that there are now no
|
|||
|
fewer than five *flavors*, or API families. In addition, the primary
|
|||
|
flavor that has been the sole focus up to this point has two different
|
|||
|
implementations, non-preemptible and preemptible. The other four flavors
|
|||
|
are listed below, with requirements for each described in a separate
|
|||
|
section.
|
|||
|
|
|||
|
#. `Bottom-Half Flavor (Historical)`_
|
|||
|
#. `Sched Flavor (Historical)`_
|
|||
|
#. `Sleepable RCU`_
|
|||
|
#. `Tasks RCU`_
|
|||
|
|
|||
|
Bottom-Half Flavor (Historical)
|
|||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|||
|
|
|||
|
The RCU-bh flavor of RCU has since been expressed in terms of the other
|
|||
|
RCU flavors as part of a consolidation of the three flavors into a
|
|||
|
single flavor. The read-side API remains, and continues to disable
|
|||
|
softirq and to be accounted for by lockdep. Much of the material in this
|
|||
|
section is therefore strictly historical in nature.
|
|||
|
|
|||
|
The softirq-disable (AKA “bottom-half”, hence the “_bh” abbreviations)
|
|||
|
flavor of RCU, or *RCU-bh*, was developed by Dipankar Sarma to provide a
|
|||
|
flavor of RCU that could withstand the network-based denial-of-service
|
|||
|
attacks researched by Robert Olsson. These attacks placed so much
|
|||
|
networking load on the system that some of the CPUs never exited softirq
|
|||
|
execution, which in turn prevented those CPUs from ever executing a
|
|||
|
context switch, which, in the RCU implementation of that time, prevented
|
|||
|
grace periods from ever ending. The result was an out-of-memory
|
|||
|
condition and a system hang.
|
|||
|
|
|||
|
The solution was the creation of RCU-bh, which does
|
|||
|
local_bh_disable() across its read-side critical sections, and which
|
|||
|
uses the transition from one type of softirq processing to another as a
|
|||
|
quiescent state in addition to context switch, idle, user mode, and
|
|||
|
offline. This means that RCU-bh grace periods can complete even when
|
|||
|
some of the CPUs execute in softirq indefinitely, thus allowing
|
|||
|
algorithms based on RCU-bh to withstand network-based denial-of-service
|
|||
|
attacks.
|
|||
|
|
|||
|
Because rcu_read_lock_bh() and rcu_read_unlock_bh() disable and
|
|||
|
re-enable softirq handlers, any attempt to start a softirq handlers
|
|||
|
during the RCU-bh read-side critical section will be deferred. In this
|
|||
|
case, rcu_read_unlock_bh() will invoke softirq processing, which can
|
|||
|
take considerable time. One can of course argue that this softirq
|
|||
|
overhead should be associated with the code following the RCU-bh
|
|||
|
read-side critical section rather than rcu_read_unlock_bh(), but the
|
|||
|
fact is that most profiling tools cannot be expected to make this sort
|
|||
|
of fine distinction. For example, suppose that a three-millisecond-long
|
|||
|
RCU-bh read-side critical section executes during a time of heavy
|
|||
|
networking load. There will very likely be an attempt to invoke at least
|
|||
|
one softirq handler during that three milliseconds, but any such
|
|||
|
invocation will be delayed until the time of the
|
|||
|
rcu_read_unlock_bh(). This can of course make it appear at first
|
|||
|
glance as if rcu_read_unlock_bh() was executing very slowly.
|
|||
|
|
|||
|
The `RCU-bh
|
|||
|
API <https://lwn.net/Articles/609973/#RCU%20Per-Flavor%20API%20Table>`__
|
|||
|
includes rcu_read_lock_bh(), rcu_read_unlock_bh(), rcu_dereference_bh(),
|
|||
|
rcu_dereference_bh_check(), and rcu_read_lock_bh_held(). However, the
|
|||
|
old RCU-bh update-side APIs are now gone, replaced by synchronize_rcu(),
|
|||
|
synchronize_rcu_expedited(), call_rcu(), and rcu_barrier(). In addition,
|
|||
|
anything that disables bottom halves also marks an RCU-bh read-side
|
|||
|
critical section, including local_bh_disable() and local_bh_enable(),
|
|||
|
local_irq_save() and local_irq_restore(), and so on.
|
|||
|
|
|||
|
Sched Flavor (Historical)
|
|||
|
~~~~~~~~~~~~~~~~~~~~~~~~~
|
|||
|
|
|||
|
The RCU-sched flavor of RCU has since been expressed in terms of the
|
|||
|
other RCU flavors as part of a consolidation of the three flavors into a
|
|||
|
single flavor. The read-side API remains, and continues to disable
|
|||
|
preemption and to be accounted for by lockdep. Much of the material in
|
|||
|
this section is therefore strictly historical in nature.
|
|||
|
|
|||
|
Before preemptible RCU, waiting for an RCU grace period had the side
|
|||
|
effect of also waiting for all pre-existing interrupt and NMI handlers.
|
|||
|
However, there are legitimate preemptible-RCU implementations that do
|
|||
|
not have this property, given that any point in the code outside of an
|
|||
|
RCU read-side critical section can be a quiescent state. Therefore,
|
|||
|
*RCU-sched* was created, which follows “classic” RCU in that an
|
|||
|
RCU-sched grace period waits for pre-existing interrupt and NMI
|
|||
|
handlers. In kernels built with ``CONFIG_PREEMPTION=n``, the RCU and
|
|||
|
RCU-sched APIs have identical implementations, while kernels built with
|
|||
|
``CONFIG_PREEMPTION=y`` provide a separate implementation for each.
|
|||
|
|
|||
|
Note well that in ``CONFIG_PREEMPTION=y`` kernels,
|
|||
|
rcu_read_lock_sched() and rcu_read_unlock_sched() disable and
|
|||
|
re-enable preemption, respectively. This means that if there was a
|
|||
|
preemption attempt during the RCU-sched read-side critical section,
|
|||
|
rcu_read_unlock_sched() will enter the scheduler, with all the
|
|||
|
latency and overhead entailed. Just as with rcu_read_unlock_bh(),
|
|||
|
this can make it look as if rcu_read_unlock_sched() was executing
|
|||
|
very slowly. However, the highest-priority task won't be preempted, so
|
|||
|
that task will enjoy low-overhead rcu_read_unlock_sched()
|
|||
|
invocations.
|
|||
|
|
|||
|
The `RCU-sched
|
|||
|
API <https://lwn.net/Articles/609973/#RCU%20Per-Flavor%20API%20Table>`__
|
|||
|
includes rcu_read_lock_sched(), rcu_read_unlock_sched(),
|
|||
|
rcu_read_lock_sched_notrace(), rcu_read_unlock_sched_notrace(),
|
|||
|
rcu_dereference_sched(), rcu_dereference_sched_check(), and
|
|||
|
rcu_read_lock_sched_held(). However, the old RCU-sched update-side APIs
|
|||
|
are now gone, replaced by synchronize_rcu(), synchronize_rcu_expedited(),
|
|||
|
call_rcu(), and rcu_barrier(). In addition, anything that disables
|
|||
|
preemption also marks an RCU-sched read-side critical section,
|
|||
|
including preempt_disable() and preempt_enable(), local_irq_save()
|
|||
|
and local_irq_restore(), and so on.
|
|||
|
|
|||
|
Sleepable RCU
|
|||
|
~~~~~~~~~~~~~
|
|||
|
|
|||
|
For well over a decade, someone saying “I need to block within an RCU
|
|||
|
read-side critical section” was a reliable indication that this someone
|
|||
|
did not understand RCU. After all, if you are always blocking in an RCU
|
|||
|
read-side critical section, you can probably afford to use a
|
|||
|
higher-overhead synchronization mechanism. However, that changed with
|
|||
|
the advent of the Linux kernel's notifiers, whose RCU read-side critical
|
|||
|
sections almost never sleep, but sometimes need to. This resulted in the
|
|||
|
introduction of `sleepable RCU <https://lwn.net/Articles/202847/>`__, or
|
|||
|
*SRCU*.
|
|||
|
|
|||
|
SRCU allows different domains to be defined, with each such domain
|
|||
|
defined by an instance of an ``srcu_struct`` structure. A pointer to
|
|||
|
this structure must be passed in to each SRCU function, for example,
|
|||
|
``synchronize_srcu(&ss)``, where ``ss`` is the ``srcu_struct``
|
|||
|
structure. The key benefit of these domains is that a slow SRCU reader
|
|||
|
in one domain does not delay an SRCU grace period in some other domain.
|
|||
|
That said, one consequence of these domains is that read-side code must
|
|||
|
pass a “cookie” from srcu_read_lock() to srcu_read_unlock(), for
|
|||
|
example, as follows:
|
|||
|
|
|||
|
::
|
|||
|
|
|||
|
1 int idx;
|
|||
|
2
|
|||
|
3 idx = srcu_read_lock(&ss);
|
|||
|
4 do_something();
|
|||
|
5 srcu_read_unlock(&ss, idx);
|
|||
|
|
|||
|
As noted above, it is legal to block within SRCU read-side critical
|
|||
|
sections, however, with great power comes great responsibility. If you
|
|||
|
block forever in one of a given domain's SRCU read-side critical
|
|||
|
sections, then that domain's grace periods will also be blocked forever.
|
|||
|
Of course, one good way to block forever is to deadlock, which can
|
|||
|
happen if any operation in a given domain's SRCU read-side critical
|
|||
|
section can wait, either directly or indirectly, for that domain's grace
|
|||
|
period to elapse. For example, this results in a self-deadlock:
|
|||
|
|
|||
|
::
|
|||
|
|
|||
|
1 int idx;
|
|||
|
2
|
|||
|
3 idx = srcu_read_lock(&ss);
|
|||
|
4 do_something();
|
|||
|
5 synchronize_srcu(&ss);
|
|||
|
6 srcu_read_unlock(&ss, idx);
|
|||
|
|
|||
|
However, if line 5 acquired a mutex that was held across a
|
|||
|
synchronize_srcu() for domain ``ss``, deadlock would still be
|
|||
|
possible. Furthermore, if line 5 acquired a mutex that was held across a
|
|||
|
synchronize_srcu() for some other domain ``ss1``, and if an
|
|||
|
``ss1``-domain SRCU read-side critical section acquired another mutex
|
|||
|
that was held across as ``ss``-domain synchronize_srcu(), deadlock
|
|||
|
would again be possible. Such a deadlock cycle could extend across an
|
|||
|
arbitrarily large number of different SRCU domains. Again, with great
|
|||
|
power comes great responsibility.
|
|||
|
|
|||
|
Unlike the other RCU flavors, SRCU read-side critical sections can run
|
|||
|
on idle and even offline CPUs. This ability requires that
|
|||
|
srcu_read_lock() and srcu_read_unlock() contain memory barriers,
|
|||
|
which means that SRCU readers will run a bit slower than would RCU
|
|||
|
readers. It also motivates the smp_mb__after_srcu_read_unlock() API,
|
|||
|
which, in combination with srcu_read_unlock(), guarantees a full
|
|||
|
memory barrier.
|
|||
|
|
|||
|
Also unlike other RCU flavors, synchronize_srcu() may **not** be
|
|||
|
invoked from CPU-hotplug notifiers, due to the fact that SRCU grace
|
|||
|
periods make use of timers and the possibility of timers being
|
|||
|
temporarily “stranded” on the outgoing CPU. This stranding of timers
|
|||
|
means that timers posted to the outgoing CPU will not fire until late in
|
|||
|
the CPU-hotplug process. The problem is that if a notifier is waiting on
|
|||
|
an SRCU grace period, that grace period is waiting on a timer, and that
|
|||
|
timer is stranded on the outgoing CPU, then the notifier will never be
|
|||
|
awakened, in other words, deadlock has occurred. This same situation of
|
|||
|
course also prohibits srcu_barrier() from being invoked from
|
|||
|
CPU-hotplug notifiers.
|
|||
|
|
|||
|
SRCU also differs from other RCU flavors in that SRCU's expedited and
|
|||
|
non-expedited grace periods are implemented by the same mechanism. This
|
|||
|
means that in the current SRCU implementation, expediting a future grace
|
|||
|
period has the side effect of expediting all prior grace periods that
|
|||
|
have not yet completed. (But please note that this is a property of the
|
|||
|
current implementation, not necessarily of future implementations.) In
|
|||
|
addition, if SRCU has been idle for longer than the interval specified
|
|||
|
by the ``srcutree.exp_holdoff`` kernel boot parameter (25 microseconds
|
|||
|
by default), and if a synchronize_srcu() invocation ends this idle
|
|||
|
period, that invocation will be automatically expedited.
|
|||
|
|
|||
|
As of v4.12, SRCU's callbacks are maintained per-CPU, eliminating a
|
|||
|
locking bottleneck present in prior kernel versions. Although this will
|
|||
|
allow users to put much heavier stress on call_srcu(), it is
|
|||
|
important to note that SRCU does not yet take any special steps to deal
|
|||
|
with callback flooding. So if you are posting (say) 10,000 SRCU
|
|||
|
callbacks per second per CPU, you are probably totally OK, but if you
|
|||
|
intend to post (say) 1,000,000 SRCU callbacks per second per CPU, please
|
|||
|
run some tests first. SRCU just might need a few adjustment to deal with
|
|||
|
that sort of load. Of course, your mileage may vary based on the speed
|
|||
|
of your CPUs and the size of your memory.
|
|||
|
|
|||
|
The `SRCU
|
|||
|
API <https://lwn.net/Articles/609973/#RCU%20Per-Flavor%20API%20Table>`__
|
|||
|
includes srcu_read_lock(), srcu_read_unlock(),
|
|||
|
srcu_dereference(), srcu_dereference_check(),
|
|||
|
synchronize_srcu(), synchronize_srcu_expedited(),
|
|||
|
call_srcu(), srcu_barrier(), and srcu_read_lock_held(). It
|
|||
|
also includes DEFINE_SRCU(), DEFINE_STATIC_SRCU(), and
|
|||
|
init_srcu_struct() APIs for defining and initializing
|
|||
|
``srcu_struct`` structures.
|
|||
|
|
|||
|
More recently, the SRCU API has added polling interfaces:
|
|||
|
|
|||
|
#. start_poll_synchronize_srcu() returns a cookie identifying
|
|||
|
the completion of a future SRCU grace period and ensures
|
|||
|
that this grace period will be started.
|
|||
|
#. poll_state_synchronize_srcu() returns ``true`` iff the
|
|||
|
specified cookie corresponds to an already-completed
|
|||
|
SRCU grace period.
|
|||
|
#. get_state_synchronize_srcu() returns a cookie just like
|
|||
|
start_poll_synchronize_srcu() does, but differs in that
|
|||
|
it does nothing to ensure that any future SRCU grace period
|
|||
|
will be started.
|
|||
|
|
|||
|
These functions are used to avoid unnecessary SRCU grace periods in
|
|||
|
certain types of buffer-cache algorithms having multi-stage age-out
|
|||
|
mechanisms. The idea is that by the time the block has aged completely
|
|||
|
from the cache, an SRCU grace period will be very likely to have elapsed.
|
|||
|
|
|||
|
Tasks RCU
|
|||
|
~~~~~~~~~
|
|||
|
|
|||
|
Some forms of tracing use “trampolines” to handle the binary rewriting
|
|||
|
required to install different types of probes. It would be good to be
|
|||
|
able to free old trampolines, which sounds like a job for some form of
|
|||
|
RCU. However, because it is necessary to be able to install a trace
|
|||
|
anywhere in the code, it is not possible to use read-side markers such
|
|||
|
as rcu_read_lock() and rcu_read_unlock(). In addition, it does
|
|||
|
not work to have these markers in the trampoline itself, because there
|
|||
|
would need to be instructions following rcu_read_unlock(). Although
|
|||
|
synchronize_rcu() would guarantee that execution reached the
|
|||
|
rcu_read_unlock(), it would not be able to guarantee that execution
|
|||
|
had completely left the trampoline. Worse yet, in some situations
|
|||
|
the trampoline's protection must extend a few instructions *prior* to
|
|||
|
execution reaching the trampoline. For example, these few instructions
|
|||
|
might calculate the address of the trampoline, so that entering the
|
|||
|
trampoline would be pre-ordained a surprisingly long time before execution
|
|||
|
actually reached the trampoline itself.
|
|||
|
|
|||
|
The solution, in the form of `Tasks
|
|||
|
RCU <https://lwn.net/Articles/607117/>`__, is to have implicit read-side
|
|||
|
critical sections that are delimited by voluntary context switches, that
|
|||
|
is, calls to schedule(), cond_resched(), and
|
|||
|
synchronize_rcu_tasks(). In addition, transitions to and from
|
|||
|
userspace execution also delimit tasks-RCU read-side critical sections.
|
|||
|
|
|||
|
The tasks-RCU API is quite compact, consisting only of
|
|||
|
call_rcu_tasks(), synchronize_rcu_tasks(), and
|
|||
|
rcu_barrier_tasks(). In ``CONFIG_PREEMPTION=n`` kernels, trampolines
|
|||
|
cannot be preempted, so these APIs map to call_rcu(),
|
|||
|
synchronize_rcu(), and rcu_barrier(), respectively. In
|
|||
|
``CONFIG_PREEMPTION=y`` kernels, trampolines can be preempted, and these
|
|||
|
three APIs are therefore implemented by separate functions that check
|
|||
|
for voluntary context switches.
|
|||
|
|
|||
|
Tasks Rude RCU
|
|||
|
~~~~~~~~~~~~~~
|
|||
|
|
|||
|
Some forms of tracing need to wait for all preemption-disabled regions
|
|||
|
of code running on any online CPU, including those executed when RCU is
|
|||
|
not watching. This means that synchronize_rcu() is insufficient, and
|
|||
|
Tasks Rude RCU must be used instead. This flavor of RCU does its work by
|
|||
|
forcing a workqueue to be scheduled on each online CPU, hence the "Rude"
|
|||
|
moniker. And this operation is considered to be quite rude by real-time
|
|||
|
workloads that don't want their ``nohz_full`` CPUs receiving IPIs and
|
|||
|
by battery-powered systems that don't want their idle CPUs to be awakened.
|
|||
|
|
|||
|
The tasks-rude-RCU API is also reader-marking-free and thus quite compact,
|
|||
|
consisting of call_rcu_tasks_rude(), synchronize_rcu_tasks_rude(),
|
|||
|
and rcu_barrier_tasks_rude().
|
|||
|
|
|||
|
Tasks Trace RCU
|
|||
|
~~~~~~~~~~~~~~~
|
|||
|
|
|||
|
Some forms of tracing need to sleep in readers, but cannot tolerate
|
|||
|
SRCU's read-side overhead, which includes a full memory barrier in both
|
|||
|
srcu_read_lock() and srcu_read_unlock(). This need is handled by a
|
|||
|
Tasks Trace RCU that uses scheduler locking and IPIs to synchronize with
|
|||
|
readers. Real-time systems that cannot tolerate IPIs may build their
|
|||
|
kernels with ``CONFIG_TASKS_TRACE_RCU_READ_MB=y``, which avoids the IPIs at
|
|||
|
the expense of adding full memory barriers to the read-side primitives.
|
|||
|
|
|||
|
The tasks-trace-RCU API is also reasonably compact,
|
|||
|
consisting of rcu_read_lock_trace(), rcu_read_unlock_trace(),
|
|||
|
rcu_read_lock_trace_held(), call_rcu_tasks_trace(),
|
|||
|
synchronize_rcu_tasks_trace(), and rcu_barrier_tasks_trace().
|
|||
|
|
|||
|
Possible Future Changes
|
|||
|
-----------------------
|
|||
|
|
|||
|
One of the tricks that RCU uses to attain update-side scalability is to
|
|||
|
increase grace-period latency with increasing numbers of CPUs. If this
|
|||
|
becomes a serious problem, it will be necessary to rework the
|
|||
|
grace-period state machine so as to avoid the need for the additional
|
|||
|
latency.
|
|||
|
|
|||
|
RCU disables CPU hotplug in a few places, perhaps most notably in the
|
|||
|
rcu_barrier() operations. If there is a strong reason to use
|
|||
|
rcu_barrier() in CPU-hotplug notifiers, it will be necessary to
|
|||
|
avoid disabling CPU hotplug. This would introduce some complexity, so
|
|||
|
there had better be a *very* good reason.
|
|||
|
|
|||
|
The tradeoff between grace-period latency on the one hand and
|
|||
|
interruptions of other CPUs on the other hand may need to be
|
|||
|
re-examined. The desire is of course for zero grace-period latency as
|
|||
|
well as zero interprocessor interrupts undertaken during an expedited
|
|||
|
grace period operation. While this ideal is unlikely to be achievable,
|
|||
|
it is quite possible that further improvements can be made.
|
|||
|
|
|||
|
The multiprocessor implementations of RCU use a combining tree that
|
|||
|
groups CPUs so as to reduce lock contention and increase cache locality.
|
|||
|
However, this combining tree does not spread its memory across NUMA
|
|||
|
nodes nor does it align the CPU groups with hardware features such as
|
|||
|
sockets or cores. Such spreading and alignment is currently believed to
|
|||
|
be unnecessary because the hotpath read-side primitives do not access
|
|||
|
the combining tree, nor does call_rcu() in the common case. If you
|
|||
|
believe that your architecture needs such spreading and alignment, then
|
|||
|
your architecture should also benefit from the
|
|||
|
``rcutree.rcu_fanout_leaf`` boot parameter, which can be set to the
|
|||
|
number of CPUs in a socket, NUMA node, or whatever. If the number of
|
|||
|
CPUs is too large, use a fraction of the number of CPUs. If the number
|
|||
|
of CPUs is a large prime number, well, that certainly is an
|
|||
|
“interesting” architectural choice! More flexible arrangements might be
|
|||
|
considered, but only if ``rcutree.rcu_fanout_leaf`` has proven
|
|||
|
inadequate, and only if the inadequacy has been demonstrated by a
|
|||
|
carefully run and realistic system-level workload.
|
|||
|
|
|||
|
Please note that arrangements that require RCU to remap CPU numbers will
|
|||
|
require extremely good demonstration of need and full exploration of
|
|||
|
alternatives.
|
|||
|
|
|||
|
RCU's various kthreads are reasonably recent additions. It is quite
|
|||
|
likely that adjustments will be required to more gracefully handle
|
|||
|
extreme loads. It might also be necessary to be able to relate CPU
|
|||
|
utilization by RCU's kthreads and softirq handlers to the code that
|
|||
|
instigated this CPU utilization. For example, RCU callback overhead
|
|||
|
might be charged back to the originating call_rcu() instance, though
|
|||
|
probably not in production kernels.
|
|||
|
|
|||
|
Additional work may be required to provide reasonable forward-progress
|
|||
|
guarantees under heavy load for grace periods and for callback
|
|||
|
invocation.
|
|||
|
|
|||
|
Summary
|
|||
|
-------
|
|||
|
|
|||
|
This document has presented more than two decade's worth of RCU
|
|||
|
requirements. Given that the requirements keep changing, this will not
|
|||
|
be the last word on this subject, but at least it serves to get an
|
|||
|
important subset of the requirements set forth.
|
|||
|
|
|||
|
Acknowledgments
|
|||
|
---------------
|
|||
|
|
|||
|
I am grateful to Steven Rostedt, Lai Jiangshan, Ingo Molnar, Oleg
|
|||
|
Nesterov, Borislav Petkov, Peter Zijlstra, Boqun Feng, and Andy
|
|||
|
Lutomirski for their help in rendering this article human readable, and
|
|||
|
to Michelle Rankin for her support of this effort. Other contributions
|
|||
|
are acknowledged in the Linux kernel's git archive.
|