documentation: Add synchronize_rcu_mult() to the requirements
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
This commit is contained in:
parent
41abcf321d
commit
f43b62542e
|
@ -2231,6 +2231,8 @@ described in a separate section.
|
|||
<li> <a href="#Sched Flavor">Sched Flavor</a>
|
||||
<li> <a href="#Sleepable RCU">Sleepable RCU</a>
|
||||
<li> <a href="#Tasks RCU">Tasks RCU</a>
|
||||
<li> <a href="#Waiting for Multiple Grace Periods">
|
||||
Waiting for Multiple Grace Periods</a>
|
||||
</ol>
|
||||
|
||||
<h3><a name="Bottom-Half Flavor">Bottom-Half Flavor</a></h3>
|
||||
|
@ -2480,6 +2482,81 @@ The tasks-RCU API is quite compact, consisting only of
|
|||
<tt>synchronize_rcu_tasks()</tt>, and
|
||||
<tt>rcu_barrier_tasks()</tt>.
|
||||
|
||||
<h3><a name="Waiting for Multiple Grace Periods">
|
||||
Waiting for Multiple Grace Periods</a></h3>
|
||||
|
||||
<p>
|
||||
Perhaps you have an RCU protected data structure that is accessed from
|
||||
RCU read-side critical sections, from softirq handlers, and from
|
||||
hardware interrupt handlers.
|
||||
That is three flavors of RCU, the normal flavor, the bottom-half flavor,
|
||||
and the sched flavor.
|
||||
How to wait for a compound grace period?
|
||||
|
||||
<p>
|
||||
The best approach is usually to “just say no!” and
|
||||
insert <tt>rcu_read_lock()</tt> and <tt>rcu_read_unlock()</tt>
|
||||
around each RCU read-side critical section, regardless of what
|
||||
environment it happens to be in.
|
||||
But suppose that some of the RCU read-side critical sections are
|
||||
on extremely hot code paths, and that use of <tt>CONFIG_PREEMPT=n</tt>
|
||||
is not a viable option, so that <tt>rcu_read_lock()</tt> and
|
||||
<tt>rcu_read_unlock()</tt> are not free.
|
||||
What then?
|
||||
|
||||
<p>
|
||||
You <i>could</i> wait on all three grace periods in succession, as follows:
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
1 synchronize_rcu();
|
||||
2 synchronize_rcu_bh();
|
||||
3 synchronize_sched();
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<p>
|
||||
This works, but triples the update-side latency penalty.
|
||||
In cases where this is not acceptable, <tt>synchronize_rcu_mult()</tt>
|
||||
may be used to wait on all three flavors of grace period concurrently:
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
1 synchronize_rcu_mult(call_rcu, call_rcu_bh, call_rcu_sched);
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<p>
|
||||
But what if it is necessary to also wait on SRCU?
|
||||
This can be done as follows:
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
1 static void call_my_srcu(struct rcu_head *head,
|
||||
2 void (*func)(struct rcu_head *head))
|
||||
3 {
|
||||
4 call_srcu(&my_srcu, head, func);
|
||||
5 }
|
||||
6
|
||||
7 synchronize_rcu_mult(call_rcu, call_rcu_bh, call_rcu_sched, call_my_srcu);
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<p>
|
||||
If you needed to wait on multiple different flavors of SRCU
|
||||
(but why???), you would need to create a wrapper function resembling
|
||||
<tt>call_my_srcu()</tt> for each SRCU flavor.
|
||||
|
||||
<p><a name="Quick Quiz 15"><b>Quick Quiz 15</b>:</a>
|
||||
But what if I need to wait for multiple RCU flavors, but I also need
|
||||
the grace periods to be expedited?
|
||||
<br><a href="#qq15answer">Answer</a>
|
||||
|
||||
<p>
|
||||
Again, it is usually better to adjust the RCU read-side critical sections
|
||||
to use a single flavor of RCU, but when this is not feasible, you can use
|
||||
<tt>synchronize_rcu_mult()</tt>.
|
||||
|
||||
<h2><a name="Possible Future Changes">Possible Future Changes</a></h2>
|
||||
|
||||
<p>
|
||||
|
@ -2901,5 +2978,20 @@ during scheduler initialization.
|
|||
|
||||
</p><p><a href="#Quick%20Quiz%2014"><b>Back to Quick Quiz 14</b>.</a>
|
||||
|
||||
<a name="qq15answer"></a>
|
||||
<p><b>Quick Quiz 15</b>:
|
||||
But what if I need to wait for multiple RCU flavors, but I also need
|
||||
the grace periods to be expedited?
|
||||
|
||||
|
||||
</p><p><b>Answer</b>:
|
||||
If you are using expedited grace periods, there should be less penalty
|
||||
for waiting on them in succession.
|
||||
But if that is nevertheless a problem, you can use workqueues or multiple
|
||||
kthreads to wait on the various expedited grace periods concurrently.
|
||||
|
||||
|
||||
</p><p><a href="#Quick%20Quiz%2015"><b>Back to Quick Quiz 15</b>.</a>
|
||||
|
||||
|
||||
</body></html>
|
||||
|
|
|
@ -2398,6 +2398,8 @@ described in a separate section.
|
|||
<li> <a href="#Sched Flavor">Sched Flavor</a>
|
||||
<li> <a href="#Sleepable RCU">Sleepable RCU</a>
|
||||
<li> <a href="#Tasks RCU">Tasks RCU</a>
|
||||
<li> <a href="#Waiting for Multiple Grace Periods">
|
||||
Waiting for Multiple Grace Periods</a>
|
||||
</ol>
|
||||
|
||||
<h3><a name="Bottom-Half Flavor">Bottom-Half Flavor</a></h3>
|
||||
|
@ -2647,6 +2649,86 @@ The tasks-RCU API is quite compact, consisting only of
|
|||
<tt>synchronize_rcu_tasks()</tt>, and
|
||||
<tt>rcu_barrier_tasks()</tt>.
|
||||
|
||||
<h3><a name="Waiting for Multiple Grace Periods">
|
||||
Waiting for Multiple Grace Periods</a></h3>
|
||||
|
||||
<p>
|
||||
Perhaps you have an RCU protected data structure that is accessed from
|
||||
RCU read-side critical sections, from softirq handlers, and from
|
||||
hardware interrupt handlers.
|
||||
That is three flavors of RCU, the normal flavor, the bottom-half flavor,
|
||||
and the sched flavor.
|
||||
How to wait for a compound grace period?
|
||||
|
||||
<p>
|
||||
The best approach is usually to “just say no!” and
|
||||
insert <tt>rcu_read_lock()</tt> and <tt>rcu_read_unlock()</tt>
|
||||
around each RCU read-side critical section, regardless of what
|
||||
environment it happens to be in.
|
||||
But suppose that some of the RCU read-side critical sections are
|
||||
on extremely hot code paths, and that use of <tt>CONFIG_PREEMPT=n</tt>
|
||||
is not a viable option, so that <tt>rcu_read_lock()</tt> and
|
||||
<tt>rcu_read_unlock()</tt> are not free.
|
||||
What then?
|
||||
|
||||
<p>
|
||||
You <i>could</i> wait on all three grace periods in succession, as follows:
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
1 synchronize_rcu();
|
||||
2 synchronize_rcu_bh();
|
||||
3 synchronize_sched();
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<p>
|
||||
This works, but triples the update-side latency penalty.
|
||||
In cases where this is not acceptable, <tt>synchronize_rcu_mult()</tt>
|
||||
may be used to wait on all three flavors of grace period concurrently:
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
1 synchronize_rcu_mult(call_rcu, call_rcu_bh, call_rcu_sched);
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<p>
|
||||
But what if it is necessary to also wait on SRCU?
|
||||
This can be done as follows:
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
1 static void call_my_srcu(struct rcu_head *head,
|
||||
2 void (*func)(struct rcu_head *head))
|
||||
3 {
|
||||
4 call_srcu(&my_srcu, head, func);
|
||||
5 }
|
||||
6
|
||||
7 synchronize_rcu_mult(call_rcu, call_rcu_bh, call_rcu_sched, call_my_srcu);
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<p>
|
||||
If you needed to wait on multiple different flavors of SRCU
|
||||
(but why???), you would need to create a wrapper function resembling
|
||||
<tt>call_my_srcu()</tt> for each SRCU flavor.
|
||||
|
||||
<p>@@QQ@@
|
||||
But what if I need to wait for multiple RCU flavors, but I also need
|
||||
the grace periods to be expedited?
|
||||
<p>@@QQA@@
|
||||
If you are using expedited grace periods, there should be less penalty
|
||||
for waiting on them in succession.
|
||||
But if that is nevertheless a problem, you can use workqueues or multiple
|
||||
kthreads to wait on the various expedited grace periods concurrently.
|
||||
<p>@@QQE@@
|
||||
|
||||
<p>
|
||||
Again, it is usually better to adjust the RCU read-side critical sections
|
||||
to use a single flavor of RCU, but when this is not feasible, you can use
|
||||
<tt>synchronize_rcu_mult()</tt>.
|
||||
|
||||
<h2><a name="Possible Future Changes">Possible Future Changes</a></h2>
|
||||
|
||||
<p>
|
||||
|
|
Loading…
Reference in New Issue