Commit 3717f613 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'core-rcu-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull RCU updates from Ingo Molnar:
 "The main RCU related changes in this cycle were:

   - Additional cleanups after RCU flavor consolidation

   - Grace-period forward-progress cleanups and improvements

   - Documentation updates

   - Miscellaneous fixes

   - spin_is_locked() conversions to lockdep

   - SPDX changes to RCU source and header files

   - SRCU updates

   - Torture-test updates, including nolibc updates and moving nolibc to
     tools/include"

* 'core-rcu-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (71 commits)
  locking/locktorture: Convert to SPDX license identifier
  linux/torture: Convert to SPDX license identifier
  torture: Convert to SPDX license identifier
  linux/srcu: Convert to SPDX license identifier
  linux/rcutree: Convert to SPDX license identifier
  linux/rcutiny: Convert to SPDX license identifier
  linux/rcu_sync: Convert to SPDX license identifier
  linux/rcu_segcblist: Convert to SPDX license identifier
  linux/rcupdate: Convert to SPDX license identifier
  linux/rcu_node_tree: Convert to SPDX license identifier
  rcu/update: Convert to SPDX license identifier
  rcu/tree: Convert to SPDX license identifier
  rcu/tiny: Convert to SPDX license identifier
  rcu/sync: Convert to SPDX license identifier
  rcu/srcu: Convert to SPDX license identifier
  rcu/rcutorture: Convert to SPDX license identifier
  rcu/rcu_segcblist: Convert to SPDX license identifier
  rcu/rcuperf: Convert to SPDX license identifier
  rcu/rcu.h: Convert to SPDX license identifier
  RCU/torture.txt: Remove section MODULE PARAMETERS
  ...
parents b1b988a6 cae45e1c
...@@ -328,13 +328,13 @@ ...@@ -328,13 +328,13 @@
inkscape:window-height="1148" inkscape:window-height="1148"
id="namedview90" id="namedview90"
showgrid="true" showgrid="true"
inkscape:zoom="0.80021373" inkscape:zoom="0.69092787"
inkscape:cx="462.49289" inkscape:cx="476.34085"
inkscape:cy="473.6718" inkscape:cy="712.80957"
inkscape:window-x="770" inkscape:window-x="770"
inkscape:window-y="24" inkscape:window-y="24"
inkscape:window-maximized="0" inkscape:window-maximized="0"
inkscape:current-layer="g4114-9-3-9" inkscape:current-layer="g4"
inkscape:snap-grids="false" inkscape:snap-grids="false"
fit-margin-top="5" fit-margin-top="5"
fit-margin-right="5" fit-margin-right="5"
...@@ -813,14 +813,18 @@ ...@@ -813,14 +813,18 @@
<text <text
sodipodi:linespacing="125%" sodipodi:linespacing="125%"
id="text4110-5-7-6-2-4-0" id="text4110-5-7-6-2-4-0"
y="841.88086" y="670.74316"
x="1460.1007" x="1460.1007"
style="font-size:267.24359131px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans" style="font-size:267.24359131px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
xml:space="preserve"><tspan xml:space="preserve"><tspan
y="841.88086" y="670.74316"
x="1460.1007"
sodipodi:role="line"
id="tspan4925-1-2-4-5">Request</tspan><tspan
y="1004.7976"
x="1460.1007" x="1460.1007"
sodipodi:role="line" sodipodi:role="line"
id="tspan4925-1-2-4-5">reched_cpu()</tspan></text> id="tspan3100">context switch</tspan></text>
</g> </g>
</g> </g>
</svg> </svg>
...@@ -72,10 +72,10 @@ will ignore it because idle and offline CPUs are already residing ...@@ -72,10 +72,10 @@ will ignore it because idle and offline CPUs are already residing
in quiescent states. in quiescent states.
Otherwise, the expedited grace period will use Otherwise, the expedited grace period will use
<tt>smp_call_function_single()</tt> to send the CPU an IPI, which <tt>smp_call_function_single()</tt> to send the CPU an IPI, which
is handled by <tt>sync_rcu_exp_handler()</tt>. is handled by <tt>rcu_exp_handler()</tt>.
<p> <p>
However, because this is preemptible RCU, <tt>sync_rcu_exp_handler()</tt> However, because this is preemptible RCU, <tt>rcu_exp_handler()</tt>
can check to see if the CPU is currently running in an RCU read-side can check to see if the CPU is currently running in an RCU read-side
critical section. critical section.
If not, the handler can immediately report a quiescent state. If not, the handler can immediately report a quiescent state.
...@@ -145,19 +145,18 @@ expedited grace period is shown in the following diagram: ...@@ -145,19 +145,18 @@ expedited grace period is shown in the following diagram:
<p><img src="ExpSchedFlow.svg" alt="ExpSchedFlow.svg" width="55%"> <p><img src="ExpSchedFlow.svg" alt="ExpSchedFlow.svg" width="55%">
<p> <p>
As with RCU-preempt's <tt>synchronize_rcu_expedited()</tt>, As with RCU-preempt, RCU-sched's
<tt>synchronize_sched_expedited()</tt> ignores offline and <tt>synchronize_sched_expedited()</tt> ignores offline and
idle CPUs, again because they are in remotely detectable idle CPUs, again because they are in remotely detectable
quiescent states. quiescent states.
However, the <tt>synchronize_rcu_expedited()</tt> handler However, because the
is <tt>sync_sched_exp_handler()</tt>, and because the
<tt>rcu_read_lock_sched()</tt> and <tt>rcu_read_unlock_sched()</tt> <tt>rcu_read_lock_sched()</tt> and <tt>rcu_read_unlock_sched()</tt>
leave no trace of their invocation, in general it is not possible to tell leave no trace of their invocation, in general it is not possible to tell
whether or not the current CPU is in an RCU read-side critical section. whether or not the current CPU is in an RCU read-side critical section.
The best that <tt>sync_sched_exp_handler()</tt> can do is to check The best that RCU-sched's <tt>rcu_exp_handler()</tt> can do is to check
for idle, on the off-chance that the CPU went idle while the IPI for idle, on the off-chance that the CPU went idle while the IPI
was in flight. was in flight.
If the CPU is idle, then <tt>sync_sched_exp_handler()</tt> reports If the CPU is idle, then <tt>rcu_exp_handler()</tt> reports
the quiescent state. the quiescent state.
<p> Otherwise, the handler forces a future context switch by setting the <p> Otherwise, the handler forces a future context switch by setting the
...@@ -298,19 +297,18 @@ Instead, the task pushing the grace period forward will include the ...@@ -298,19 +297,18 @@ Instead, the task pushing the grace period forward will include the
idle CPUs in the mask passed to <tt>rcu_report_exp_cpu_mult()</tt>. idle CPUs in the mask passed to <tt>rcu_report_exp_cpu_mult()</tt>.
<p> <p>
For RCU-sched, there is an additional check for idle in the IPI For RCU-sched, there is an additional check:
handler, <tt>sync_sched_exp_handler()</tt>.
If the IPI has interrupted the idle loop, then If the IPI has interrupted the idle loop, then
<tt>sync_sched_exp_handler()</tt> invokes <tt>rcu_report_exp_rdp()</tt> <tt>rcu_exp_handler()</tt> invokes <tt>rcu_report_exp_rdp()</tt>
to report the corresponding quiescent state. to report the corresponding quiescent state.
<p> <p>
For RCU-preempt, there is no specific check for idle in the For RCU-preempt, there is no specific check for idle in the
IPI handler (<tt>sync_rcu_exp_handler()</tt>), but because IPI handler (<tt>rcu_exp_handler()</tt>), but because
RCU read-side critical sections are not permitted within the RCU read-side critical sections are not permitted within the
idle loop, if <tt>sync_rcu_exp_handler()</tt> sees that the CPU is within idle loop, if <tt>rcu_exp_handler()</tt> sees that the CPU is within
RCU read-side critical section, the CPU cannot possibly be idle. RCU read-side critical section, the CPU cannot possibly be idle.
Otherwise, <tt>sync_rcu_exp_handler()</tt> invokes Otherwise, <tt>rcu_exp_handler()</tt> invokes
<tt>rcu_report_exp_rdp()</tt> to report the corresponding quiescent <tt>rcu_report_exp_rdp()</tt> to report the corresponding quiescent
state, regardless of whether or not that quiescent state was due to state, regardless of whether or not that quiescent state was due to
the CPU being idle. the CPU being idle.
...@@ -625,6 +623,8 @@ checks, but only during the mid-boot dead zone. ...@@ -625,6 +623,8 @@ checks, but only during the mid-boot dead zone.
<p> <p>
With this refinement, synchronous grace periods can now be used from With this refinement, synchronous grace periods can now be used from
task context pretty much any time during the life of the kernel. task context pretty much any time during the life of the kernel.
That is, aside from some points in the suspend, hibernate, or shutdown
code path.
<h3><a name="Summary"> <h3><a name="Summary">
Summary</a></h3> Summary</a></h3>
......
...@@ -485,13 +485,13 @@ section that the grace period must wait on. ...@@ -485,13 +485,13 @@ section that the grace period must wait on.
noted by <tt>rcu_node_context_switch()</tt> on the left. noted by <tt>rcu_node_context_switch()</tt> on the left.
On the other hand, if the CPU takes a scheduler-clock interrupt On the other hand, if the CPU takes a scheduler-clock interrupt
while executing in usermode, a quiescent state will be noted by while executing in usermode, a quiescent state will be noted by
<tt>rcu_check_callbacks()</tt> on the right. <tt>rcu_sched_clock_irq()</tt> on the right.
Either way, the passage through a quiescent state will be noted Either way, the passage through a quiescent state will be noted
in a per-CPU variable. in a per-CPU variable.
<p>The next time an <tt>RCU_SOFTIRQ</tt> handler executes on <p>The next time an <tt>RCU_SOFTIRQ</tt> handler executes on
this CPU (for example, after the next scheduler-clock this CPU (for example, after the next scheduler-clock
interrupt), <tt>__rcu_process_callbacks()</tt> will invoke interrupt), <tt>rcu_core()</tt> will invoke
<tt>rcu_check_quiescent_state()</tt>, which will notice the <tt>rcu_check_quiescent_state()</tt>, which will notice the
recorded quiescent state, and invoke recorded quiescent state, and invoke
<tt>rcu_report_qs_rdp()</tt>. <tt>rcu_report_qs_rdp()</tt>.
...@@ -651,7 +651,7 @@ to end. ...@@ -651,7 +651,7 @@ to end.
These callbacks are identified by <tt>rcu_advance_cbs()</tt>, These callbacks are identified by <tt>rcu_advance_cbs()</tt>,
which is usually invoked by <tt>__note_gp_changes()</tt>. which is usually invoked by <tt>__note_gp_changes()</tt>.
As shown in the diagram below, this invocation can be triggered by As shown in the diagram below, this invocation can be triggered by
the scheduling-clock interrupt (<tt>rcu_check_callbacks()</tt> on the scheduling-clock interrupt (<tt>rcu_sched_clock_irq()</tt> on
the left) or by idle entry (<tt>rcu_cleanup_after_idle()</tt> on the left) or by idle entry (<tt>rcu_cleanup_after_idle()</tt> on
the right, but only for kernels build with the right, but only for kernels build with
<tt>CONFIG_RCU_FAST_NO_HZ=y</tt>). <tt>CONFIG_RCU_FAST_NO_HZ=y</tt>).
......
...@@ -349,7 +349,7 @@ ...@@ -349,7 +349,7 @@
font-weight="bold" font-weight="bold"
font-size="192" font-size="192"
id="text202-7-5" id="text202-7-5"
style="font-size:192px;font-style:normal;font-weight:bold;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier">rcu_check_callbacks()</text> style="font-size:192px;font-style:normal;font-weight:bold;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier">rcu_sched_clock_irq()</text>
<rect <rect
x="7069.6187" x="7069.6187"
y="5087.4678" y="5087.4678"
......
...@@ -3902,7 +3902,7 @@ ...@@ -3902,7 +3902,7 @@
font-style="normal" font-style="normal"
y="-4418.6582" y="-4418.6582"
x="3745.7725" x="3745.7725"
xml:space="preserve">rcu_check_callbacks()</text> xml:space="preserve">rcu_sched_clock_irq()</text>
</g> </g>
<g <g
transform="translate(-850.30204,55463.106)" transform="translate(-850.30204,55463.106)"
...@@ -3924,7 +3924,7 @@ ...@@ -3924,7 +3924,7 @@
font-style="normal" font-style="normal"
y="-4418.6582" y="-4418.6582"
x="3745.7725" x="3745.7725"
xml:space="preserve">rcu_process_callbacks()</text> xml:space="preserve">rcu_core()</text>
<text <text
style="font-size:192px;font-style:normal;font-weight:bold;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier" style="font-size:192px;font-style:normal;font-weight:bold;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier"
id="text202-7-5-3-27-0" id="text202-7-5-3-27-0"
...@@ -3933,7 +3933,7 @@ ...@@ -3933,7 +3933,7 @@
font-style="normal" font-style="normal"
y="-4165.7954" y="-4165.7954"
x="3745.7725" x="3745.7725"
xml:space="preserve">rcu_check_quiescent_state())</text> xml:space="preserve">rcu_check_quiescent_state()</text>
<text <text
style="font-size:192px;font-style:normal;font-weight:bold;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier" style="font-size:192px;font-style:normal;font-weight:bold;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier"
id="text202-7-5-3-27-0-9" id="text202-7-5-3-27-0-9"
...@@ -4968,7 +4968,7 @@ ...@@ -4968,7 +4968,7 @@
font-weight="bold" font-weight="bold"
font-size="192" font-size="192"
id="text202-7-5-19" id="text202-7-5-19"
style="font-size:192px;font-style:normal;font-weight:bold;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier">rcu_check_callbacks()</text> style="font-size:192px;font-style:normal;font-weight:bold;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier">rcu_sched_clock_irq()</text>
<rect <rect
x="5314.2671" x="5314.2671"
y="82817.688" y="82817.688"
......
...@@ -775,7 +775,7 @@ ...@@ -775,7 +775,7 @@
font-style="normal" font-style="normal"
y="-4418.6582" y="-4418.6582"
x="3745.7725" x="3745.7725"
xml:space="preserve">rcu_check_callbacks()</text> xml:space="preserve">rcu_sched_clock_irq()</text>
</g> </g>
<g <g
transform="translate(399.7744,828.86448)" transform="translate(399.7744,828.86448)"
...@@ -797,7 +797,7 @@ ...@@ -797,7 +797,7 @@
font-style="normal" font-style="normal"
y="-4418.6582" y="-4418.6582"
x="3745.7725" x="3745.7725"
xml:space="preserve">rcu_process_callbacks()</text> xml:space="preserve">rcu_core()</text>
<text <text
style="font-size:192px;font-style:normal;font-weight:bold;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier" style="font-size:192px;font-style:normal;font-weight:bold;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier"
id="text202-7-5-3-27-0" id="text202-7-5-3-27-0"
...@@ -806,7 +806,7 @@ ...@@ -806,7 +806,7 @@
font-style="normal" font-style="normal"
y="-4165.7954" y="-4165.7954"
x="3745.7725" x="3745.7725"
xml:space="preserve">rcu_check_quiescent_state())</text> xml:space="preserve">rcu_check_quiescent_state()</text>
<text <text
style="font-size:192px;font-style:normal;font-weight:bold;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier" style="font-size:192px;font-style:normal;font-weight:bold;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier"
id="text202-7-5-3-27-0-9" id="text202-7-5-3-27-0-9"
......
...@@ -3099,7 +3099,7 @@ If you block forever in one of a given domain's SRCU read-side critical ...@@ -3099,7 +3099,7 @@ 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. 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 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 happen if any operation in a given domain's SRCU read-side critical
section can block waiting, either directly or indirectly, for that domain's section can wait, either directly or indirectly, for that domain's
grace period to elapse. grace period to elapse.
For example, this results in a self-deadlock: For example, this results in a self-deadlock:
...@@ -3139,12 +3139,18 @@ API, which, in combination with <tt>srcu_read_unlock()</tt>, ...@@ -3139,12 +3139,18 @@ API, which, in combination with <tt>srcu_read_unlock()</tt>,
guarantees a full memory barrier. guarantees a full memory barrier.
<p> <p>
Also unlike other RCU flavors, SRCU's callbacks-wait function Also unlike other RCU flavors, <tt>synchronize_srcu()</tt> may <b>not</b>
<tt>srcu_barrier()</tt> may be invoked from CPU-hotplug notifiers, be invoked from CPU-hotplug notifiers, due to the fact that SRCU grace
though this is not necessarily a good idea. periods make use of timers and the possibility of timers being temporarily
The reason that this is possible is that SRCU is insensitive &ldquo;stranded&rdquo; on the outgoing CPU.
to whether or not a CPU is online, which means that <tt>srcu_barrier()</tt> This stranding of timers means that timers posted to the outgoing CPU
need not exclude CPU-hotplug operations. 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 <tt>srcu_barrier()</tt>
from being invoked from CPU-hotplug notifiers.
<p> <p>
SRCU also differs from other RCU flavors in that SRCU's expedited and SRCU also differs from other RCU flavors in that SRCU's expedited and
......
...@@ -219,17 +219,18 @@ an estimate of the total number of RCU callbacks queued across all CPUs ...@@ -219,17 +219,18 @@ an estimate of the total number of RCU callbacks queued across all CPUs
In kernels with CONFIG_RCU_FAST_NO_HZ, more information is printed In kernels with CONFIG_RCU_FAST_NO_HZ, more information is printed
for each CPU: for each CPU:
0: (64628 ticks this GP) idle=dd5/3fffffffffffffff/0 softirq=82/543 last_accelerate: a345/d342 nonlazy_posted: 25 .D 0: (64628 ticks this GP) idle=dd5/3fffffffffffffff/0 softirq=82/543 last_accelerate: a345/d342 Nonlazy posted: ..D
The "last_accelerate:" prints the low-order 16 bits (in hex) of the The "last_accelerate:" prints the low-order 16 bits (in hex) of the
jiffies counter when this CPU last invoked rcu_try_advance_all_cbs() jiffies counter when this CPU last invoked rcu_try_advance_all_cbs()
from rcu_needs_cpu() or last invoked rcu_accelerate_cbs() from from rcu_needs_cpu() or last invoked rcu_accelerate_cbs() from
rcu_prepare_for_idle(). The "nonlazy_posted:" prints the number rcu_prepare_for_idle(). The "Nonlazy posted:" indicates lazy-callback
of non-lazy callbacks posted since the last call to rcu_needs_cpu(). status, so that an "l" indicates that all callbacks were lazy at the start
Finally, an "L" indicates that there are currently no non-lazy callbacks of the last idle period and an "L" indicates that there are currently
("." is printed otherwise, as shown above) and "D" indicates that no non-lazy callbacks (in both cases, "." is printed otherwise, as
dyntick-idle processing is enabled ("." is printed otherwise, for example, shown above) and "D" indicates that dyntick-idle processing is enabled
if disabled via the "nohz=" kernel boot parameter). ("." is printed otherwise, for example, if disabled via the "nohz="
kernel boot parameter).
If the grace period ends just as the stall warning starts printing, If the grace period ends just as the stall warning starts printing,
there will be a spurious stall-warning message, which will include there will be a spurious stall-warning message, which will include
......
...@@ -10,173 +10,8 @@ status messages via printk(), which can be examined via the dmesg ...@@ -10,173 +10,8 @@ status messages via printk(), which can be examined via the dmesg
command (perhaps grepping for "torture"). The test is started command (perhaps grepping for "torture"). The test is started
when the module is loaded, and stops when the module is unloaded. when the module is loaded, and stops when the module is unloaded.
Module parameters are prefixed by "rcutorture." in
MODULE PARAMETERS Documentation/admin-guide/kernel-parameters.txt.
This module has the following parameters:
fqs_duration Duration (in microseconds) of artificially induced bursts
of force_quiescent_state() invocations. In RCU
implementations having force_quiescent_state(), these
bursts help force races between forcing a given grace
period and that grace period ending on its own.
fqs_holdoff Holdoff time (in microseconds) between consecutive calls
to force_quiescent_state() within a burst.
fqs_stutter Wait time (in seconds) between consecutive bursts
of calls to force_quiescent_state().
gp_normal Make the fake writers use normal synchronous grace-period
primitives.
gp_exp Make the fake writers use expedited synchronous grace-period
primitives. If both gp_normal and gp_exp are set, or
if neither gp_normal nor gp_exp are set, then randomly
choose the primitive so that about 50% are normal and
50% expedited. By default, neither are set, which
gives best overall test coverage.
irqreader Says to invoke RCU readers from irq level. This is currently
done via timers. Defaults to "1" for variants of RCU that
permit this. (Or, more accurately, variants of RCU that do
-not- permit this know to ignore this variable.)
n_barrier_cbs If this is nonzero, RCU barrier testing will be conducted,
in which case n_barrier_cbs specifies the number of
RCU callbacks (and corresponding kthreads) to use for
this testing. The value cannot be negative. If you
specify this to be non-zero when torture_type indicates a
synchronous RCU implementation (one for which a member of
the synchronize_rcu() rather than the call_rcu() family is
used -- see the documentation for torture_type below), an
error will be reported and no testing will be carried out.
nfakewriters This is the number of RCU fake writer threads to run. Fake
writer threads repeatedly use the synchronous "wait for
current readers" function of the interface selected by
torture_type, with a delay between calls to allow for various
different numbers of writers running in parallel.
nfakewriters defaults to 4, which provides enough parallelism
to trigger special cases caused by multiple writers, such as
the synchronize_srcu() early return optimization.
nreaders This is the number of RCU reading threads supported.
The default is twice the number of CPUs. Why twice?
To properly exercise RCU implementations with preemptible
read-side critical sections.
onoff_interval
The number of seconds between each attempt to execute a
randomly selected CPU-hotplug operation. Defaults to
zero, which disables CPU hotplugging. In HOTPLUG_CPU=n
kernels, rcutorture will silently refuse to do any
CPU-hotplug operations regardless of what value is
specified for onoff_interval.
onoff_holdoff The number of seconds to wait until starting CPU-hotplug
operations. This would normally only be used when
rcutorture was built into the kernel and started
automatically at boot time, in which case it is useful
in order to avoid confusing boot-time code with CPUs
coming and going.
shuffle_interval
The number of seconds to keep the test threads affinitied
to a particular subset of the CPUs, defaults to 3 seconds.
Used in conjunction with test_no_idle_hz.
shutdown_secs The number of seconds to run the test before terminating
the test and powering off the system. The default is
zero, which disables test termination and system shutdown.
This capability is useful for automated testing.
stall_cpu The number of seconds that a CPU should be stalled while
within both an rcu_read_lock() and a preempt_disable().
This stall happens only once per rcutorture run.
If you need multiple stalls, use modprobe and rmmod to
repeatedly run rcutorture. The default for stall_cpu
is zero, which prevents rcutorture from stalling a CPU.
Note that attempts to rmmod rcutorture while the stall
is ongoing will hang, so be careful what value you
choose for this module parameter! In addition, too-large
values for stall_cpu might well induce failures and
warnings in other parts of the kernel. You have been
warned!
stall_cpu_holdoff
The number of seconds to wait after rcutorture starts
before stalling a CPU. Defaults to 10 seconds.
stat_interval The number of seconds between output of torture
statistics (via printk()). Regardless of the interval,
statistics are printed when the module is unloaded.
Setting the interval to zero causes the statistics to
be printed -only- when the module is unloaded, and this
is the default.
stutter The length of time to run the test before pausing for this
same period of time. Defaults to "stutter=5", so as
to run and pause for (roughly) five-second intervals.
Specifying "stutter=0" causes the test to run continuously
without pausing, which is the old default behavior.
test_boost Whether or not to test the ability of RCU to do priority
boosting. Defaults to "test_boost=1", which performs
RCU priority-inversion testing only if the selected
RCU implementation supports priority boosting. Specifying
"test_boost=0" never performs RCU priority-inversion
testing. Specifying "test_boost=2" performs RCU
priority-inversion testing even if the selected RCU
implementation does not support RCU priority boosting,
which can be used to test rcutorture's ability to
carry out RCU priority-inversion testing.
test_boost_interval
The number of seconds in an RCU priority-inversion test
cycle. Defaults to "test_boost_interval=7". It is
usually wise for this value to be relatively prime to
the value selected for "stutter".
test_boost_duration
The number of seconds to do RCU priority-inversion testing
within any given "test_boost_interval". Defaults to
"test_boost_duration=4".
test_no_idle_hz Whether or not to test the ability of RCU to operate in
a kernel that disables the scheduling-clock interrupt to
idle CPUs. Boolean parameter, "1" to test, "0" otherwise.
Defaults to omitting this test.
torture_type The type of RCU to test, with string values as follows:
"rcu": rcu_read_lock(), rcu_read_unlock() and call_rcu(),
along with expedited, synchronous, and polling
variants.
"rcu_bh": rcu_read_lock_bh(), rcu_read_unlock_bh(), and
call_rcu_bh(), along with expedited and synchronous
variants.
"rcu_busted": This tests an intentionally incorrect version
of RCU in order to help test rcutorture itself.
"srcu": srcu_read_lock(), srcu_read_unlock() and
call_srcu(), along with expedited and
synchronous variants.
"sched": preempt_disable(), preempt_enable(), and
call_rcu_sched(), along with expedited,
synchronous, and polling variants.
"tasks": voluntary context switch and call_rcu_tasks(),
along with expedited and synchronous variants.
Defaults to "rcu".
verbose Enable debug printk()s. Default is disabled.
OUTPUT OUTPUT
......
...@@ -302,7 +302,7 @@ rcu_dereference() ...@@ -302,7 +302,7 @@ rcu_dereference()
must prohibit. The rcu_dereference_protected() variant takes must prohibit. The rcu_dereference_protected() variant takes
a lockdep expression to indicate which locks must be acquired a lockdep expression to indicate which locks must be acquired
by the caller. If the indicated protection is not provided, by the caller. If the indicated protection is not provided,
a lockdep splat is emitted. See RCU/Design/Requirements.html a lockdep splat is emitted. See RCU/Design/Requirements/Requirements.html
and the API's code comments for more details and example usage. and the API's code comments for more details and example usage.
The following diagram shows how each API communicates among the The following diagram shows how each API communicates among the
...@@ -560,7 +560,7 @@ presents two such "toy" implementations of RCU, one that is implemented ...@@ -560,7 +560,7 @@ presents two such "toy" implementations of RCU, one that is implemented
in terms of familiar locking primitives, and another that more closely in terms of familiar locking primitives, and another that more closely
resembles "classic" RCU. Both are way too simple for real-world use, resembles "classic" RCU. Both are way too simple for real-world use,
lacking both functionality and performance. However, they are useful lacking both functionality and performance. However, they are useful
in getting a feel for how RCU works. See kernel/rcupdate.c for a in getting a feel for how RCU works. See kernel/rcu/update.c for a
production-quality implementation, and see: production-quality implementation, and see:
http://www.rdrop.com/users/paulmck/RCU http://www.rdrop.com/users/paulmck/RCU
......
...@@ -3658,19 +3658,6 @@ ...@@ -3658,19 +3658,6 @@
latencies, which will choose a value aligned latencies, which will choose a value aligned
with the appropriate hardware boundaries. with the appropriate hardware boundaries.
rcutree.jiffies_till_sched_qs= [KNL]
Set required age in jiffies for a
given grace period before RCU starts
soliciting quiescent-state help from
rcu_note_context_switch(). If not specified, the
kernel will calculate a value based on the most
recent settings of rcutree.jiffies_till_first_fqs
and rcutree.jiffies_till_next_fqs.
This calculated value may be viewed in
rcutree.jiffies_to_sched_qs. Any attempt to
set rcutree.jiffies_to_sched_qs will be
cheerfully overwritten.
rcutree.jiffies_till_first_fqs= [KNL] rcutree.jiffies_till_first_fqs= [KNL]
Set delay from grace-period initialization to Set delay from grace-period initialization to
first attempt to force quiescent states. first attempt to force quiescent states.
...@@ -3682,6 +3669,20 @@ ...@@ -3682,6 +3669,20 @@
quiescent states. Units are jiffies, minimum quiescent states. Units are jiffies, minimum
value is one, and maximum value is HZ. value is one, and maximum value is HZ.
rcutree.jiffies_till_sched_qs= [KNL]
Set required age in jiffies for a
given grace period before RCU starts
soliciting quiescent-state help from
rcu_note_context_switch() and cond_resched().
If not specified, the kernel will calculate
a value based on the most recent settings
of rcutree.jiffies_till_first_fqs
and rcutree.jiffies_till_next_fqs.
This calculated value may be viewed in
rcutree.jiffies_to_sched_qs. Any attempt to set
rcutree.jiffies_to_sched_qs will be cheerfully
overwritten.
rcutree.kthread_prio= [KNL,BOOT] rcutree.kthread_prio= [KNL,BOOT]
Set the SCHED_FIFO priority of the RCU per-CPU Set the SCHED_FIFO priority of the RCU per-CPU
kthreads (rcuc/N). This value is also used for kthreads (rcuc/N). This value is also used for
...@@ -3725,6 +3726,11 @@ ...@@ -3725,6 +3726,11 @@
This wake_up() will be accompanied by a This wake_up() will be accompanied by a
WARN_ONCE() splat and an ftrace_dump(). WARN_ONCE() splat and an ftrace_dump().
rcutree.sysrq_rcu= [KNL]
Commandeer a sysrq key to dump out Tree RCU's
rcu_node tree with an eye towards determining
why a new grace period has not yet started.
rcuperf.gp_async= [KNL] rcuperf.gp_async= [KNL]
Measure performance of asynchronous Measure performance of asynchronous
grace-period primitives such as call_rcu(). grace-period primitives such as call_rcu().
......
...@@ -10827,6 +10827,12 @@ F: drivers/power/supply/bq27xxx_battery_i2c.c ...@@ -10827,6 +10827,12 @@ F: drivers/power/supply/bq27xxx_battery_i2c.c
F: drivers/power/supply/isp1704_charger.c F: drivers/power/supply/isp1704_charger.c
F: drivers/power/supply/rx51_battery.c F: drivers/power/supply/rx51_battery.c
NOLIBC HEADER FILE
M: Willy Tarreau <w@1wt.eu>
S: Maintained
T: git git://git.kernel.org/pub/scm/linux/kernel/git/wtarreau/nolibc.git
F: tools/include/nolibc/
NTB AMD DRIVER NTB AMD DRIVER
M: Shyam Sundar S K <Shyam-sundar.S-k@amd.com> M: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
L: linux-ntb@googlegroups.com L: linux-ntb@googlegroups.com
......
...@@ -211,9 +211,6 @@ void __warn(const char *file, int line, void *caller, unsigned taint, ...@@ -211,9 +211,6 @@ void __warn(const char *file, int line, void *caller, unsigned taint,
/* /*
* WARN_ON_SMP() is for cases that the warning is either * WARN_ON_SMP() is for cases that the warning is either
* meaningless for !SMP or may even cause failures. * meaningless for !SMP or may even cause failures.
* This is usually used for cases that we have
* WARN_ON(!spin_is_locked(&lock)) checks, as spin_is_locked()
* returns 0 for uniprocessor settings.
* It can also be used with values that are only defined * It can also be used with values that are only defined
* on SMP: * on SMP:
* *
......
/* SPDX-License-Identifier: GPL-2.0+ */
/* /*
* RCU node combining tree definitions. These are used to compute * RCU node combining tree definitions. These are used to compute
* global attributes while avoiding common-case global contention. A key * global attributes while avoiding common-case global contention. A key
...@@ -11,23 +12,9 @@ ...@@ -11,23 +12,9 @@
* because the size of the TREE SRCU srcu_struct structure depends * because the size of the TREE SRCU srcu_struct structure depends
* on these definitions. * on these definitions.
* *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you can access it online at
* http://www.gnu.org/licenses/gpl-2.0.html.
*
* Copyright IBM Corporation, 2017 * Copyright IBM Corporation, 2017
* *
* Author: Paul E. McKenney <paulmck@linux.vnet.ibm.com> * Author: Paul E. McKenney <paulmck@linux.ibm.com>
*/ */
#ifndef __LINUX_RCU_NODE_TREE_H #ifndef __LINUX_RCU_NODE_TREE_H
......
/* SPDX-License-Identifier: GPL-2.0+ */
/* /*
* RCU segmented callback lists * RCU segmented callback lists
* *
...@@ -5,23 +6,9 @@ ...@@ -5,23 +6,9 @@
* because the size of the TREE SRCU srcu_struct structure depends * because the size of the TREE SRCU srcu_struct structure depends
* on these definitions. * on these definitions.
* *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you can access it online at
* http://www.gnu.org/licenses/gpl-2.0.html.
*
* Copyright IBM Corporation, 2017 * Copyright IBM Corporation, 2017
* *
* Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com> * Authors: Paul E. McKenney <paulmck@linux.net.ibm.com>
*/ */
#ifndef __INCLUDE_LINUX_RCU_SEGCBLIST_H #ifndef __INCLUDE_LINUX_RCU_SEGCBLIST_H
......
/* SPDX-License-Identifier: GPL-2.0+ */
/* /*
* RCU-based infrastructure for lightweight reader-writer locking * RCU-based infrastructure for lightweight reader-writer locking
* *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you can access it online at
* http://www.gnu.org/licenses/gpl-2.0.html.
*
* Copyright (c) 2015, Red Hat, Inc. * Copyright (c) 2015, Red Hat, Inc.
* *
* Author: Oleg Nesterov <oleg@redhat.com> * Author: Oleg Nesterov <oleg@redhat.com>
......
/* SPDX-License-Identifier: GPL-2.0+ */
/* /*
* Read-Copy Update mechanism for mutual exclusion * Read-Copy Update mechanism for mutual exclusion
* *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you can access it online at
* http://www.gnu.org/licenses/gpl-2.0.html.
*
* Copyright IBM Corporation, 2001 * Copyright IBM Corporation, 2001
* *
* Author: Dipankar Sarma <dipankar@in.ibm.com> * Author: Dipankar Sarma <dipankar@in.ibm.com>
* *
* Based on the original work by Paul McKenney <paulmck@us.ibm.com> * Based on the original work by Paul McKenney <paulmck@vnet.ibm.com>
* and inputs from Rusty Russell, Andrea Arcangeli and Andi Kleen. * and inputs from Rusty Russell, Andrea Arcangeli and Andi Kleen.
* Papers: * Papers:
* http://www.rdrop.com/users/paulmck/paper/rclockpdcsproof.pdf * http://www.rdrop.com/users/paulmck/paper/rclockpdcsproof.pdf
...@@ -89,7 +76,7 @@ static inline int rcu_preempt_depth(void) ...@@ -89,7 +76,7 @@ static inline int rcu_preempt_depth(void)
/* Internal to kernel */ /* Internal to kernel */
void rcu_init(void); void rcu_init(void);
extern int rcu_scheduler_active __read_mostly; extern int rcu_scheduler_active __read_mostly;
void rcu_check_callbacks(int user); void rcu_sched_clock_irq(int user);
void rcu_report_dead(unsigned int cpu); void rcu_report_dead(unsigned int cpu);
void rcutree_migrate_callbacks(int cpu); void rcutree_migrate_callbacks(int cpu);
...@@ -309,16 +296,16 @@ static inline void rcu_preempt_sleep_check(void) { } ...@@ -309,16 +296,16 @@ static inline void rcu_preempt_sleep_check(void) { }
*/ */
#ifdef __CHECKER__ #ifdef __CHECKER__
#define rcu_dereference_sparse(p, space) \ #define rcu_check_sparse(p, space) \
((void)(((typeof(*p) space *)p) == p)) ((void)(((typeof(*p) space *)p) == p))
#else /* #ifdef __CHECKER__ */ #else /* #ifdef __CHECKER__ */
#define rcu_dereference_sparse(p, space) #define rcu_check_sparse(p, space)
#endif /* #else #ifdef __CHECKER__ */ #endif /* #else #ifdef __CHECKER__ */
#define __rcu_access_pointer(p, space) \ #define __rcu_access_pointer(p, space) \
({ \ ({ \
typeof(*p) *_________p1 = (typeof(*p) *__force)READ_ONCE(p); \ typeof(*p) *_________p1 = (typeof(*p) *__force)READ_ONCE(p); \
rcu_dereference_sparse(p, space); \ rcu_check_sparse(p, space); \
((typeof(*p) __force __kernel *)(_________p1)); \ ((typeof(*p) __force __kernel *)(_________p1)); \
}) })
#define __rcu_dereference_check(p, c, space) \ #define __rcu_dereference_check(p, c, space) \
...@@ -326,13 +313,13 @@ static inline void rcu_preempt_sleep_check(void) { } ...@@ -326,13 +313,13 @@ static inline void rcu_preempt_sleep_check(void) { }
/* Dependency order vs. p above. */ \ /* Dependency order vs. p above. */ \
typeof(*p) *________p1 = (typeof(*p) *__force)READ_ONCE(p); \ typeof(*p) *________p1 = (typeof(*p) *__force)READ_ONCE(p); \
RCU_LOCKDEP_WARN(!(c), "suspicious rcu_dereference_check() usage"); \ RCU_LOCKDEP_WARN(!(c), "suspicious rcu_dereference_check() usage"); \
rcu_dereference_sparse(p, space); \ rcu_check_sparse(p, space); \
((typeof(*p) __force __kernel *)(________p1)); \ ((typeof(*p) __force __kernel *)(________p1)); \
}) })
#define __rcu_dereference_protected(p, c, space) \ #define __rcu_dereference_protected(p, c, space) \
({ \ ({ \
RCU_LOCKDEP_WARN(!(c), "suspicious rcu_dereference_protected() usage"); \ RCU_LOCKDEP_WARN(!(c), "suspicious rcu_dereference_protected() usage"); \
rcu_dereference_sparse(p, space); \ rcu_check_sparse(p, space); \
((typeof(*p) __force __kernel *)(p)); \ ((typeof(*p) __force __kernel *)(p)); \
}) })
#define rcu_dereference_raw(p) \ #define rcu_dereference_raw(p) \
...@@ -382,6 +369,7 @@ static inline void rcu_preempt_sleep_check(void) { } ...@@ -382,6 +369,7 @@ static inline void rcu_preempt_sleep_check(void) { }
#define rcu_assign_pointer(p, v) \ #define rcu_assign_pointer(p, v) \
({ \ ({ \
uintptr_t _r_a_p__v = (uintptr_t)(v); \ uintptr_t _r_a_p__v = (uintptr_t)(v); \
rcu_check_sparse(p, __rcu); \
\ \
if (__builtin_constant_p(v) && (_r_a_p__v) == (uintptr_t)NULL) \ if (__builtin_constant_p(v) && (_r_a_p__v) == (uintptr_t)NULL) \
WRITE_ONCE((p), (typeof(p))(_r_a_p__v)); \ WRITE_ONCE((p), (typeof(p))(_r_a_p__v)); \
...@@ -785,7 +773,7 @@ static inline notrace void rcu_read_unlock_sched_notrace(void) ...@@ -785,7 +773,7 @@ static inline notrace void rcu_read_unlock_sched_notrace(void)
*/ */
#define RCU_INIT_POINTER(p, v) \ #define RCU_INIT_POINTER(p, v) \
do { \ do { \
rcu_dereference_sparse(p, __rcu); \ rcu_check_sparse(p, __rcu); \
WRITE_ONCE(p, RCU_INITIALIZER(v)); \ WRITE_ONCE(p, RCU_INITIALIZER(v)); \
} while (0) } while (0)
...@@ -859,7 +847,7 @@ static inline notrace void rcu_read_unlock_sched_notrace(void) ...@@ -859,7 +847,7 @@ static inline notrace void rcu_read_unlock_sched_notrace(void)
/* Has the specified rcu_head structure been handed to call_rcu()? */ /* Has the specified rcu_head structure been handed to call_rcu()? */
/* /**
* rcu_head_init - Initialize rcu_head for rcu_head_after_call_rcu() * rcu_head_init - Initialize rcu_head for rcu_head_after_call_rcu()
* @rhp: The rcu_head structure to initialize. * @rhp: The rcu_head structure to initialize.
* *
...@@ -874,10 +862,10 @@ static inline void rcu_head_init(struct rcu_head *rhp) ...@@ -874,10 +862,10 @@ static inline void rcu_head_init(struct rcu_head *rhp)
rhp->func = (rcu_callback_t)~0L; rhp->func = (rcu_callback_t)~0L;
} }
/* /**
* rcu_head_after_call_rcu - Has this rcu_head been passed to call_rcu()? * rcu_head_after_call_rcu - Has this rcu_head been passed to call_rcu()?
* @rhp: The rcu_head structure to test. * @rhp: The rcu_head structure to test.
* @func: The function passed to call_rcu() along with @rhp. * @f: The function passed to call_rcu() along with @rhp.
* *
* Returns @true if the @rhp has been passed to call_rcu() with @func, * Returns @true if the @rhp has been passed to call_rcu() with @func,
* and @false otherwise. Emits a warning in any other case, including * and @false otherwise. Emits a warning in any other case, including
...@@ -896,57 +884,4 @@ rcu_head_after_call_rcu(struct rcu_head *rhp, rcu_callback_t f) ...@@ -896,57 +884,4 @@ rcu_head_after_call_rcu(struct rcu_head *rhp, rcu_callback_t f)
return false; return false;
} }
/* Transitional pre-consolidation compatibility definitions. */
static inline void synchronize_rcu_bh(void)
{
synchronize_rcu();
}
static inline void synchronize_rcu_bh_expedited(void)
{
synchronize_rcu_expedited();
}
static inline void call_rcu_bh(struct rcu_head *head, rcu_callback_t func)
{
call_rcu(head, func);
}
static inline void rcu_barrier_bh(void)
{
rcu_barrier();
}
static inline void synchronize_sched(void)
{
synchronize_rcu();
}
static inline void synchronize_sched_expedited(void)
{
synchronize_rcu_expedited();
}
static inline void call_rcu_sched(struct rcu_head *head, rcu_callback_t func)
{
call_rcu(head, func);
}
static inline void rcu_barrier_sched(void)
{
rcu_barrier();
}
static inline unsigned long get_state_synchronize_sched(void)
{
return get_state_synchronize_rcu();
}
static inline void cond_synchronize_sched(unsigned long oldstate)
{
cond_synchronize_rcu(oldstate);
}
#endif /* __LINUX_RCUPDATE_H */ #endif /* __LINUX_RCUPDATE_H */
/* SPDX-License-Identifier: GPL-2.0+ */
/* /*
* Read-Copy Update mechanism for mutual exclusion, the Bloatwatch edition. * Read-Copy Update mechanism for mutual exclusion, the Bloatwatch edition.
* *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you can access it online at
* http://www.gnu.org/licenses/gpl-2.0.html.
*
* Copyright IBM Corporation, 2008 * Copyright IBM Corporation, 2008
* *
* Author: Paul E. McKenney <paulmck@linux.vnet.ibm.com> * Author: Paul E. McKenney <paulmck@linux.ibm.com>
* *
* For detailed explanation of Read-Copy Update mechanism see - * For detailed explanation of Read-Copy Update mechanism see -
* Documentation/RCU * Documentation/RCU
......
/* SPDX-License-Identifier: GPL-2.0+ */
/* /*
* Read-Copy Update mechanism for mutual exclusion (tree-based version) * Read-Copy Update mechanism for mutual exclusion (tree-based version)
* *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you can access it online at
* http://www.gnu.org/licenses/gpl-2.0.html.
*
* Copyright IBM Corporation, 2008 * Copyright IBM Corporation, 2008
* *
* Author: Dipankar Sarma <dipankar@in.ibm.com> * Author: Dipankar Sarma <dipankar@in.ibm.com>
* Paul E. McKenney <paulmck@linux.vnet.ibm.com> Hierarchical algorithm * Paul E. McKenney <paulmck@linux.ibm.com> Hierarchical algorithm
* *
* Based on the original work by Paul McKenney <paulmck@us.ibm.com> * Based on the original work by Paul McKenney <paulmck@linux.ibm.com>
* and inputs from Rusty Russell, Andrea Arcangeli and Andi Kleen. * and inputs from Rusty Russell, Andrea Arcangeli and Andi Kleen.
* *
* For detailed explanation of Read-Copy Update mechanism see - * For detailed explanation of Read-Copy Update mechanism see -
......
/* SPDX-License-Identifier: GPL-2.0+ */
/* /*
* Sleepable Read-Copy Update mechanism for mutual exclusion * Sleepable Read-Copy Update mechanism for mutual exclusion
* *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you can access it online at
* http://www.gnu.org/licenses/gpl-2.0.html.
*
* Copyright (C) IBM Corporation, 2006 * Copyright (C) IBM Corporation, 2006
* Copyright (C) Fujitsu, 2012 * Copyright (C) Fujitsu, 2012
* *
* Author: Paul McKenney <paulmck@us.ibm.com> * Author: Paul McKenney <paulmck@linux.ibm.com>
* Lai Jiangshan <laijs@cn.fujitsu.com> * Lai Jiangshan <laijs@cn.fujitsu.com>
* *
* For detailed explanation of Read-Copy Update mechanism see - * For detailed explanation of Read-Copy Update mechanism see -
...@@ -223,6 +210,7 @@ srcu_read_lock_notrace(struct srcu_struct *ssp) __acquires(ssp) ...@@ -223,6 +210,7 @@ srcu_read_lock_notrace(struct srcu_struct *ssp) __acquires(ssp)
static inline void srcu_read_unlock(struct srcu_struct *ssp, int idx) static inline void srcu_read_unlock(struct srcu_struct *ssp, int idx)
__releases(ssp) __releases(ssp)
{ {
WARN_ON_ONCE(idx & ~0x1);
rcu_lock_release(&(ssp)->dep_map); rcu_lock_release(&(ssp)->dep_map);
__srcu_read_unlock(ssp, idx); __srcu_read_unlock(ssp, idx);
} }
......
/* SPDX-License-Identifier: GPL-2.0+ */
/* /*
* Sleepable Read-Copy Update mechanism for mutual exclusion, * Sleepable Read-Copy Update mechanism for mutual exclusion,
* tiny variant. * tiny variant.
* *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you can access it online at
* http://www.gnu.org/licenses/gpl-2.0.html.
*
* Copyright (C) IBM Corporation, 2017 * Copyright (C) IBM Corporation, 2017
* *
* Author: Paul McKenney <paulmck@us.ibm.com> * Author: Paul McKenney <paulmck@linux.ibm.com>
*/ */
#ifndef _LINUX_SRCU_TINY_H #ifndef _LINUX_SRCU_TINY_H
......
/* SPDX-License-Identifier: GPL-2.0+ */
/* /*
* Sleepable Read-Copy Update mechanism for mutual exclusion, * Sleepable Read-Copy Update mechanism for mutual exclusion,
* tree variant. * tree variant.
* *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you can access it online at
* http://www.gnu.org/licenses/gpl-2.0.html.
*
* Copyright (C) IBM Corporation, 2017 * Copyright (C) IBM Corporation, 2017
* *
* Author: Paul McKenney <paulmck@us.ibm.com> * Author: Paul McKenney <paulmck@linux.ibm.com>
*/ */
#ifndef _LINUX_SRCU_TREE_H #ifndef _LINUX_SRCU_TREE_H
...@@ -45,7 +32,8 @@ struct srcu_data { ...@@ -45,7 +32,8 @@ struct srcu_data {
unsigned long srcu_gp_seq_needed; /* Furthest future GP needed. */ unsigned long srcu_gp_seq_needed; /* Furthest future GP needed. */
unsigned long srcu_gp_seq_needed_exp; /* Furthest future exp GP. */ unsigned long srcu_gp_seq_needed_exp; /* Furthest future exp GP. */
bool srcu_cblist_invoking; /* Invoking these CBs? */ bool srcu_cblist_invoking; /* Invoking these CBs? */
struct delayed_work work; /* Context for CB invoking. */ struct timer_list delay_work; /* Delay for CB invoking */
struct work_struct work; /* Context for CB invoking. */
struct rcu_head srcu_barrier_head; /* For srcu_barrier() use. */ struct rcu_head srcu_barrier_head; /* For srcu_barrier() use. */
struct srcu_node *mynode; /* Leaf srcu_node. */ struct srcu_node *mynode; /* Leaf srcu_node. */
unsigned long grpmask; /* Mask for leaf srcu_node */ unsigned long grpmask; /* Mask for leaf srcu_node */
......
/* SPDX-License-Identifier: GPL-2.0+ */
/* /*
* Common functions for in-kernel torture tests. * Common functions for in-kernel torture tests.
* *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you can access it online at
* http://www.gnu.org/licenses/gpl-2.0.html.
*
* Copyright IBM Corporation, 2014 * Copyright IBM Corporation, 2014
* *
* Author: Paul E. McKenney <paulmck@linux.vnet.ibm.com> * Author: Paul E. McKenney <paulmck@linux.ibm.com>
*/ */
#ifndef __LINUX_TORTURE_H #ifndef __LINUX_TORTURE_H
...@@ -50,11 +37,12 @@ ...@@ -50,11 +37,12 @@
do { if (verbose) pr_alert("%s" TORTURE_FLAG "!!! %s\n", torture_type, s); } while (0) do { if (verbose) pr_alert("%s" TORTURE_FLAG "!!! %s\n", torture_type, s); } while (0)
/* Definitions for online/offline exerciser. */ /* Definitions for online/offline exerciser. */
typedef void torture_ofl_func(void);
bool torture_offline(int cpu, long *n_onl_attempts, long *n_onl_successes, bool torture_offline(int cpu, long *n_onl_attempts, long *n_onl_successes,
unsigned long *sum_offl, int *min_onl, int *max_onl); unsigned long *sum_offl, int *min_onl, int *max_onl);
bool torture_online(int cpu, long *n_onl_attempts, long *n_onl_successes, bool torture_online(int cpu, long *n_onl_attempts, long *n_onl_successes,
unsigned long *sum_onl, int *min_onl, int *max_onl); unsigned long *sum_onl, int *min_onl, int *max_onl);
int torture_onoff_init(long ooholdoff, long oointerval); int torture_onoff_init(long ooholdoff, long oointerval, torture_ofl_func *f);
void torture_onoff_stats(void); void torture_onoff_stats(void);
bool torture_onoff_failures(void); bool torture_onoff_failures(void);
......
// SPDX-License-Identifier: GPL-2.0+
/* /*
* Module-based torture test facility for locking * Module-based torture test facility for locking
* *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you can access it online at
* http://www.gnu.org/licenses/gpl-2.0.html.
*
* Copyright (C) IBM Corporation, 2014 * Copyright (C) IBM Corporation, 2014
* *
* Authors: Paul E. McKenney <paulmck@us.ibm.com> * Authors: Paul E. McKenney <paulmck@linux.ibm.com>
* Davidlohr Bueso <dave@stgolabs.net> * Davidlohr Bueso <dave@stgolabs.net>
* Based on kernel/rcu/torture.c. * Based on kernel/rcu/torture.c.
*/ */
...@@ -45,7 +32,7 @@ ...@@ -45,7 +32,7 @@
#include <linux/torture.h> #include <linux/torture.h>
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_AUTHOR("Paul E. McKenney <paulmck@us.ibm.com>"); MODULE_AUTHOR("Paul E. McKenney <paulmck@linux.ibm.com>");
torture_param(int, nwriters_stress, -1, torture_param(int, nwriters_stress, -1,
"Number of write-locking stress-test threads"); "Number of write-locking stress-test threads");
...@@ -970,7 +957,7 @@ static int __init lock_torture_init(void) ...@@ -970,7 +957,7 @@ static int __init lock_torture_init(void)
/* Prepare torture context. */ /* Prepare torture context. */
if (onoff_interval > 0) { if (onoff_interval > 0) {
firsterr = torture_onoff_init(onoff_holdoff * HZ, firsterr = torture_onoff_init(onoff_holdoff * HZ,
onoff_interval * HZ); onoff_interval * HZ, NULL);
if (firsterr) if (firsterr)
goto unwind; goto unwind;
} }
......
/* SPDX-License-Identifier: GPL-2.0+ */
/* /*
* Read-Copy Update definitions shared among RCU implementations. * Read-Copy Update definitions shared among RCU implementations.
* *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you can access it online at
* http://www.gnu.org/licenses/gpl-2.0.html.
*
* Copyright IBM Corporation, 2011 * Copyright IBM Corporation, 2011
* *
* Author: Paul E. McKenney <paulmck@linux.vnet.ibm.com> * Author: Paul E. McKenney <paulmck@linux.ibm.com>
*/ */
#ifndef __LINUX_RCU_H #ifndef __LINUX_RCU_H
...@@ -30,7 +17,7 @@ ...@@ -30,7 +17,7 @@
#define RCU_TRACE(stmt) #define RCU_TRACE(stmt)
#endif /* #else #ifdef CONFIG_RCU_TRACE */ #endif /* #else #ifdef CONFIG_RCU_TRACE */
/* Offset to allow for unmatched rcu_irq_{enter,exit}(). */ /* Offset to allow distinguishing irq vs. task-based idle entry/exit. */
#define DYNTICK_IRQ_NONIDLE ((LONG_MAX / 2) + 1) #define DYNTICK_IRQ_NONIDLE ((LONG_MAX / 2) + 1)
...@@ -462,8 +449,6 @@ void rcu_request_urgent_qs_task(struct task_struct *t); ...@@ -462,8 +449,6 @@ void rcu_request_urgent_qs_task(struct task_struct *t);
enum rcutorture_type { enum rcutorture_type {
RCU_FLAVOR, RCU_FLAVOR,
RCU_BH_FLAVOR,
RCU_SCHED_FLAVOR,
RCU_TASKS_FLAVOR, RCU_TASKS_FLAVOR,
SRCU_FLAVOR, SRCU_FLAVOR,
INVALID_RCU_FLAVOR INVALID_RCU_FLAVOR
......
// SPDX-License-Identifier: GPL-2.0+
/* /*
* RCU segmented callback lists, function definitions * RCU segmented callback lists, function definitions
* *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you can access it online at
* http://www.gnu.org/licenses/gpl-2.0.html.
*
* Copyright IBM Corporation, 2017 * Copyright IBM Corporation, 2017
* *
* Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com> * Authors: Paul E. McKenney <paulmck@linux.ibm.com>
*/ */
#include <linux/types.h> #include <linux/types.h>
......
/* SPDX-License-Identifier: GPL-2.0+ */
/* /*
* RCU segmented callback lists, internal-to-rcu header file * RCU segmented callback lists, internal-to-rcu header file
* *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you can access it online at
* http://www.gnu.org/licenses/gpl-2.0.html.
*
* Copyright IBM Corporation, 2017 * Copyright IBM Corporation, 2017
* *
* Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com> * Authors: Paul E. McKenney <paulmck@linux.ibm.com>
*/ */
#include <linux/rcu_segcblist.h> #include <linux/rcu_segcblist.h>
......
// SPDX-License-Identifier: GPL-2.0+
/* /*
* Read-Copy Update module-based performance-test facility * Read-Copy Update module-based performance-test facility
* *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you can access it online at
* http://www.gnu.org/licenses/gpl-2.0.html.
*
* Copyright (C) IBM Corporation, 2015 * Copyright (C) IBM Corporation, 2015
* *
* Authors: Paul E. McKenney <paulmck@us.ibm.com> * Authors: Paul E. McKenney <paulmck@linux.ibm.com>
*/ */
#define pr_fmt(fmt) fmt #define pr_fmt(fmt) fmt
...@@ -54,7 +41,7 @@ ...@@ -54,7 +41,7 @@
#include "rcu.h" #include "rcu.h"
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_AUTHOR("Paul E. McKenney <paulmck@linux.vnet.ibm.com>"); MODULE_AUTHOR("Paul E. McKenney <paulmck@linux.ibm.com>");
#define PERF_FLAG "-perf:" #define PERF_FLAG "-perf:"
#define PERFOUT_STRING(s) \ #define PERFOUT_STRING(s) \
...@@ -83,13 +70,19 @@ MODULE_AUTHOR("Paul E. McKenney <paulmck@linux.vnet.ibm.com>"); ...@@ -83,13 +70,19 @@ MODULE_AUTHOR("Paul E. McKenney <paulmck@linux.vnet.ibm.com>");
* Various other use cases may of course be specified. * Various other use cases may of course be specified.
*/ */
#ifdef MODULE
# define RCUPERF_SHUTDOWN 0
#else
# define RCUPERF_SHUTDOWN 1
#endif
torture_param(bool, gp_async, false, "Use asynchronous GP wait primitives"); torture_param(bool, gp_async, false, "Use asynchronous GP wait primitives");
torture_param(int, gp_async_max, 1000, "Max # outstanding waits per reader"); torture_param(int, gp_async_max, 1000, "Max # outstanding waits per reader");
torture_param(bool, gp_exp, false, "Use expedited GP wait primitives"); torture_param(bool, gp_exp, false, "Use expedited GP wait primitives");
torture_param(int, holdoff, 10, "Holdoff time before test start (s)"); torture_param(int, holdoff, 10, "Holdoff time before test start (s)");
torture_param(int, nreaders, -1, "Number of RCU reader threads"); torture_param(int, nreaders, -1, "Number of RCU reader threads");
torture_param(int, nwriters, -1, "Number of RCU updater threads"); torture_param(int, nwriters, -1, "Number of RCU updater threads");
torture_param(bool, shutdown, !IS_ENABLED(MODULE), torture_param(bool, shutdown, RCUPERF_SHUTDOWN,
"Shutdown at end of performance tests."); "Shutdown at end of performance tests.");
torture_param(int, verbose, 1, "Enable verbose debugging printk()s"); torture_param(int, verbose, 1, "Enable verbose debugging printk()s");
torture_param(int, writer_holdoff, 0, "Holdoff (us) between GPs, zero to disable"); torture_param(int, writer_holdoff, 0, "Holdoff (us) between GPs, zero to disable");
......
// SPDX-License-Identifier: GPL-2.0+
/* /*
* Read-Copy Update module-based torture test facility * Read-Copy Update module-based torture test facility
* *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you can access it online at
* http://www.gnu.org/licenses/gpl-2.0.html.
*
* Copyright (C) IBM Corporation, 2005, 2006 * Copyright (C) IBM Corporation, 2005, 2006
* *
* Authors: Paul E. McKenney <paulmck@us.ibm.com> * Authors: Paul E. McKenney <paulmck@linux.ibm.com>
* Josh Triplett <josh@joshtriplett.org> * Josh Triplett <josh@joshtriplett.org>
* *
* See also: Documentation/RCU/torture.txt * See also: Documentation/RCU/torture.txt
...@@ -61,7 +48,7 @@ ...@@ -61,7 +48,7 @@
#include "rcu.h" #include "rcu.h"
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_AUTHOR("Paul E. McKenney <paulmck@us.ibm.com> and Josh Triplett <josh@joshtriplett.org>"); MODULE_AUTHOR("Paul E. McKenney <paulmck@linux.ibm.com> and Josh Triplett <josh@joshtriplett.org>");
/* Bits for ->extendables field, extendables param, and related definitions. */ /* Bits for ->extendables field, extendables param, and related definitions. */
...@@ -1630,21 +1617,34 @@ static bool rcu_fwd_emergency_stop; ...@@ -1630,21 +1617,34 @@ static bool rcu_fwd_emergency_stop;
#define MIN_FWD_CB_LAUNDERS 3 /* This many CB invocations to count. */ #define MIN_FWD_CB_LAUNDERS 3 /* This many CB invocations to count. */
#define MIN_FWD_CBS_LAUNDERED 100 /* Number of counted CBs. */ #define MIN_FWD_CBS_LAUNDERED 100 /* Number of counted CBs. */
#define FWD_CBS_HIST_DIV 10 /* Histogram buckets/second. */ #define FWD_CBS_HIST_DIV 10 /* Histogram buckets/second. */
static long n_launders_hist[2 * MAX_FWD_CB_JIFFIES / (HZ / FWD_CBS_HIST_DIV)]; struct rcu_launder_hist {
long n_launders;
unsigned long launder_gp_seq;
};
#define N_LAUNDERS_HIST (2 * MAX_FWD_CB_JIFFIES / (HZ / FWD_CBS_HIST_DIV))
static struct rcu_launder_hist n_launders_hist[N_LAUNDERS_HIST];
static unsigned long rcu_launder_gp_seq_start;
static void rcu_torture_fwd_cb_hist(void) static void rcu_torture_fwd_cb_hist(void)
{ {
unsigned long gps;
unsigned long gps_old;
int i; int i;
int j; int j;
for (i = ARRAY_SIZE(n_launders_hist) - 1; i > 0; i--) for (i = ARRAY_SIZE(n_launders_hist) - 1; i > 0; i--)
if (n_launders_hist[i] > 0) if (n_launders_hist[i].n_launders > 0)
break; break;
pr_alert("%s: Callback-invocation histogram (duration %lu jiffies):", pr_alert("%s: Callback-invocation histogram (duration %lu jiffies):",
__func__, jiffies - rcu_fwd_startat); __func__, jiffies - rcu_fwd_startat);
for (j = 0; j <= i; j++) gps_old = rcu_launder_gp_seq_start;
pr_cont(" %ds/%d: %ld", for (j = 0; j <= i; j++) {
j + 1, FWD_CBS_HIST_DIV, n_launders_hist[j]); gps = n_launders_hist[j].launder_gp_seq;
pr_cont(" %ds/%d: %ld:%ld",
j + 1, FWD_CBS_HIST_DIV, n_launders_hist[j].n_launders,
rcutorture_seq_diff(gps, gps_old));
gps_old = gps;
}
pr_cont("\n"); pr_cont("\n");
} }
...@@ -1666,7 +1666,8 @@ static void rcu_torture_fwd_cb_cr(struct rcu_head *rhp) ...@@ -1666,7 +1666,8 @@ static void rcu_torture_fwd_cb_cr(struct rcu_head *rhp)
i = ((jiffies - rcu_fwd_startat) / (HZ / FWD_CBS_HIST_DIV)); i = ((jiffies - rcu_fwd_startat) / (HZ / FWD_CBS_HIST_DIV));
if (i >= ARRAY_SIZE(n_launders_hist)) if (i >= ARRAY_SIZE(n_launders_hist))
i = ARRAY_SIZE(n_launders_hist) - 1; i = ARRAY_SIZE(n_launders_hist) - 1;
n_launders_hist[i]++; n_launders_hist[i].n_launders++;
n_launders_hist[i].launder_gp_seq = cur_ops->get_gp_seq();
spin_unlock_irqrestore(&rcu_fwd_lock, flags); spin_unlock_irqrestore(&rcu_fwd_lock, flags);
} }
...@@ -1786,9 +1787,10 @@ static void rcu_torture_fwd_prog_cr(void) ...@@ -1786,9 +1787,10 @@ static void rcu_torture_fwd_prog_cr(void)
n_max_cbs = 0; n_max_cbs = 0;
n_max_gps = 0; n_max_gps = 0;
for (i = 0; i < ARRAY_SIZE(n_launders_hist); i++) for (i = 0; i < ARRAY_SIZE(n_launders_hist); i++)
n_launders_hist[i] = 0; n_launders_hist[i].n_launders = 0;
cver = READ_ONCE(rcu_torture_current_version); cver = READ_ONCE(rcu_torture_current_version);
gps = cur_ops->get_gp_seq(); gps = cur_ops->get_gp_seq();
rcu_launder_gp_seq_start = gps;
while (time_before(jiffies, stopat) && while (time_before(jiffies, stopat) &&
!READ_ONCE(rcu_fwd_emergency_stop) && !torture_must_stop()) { !READ_ONCE(rcu_fwd_emergency_stop) && !torture_must_stop()) {
rfcp = READ_ONCE(rcu_fwd_cb_head); rfcp = READ_ONCE(rcu_fwd_cb_head);
...@@ -2228,6 +2230,14 @@ static void rcu_test_debug_objects(void) ...@@ -2228,6 +2230,14 @@ static void rcu_test_debug_objects(void)
#endif /* #else #ifdef CONFIG_DEBUG_OBJECTS_RCU_HEAD */ #endif /* #else #ifdef CONFIG_DEBUG_OBJECTS_RCU_HEAD */
} }
static void rcutorture_sync(void)
{
static unsigned long n;
if (cur_ops->sync && !(++n & 0xfff))
cur_ops->sync();
}
static int __init static int __init
rcu_torture_init(void) rcu_torture_init(void)
{ {
...@@ -2389,7 +2399,8 @@ rcu_torture_init(void) ...@@ -2389,7 +2399,8 @@ rcu_torture_init(void)
firsterr = torture_shutdown_init(shutdown_secs, rcu_torture_cleanup); firsterr = torture_shutdown_init(shutdown_secs, rcu_torture_cleanup);
if (firsterr) if (firsterr)
goto unwind; goto unwind;
firsterr = torture_onoff_init(onoff_holdoff * HZ, onoff_interval); firsterr = torture_onoff_init(onoff_holdoff * HZ, onoff_interval,
rcutorture_sync);
if (firsterr) if (firsterr)
goto unwind; goto unwind;
firsterr = rcu_torture_stall_init(); firsterr = rcu_torture_stall_init();
......
// SPDX-License-Identifier: GPL-2.0+
/* /*
* Sleepable Read-Copy Update mechanism for mutual exclusion, * Sleepable Read-Copy Update mechanism for mutual exclusion,
* tiny version for non-preemptible single-CPU use. * tiny version for non-preemptible single-CPU use.
* *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you can access it online at
* http://www.gnu.org/licenses/gpl-2.0.html.
*
* Copyright (C) IBM Corporation, 2017 * Copyright (C) IBM Corporation, 2017
* *
* Author: Paul McKenney <paulmck@us.ibm.com> * Author: Paul McKenney <paulmck@linux.ibm.com>
*/ */
#include <linux/export.h> #include <linux/export.h>
......
// SPDX-License-Identifier: GPL-2.0+
/* /*
* Sleepable Read-Copy Update mechanism for mutual exclusion. * Sleepable Read-Copy Update mechanism for mutual exclusion.
* *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you can access it online at
* http://www.gnu.org/licenses/gpl-2.0.html.
*
* Copyright (C) IBM Corporation, 2006 * Copyright (C) IBM Corporation, 2006
* Copyright (C) Fujitsu, 2012 * Copyright (C) Fujitsu, 2012
* *
* Author: Paul McKenney <paulmck@us.ibm.com> * Author: Paul McKenney <paulmck@linux.ibm.com>
* Lai Jiangshan <laijs@cn.fujitsu.com> * Lai Jiangshan <laijs@cn.fujitsu.com>
* *
* For detailed explanation of Read-Copy Update mechanism see - * For detailed explanation of Read-Copy Update mechanism see -
...@@ -58,6 +45,7 @@ static bool __read_mostly srcu_init_done; ...@@ -58,6 +45,7 @@ static bool __read_mostly srcu_init_done;
static void srcu_invoke_callbacks(struct work_struct *work); static void srcu_invoke_callbacks(struct work_struct *work);
static void srcu_reschedule(struct srcu_struct *ssp, unsigned long delay); static void srcu_reschedule(struct srcu_struct *ssp, unsigned long delay);
static void process_srcu(struct work_struct *work); static void process_srcu(struct work_struct *work);
static void srcu_delay_timer(struct timer_list *t);
/* Wrappers for lock acquisition and release, see raw_spin_lock_rcu_node(). */ /* Wrappers for lock acquisition and release, see raw_spin_lock_rcu_node(). */
#define spin_lock_rcu_node(p) \ #define spin_lock_rcu_node(p) \
...@@ -156,7 +144,8 @@ static void init_srcu_struct_nodes(struct srcu_struct *ssp, bool is_static) ...@@ -156,7 +144,8 @@ static void init_srcu_struct_nodes(struct srcu_struct *ssp, bool is_static)
snp->grphi = cpu; snp->grphi = cpu;
} }
sdp->cpu = cpu; sdp->cpu = cpu;
INIT_DELAYED_WORK(&sdp->work, srcu_invoke_callbacks); INIT_WORK(&sdp->work, srcu_invoke_callbacks);
timer_setup(&sdp->delay_work, srcu_delay_timer, 0);
sdp->ssp = ssp; sdp->ssp = ssp;
sdp->grpmask = 1 << (cpu - sdp->mynode->grplo); sdp->grpmask = 1 << (cpu - sdp->mynode->grplo);
if (is_static) if (is_static)
...@@ -386,12 +375,18 @@ void _cleanup_srcu_struct(struct srcu_struct *ssp, bool quiesced) ...@@ -386,12 +375,18 @@ void _cleanup_srcu_struct(struct srcu_struct *ssp, bool quiesced)
} else { } else {
flush_delayed_work(&ssp->work); flush_delayed_work(&ssp->work);
} }
for_each_possible_cpu(cpu) for_each_possible_cpu(cpu) {
struct srcu_data *sdp = per_cpu_ptr(ssp->sda, cpu);
if (quiesced) { if (quiesced) {
if (WARN_ON(delayed_work_pending(&per_cpu_ptr(ssp->sda, cpu)->work))) if (WARN_ON(timer_pending(&sdp->delay_work)))
return; /* Just leak it! */
if (WARN_ON(work_pending(&sdp->work)))
return; /* Just leak it! */ return; /* Just leak it! */
} else { } else {
flush_delayed_work(&per_cpu_ptr(ssp->sda, cpu)->work); del_timer_sync(&sdp->delay_work);
flush_work(&sdp->work);
}
} }
if (WARN_ON(rcu_seq_state(READ_ONCE(ssp->srcu_gp_seq)) != SRCU_STATE_IDLE) || if (WARN_ON(rcu_seq_state(READ_ONCE(ssp->srcu_gp_seq)) != SRCU_STATE_IDLE) ||
WARN_ON(srcu_readers_active(ssp))) { WARN_ON(srcu_readers_active(ssp))) {
...@@ -463,39 +458,23 @@ static void srcu_gp_start(struct srcu_struct *ssp) ...@@ -463,39 +458,23 @@ static void srcu_gp_start(struct srcu_struct *ssp)
WARN_ON_ONCE(state != SRCU_STATE_SCAN1); WARN_ON_ONCE(state != SRCU_STATE_SCAN1);
} }
/*
* Track online CPUs to guide callback workqueue placement.
*/
DEFINE_PER_CPU(bool, srcu_online);
void srcu_online_cpu(unsigned int cpu) static void srcu_delay_timer(struct timer_list *t)
{ {
WRITE_ONCE(per_cpu(srcu_online, cpu), true); struct srcu_data *sdp = container_of(t, struct srcu_data, delay_work);
}
void srcu_offline_cpu(unsigned int cpu) queue_work_on(sdp->cpu, rcu_gp_wq, &sdp->work);
{
WRITE_ONCE(per_cpu(srcu_online, cpu), false);
} }
/* static void srcu_queue_delayed_work_on(struct srcu_data *sdp,
* Place the workqueue handler on the specified CPU if online, otherwise
* just run it whereever. This is useful for placing workqueue handlers
* that are to invoke the specified CPU's callbacks.
*/
static bool srcu_queue_delayed_work_on(int cpu, struct workqueue_struct *wq,
struct delayed_work *dwork,
unsigned long delay) unsigned long delay)
{ {
bool ret; if (!delay) {
queue_work_on(sdp->cpu, rcu_gp_wq, &sdp->work);
return;
}
preempt_disable(); timer_reduce(&sdp->delay_work, jiffies + delay);
if (READ_ONCE(per_cpu(srcu_online, cpu)))
ret = queue_delayed_work_on(cpu, wq, dwork, delay);
else
ret = queue_delayed_work(wq, dwork, delay);
preempt_enable();
return ret;
} }
/* /*
...@@ -504,7 +483,7 @@ static bool srcu_queue_delayed_work_on(int cpu, struct workqueue_struct *wq, ...@@ -504,7 +483,7 @@ static bool srcu_queue_delayed_work_on(int cpu, struct workqueue_struct *wq,
*/ */
static void srcu_schedule_cbs_sdp(struct srcu_data *sdp, unsigned long delay) static void srcu_schedule_cbs_sdp(struct srcu_data *sdp, unsigned long delay)
{ {
srcu_queue_delayed_work_on(sdp->cpu, rcu_gp_wq, &sdp->work, delay); srcu_queue_delayed_work_on(sdp, delay);
} }
/* /*
...@@ -1186,7 +1165,8 @@ static void srcu_invoke_callbacks(struct work_struct *work) ...@@ -1186,7 +1165,8 @@ static void srcu_invoke_callbacks(struct work_struct *work)
struct srcu_data *sdp; struct srcu_data *sdp;
struct srcu_struct *ssp; struct srcu_struct *ssp;
sdp = container_of(work, struct srcu_data, work.work); sdp = container_of(work, struct srcu_data, work);
ssp = sdp->ssp; ssp = sdp->ssp;
rcu_cblist_init(&ready_cbs); rcu_cblist_init(&ready_cbs);
spin_lock_irq_rcu_node(sdp); spin_lock_irq_rcu_node(sdp);
......
// SPDX-License-Identifier: GPL-2.0+
/* /*
* RCU-based infrastructure for lightweight reader-writer locking * RCU-based infrastructure for lightweight reader-writer locking
* *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you can access it online at
* http://www.gnu.org/licenses/gpl-2.0.html.
*
* Copyright (c) 2015, Red Hat, Inc. * Copyright (c) 2015, Red Hat, Inc.
* *
* Author: Oleg Nesterov <oleg@redhat.com> * Author: Oleg Nesterov <oleg@redhat.com>
......
// SPDX-License-Identifier: GPL-2.0+
/* /*
* Read-Copy Update mechanism for mutual exclusion, the Bloatwatch edition. * Read-Copy Update mechanism for mutual exclusion, the Bloatwatch edition.
* *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you can access it online at
* http://www.gnu.org/licenses/gpl-2.0.html.
*
* Copyright IBM Corporation, 2008 * Copyright IBM Corporation, 2008
* *
* Author: Paul E. McKenney <paulmck@linux.vnet.ibm.com> * Author: Paul E. McKenney <paulmck@linux.ibm.com>
* *
* For detailed explanation of Read-Copy Update mechanism see - * For detailed explanation of Read-Copy Update mechanism see -
* Documentation/RCU * Documentation/RCU
...@@ -76,7 +63,7 @@ void rcu_qs(void) ...@@ -76,7 +63,7 @@ void rcu_qs(void)
* be called from hardirq context. It is normally called from the * be called from hardirq context. It is normally called from the
* scheduling-clock interrupt. * scheduling-clock interrupt.
*/ */
void rcu_check_callbacks(int user) void rcu_sched_clock_irq(int user)
{ {
if (user) { if (user) {
rcu_qs(); rcu_qs();
......
This diff is collapsed.
/* SPDX-License-Identifier: GPL-2.0+ */
/* /*
* Read-Copy Update mechanism for mutual exclusion (tree-based version) * Read-Copy Update mechanism for mutual exclusion (tree-based version)
* Internal non-public definitions. * Internal non-public definitions.
* *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you can access it online at
* http://www.gnu.org/licenses/gpl-2.0.html.
*
* Copyright IBM Corporation, 2008 * Copyright IBM Corporation, 2008
* *
* Author: Ingo Molnar <mingo@elte.hu> * Author: Ingo Molnar <mingo@elte.hu>
* Paul E. McKenney <paulmck@linux.vnet.ibm.com> * Paul E. McKenney <paulmck@linux.ibm.com>
*/ */
#include <linux/cache.h> #include <linux/cache.h>
...@@ -36,7 +23,6 @@ ...@@ -36,7 +23,6 @@
/* Communicate arguments to a workqueue handler. */ /* Communicate arguments to a workqueue handler. */
struct rcu_exp_work { struct rcu_exp_work {
smp_call_func_t rew_func;
unsigned long rew_s; unsigned long rew_s;
struct work_struct rew_work; struct work_struct rew_work;
}; };
...@@ -194,10 +180,7 @@ struct rcu_data { ...@@ -194,10 +180,7 @@ struct rcu_data {
bool rcu_need_heavy_qs; /* GP old, so heavy quiescent state! */ bool rcu_need_heavy_qs; /* GP old, so heavy quiescent state! */
bool rcu_urgent_qs; /* GP old need light quiescent state. */ bool rcu_urgent_qs; /* GP old need light quiescent state. */
#ifdef CONFIG_RCU_FAST_NO_HZ #ifdef CONFIG_RCU_FAST_NO_HZ
bool all_lazy; /* Are all CPU's CBs lazy? */ bool all_lazy; /* All CPU's CBs lazy at idle start? */
unsigned long nonlazy_posted; /* # times non-lazy CB posted to CPU. */
unsigned long nonlazy_posted_snap;
/* Nonlazy_posted snapshot. */
unsigned long last_accelerate; /* Last jiffy CBs were accelerated. */ unsigned long last_accelerate; /* Last jiffy CBs were accelerated. */
unsigned long last_advance_all; /* Last jiffy CBs were all advanced. */ unsigned long last_advance_all; /* Last jiffy CBs were all advanced. */
int tick_nohz_enabled_snap; /* Previously seen value from sysfs. */ int tick_nohz_enabled_snap; /* Previously seen value from sysfs. */
...@@ -234,7 +217,13 @@ struct rcu_data { ...@@ -234,7 +217,13 @@ struct rcu_data {
/* Leader CPU takes GP-end wakeups. */ /* Leader CPU takes GP-end wakeups. */
#endif /* #ifdef CONFIG_RCU_NOCB_CPU */ #endif /* #ifdef CONFIG_RCU_NOCB_CPU */
/* 6) Diagnostic data, including RCU CPU stall warnings. */ /* 6) RCU priority boosting. */
struct task_struct *rcu_cpu_kthread_task;
/* rcuc per-CPU kthread or NULL. */
unsigned int rcu_cpu_kthread_status;
char rcu_cpu_has_work;
/* 7) Diagnostic data, including RCU CPU stall warnings. */
unsigned int softirq_snap; /* Snapshot of softirq activity. */ unsigned int softirq_snap; /* Snapshot of softirq activity. */
/* ->rcu_iw* fields protected by leaf rcu_node ->lock. */ /* ->rcu_iw* fields protected by leaf rcu_node ->lock. */
struct irq_work rcu_iw; /* Check for non-irq activity. */ struct irq_work rcu_iw; /* Check for non-irq activity. */
...@@ -303,6 +292,8 @@ struct rcu_state { ...@@ -303,6 +292,8 @@ struct rcu_state {
struct swait_queue_head gp_wq; /* Where GP task waits. */ struct swait_queue_head gp_wq; /* Where GP task waits. */
short gp_flags; /* Commands for GP task. */ short gp_flags; /* Commands for GP task. */
short gp_state; /* GP kthread sleep state. */ short gp_state; /* GP kthread sleep state. */
unsigned long gp_wake_time; /* Last GP kthread wake. */
unsigned long gp_wake_seq; /* ->gp_seq at ^^^. */
/* End of fields guarded by root rcu_node's lock. */ /* End of fields guarded by root rcu_node's lock. */
...@@ -402,13 +393,6 @@ static const char *tp_rcu_varname __used __tracepoint_string = rcu_name; ...@@ -402,13 +393,6 @@ static const char *tp_rcu_varname __used __tracepoint_string = rcu_name;
int rcu_dynticks_snap(struct rcu_data *rdp); int rcu_dynticks_snap(struct rcu_data *rdp);
#ifdef CONFIG_RCU_BOOST
DECLARE_PER_CPU(unsigned int, rcu_cpu_kthread_status);
DECLARE_PER_CPU(int, rcu_cpu_kthread_cpu);
DECLARE_PER_CPU(unsigned int, rcu_cpu_kthread_loops);
DECLARE_PER_CPU(char, rcu_cpu_has_work);
#endif /* #ifdef CONFIG_RCU_BOOST */
/* Forward declarations for rcutree_plugin.h */ /* Forward declarations for rcutree_plugin.h */
static void rcu_bootup_announce(void); static void rcu_bootup_announce(void);
static void rcu_qs(void); static void rcu_qs(void);
...@@ -420,7 +404,7 @@ static void rcu_print_detail_task_stall(void); ...@@ -420,7 +404,7 @@ static void rcu_print_detail_task_stall(void);
static int rcu_print_task_stall(struct rcu_node *rnp); static int rcu_print_task_stall(struct rcu_node *rnp);
static int rcu_print_task_exp_stall(struct rcu_node *rnp); static int rcu_print_task_exp_stall(struct rcu_node *rnp);
static void rcu_preempt_check_blocked_tasks(struct rcu_node *rnp); static void rcu_preempt_check_blocked_tasks(struct rcu_node *rnp);
static void rcu_flavor_check_callbacks(int user); static void rcu_flavor_sched_clock_irq(int user);
void call_rcu(struct rcu_head *head, rcu_callback_t func); void call_rcu(struct rcu_head *head, rcu_callback_t func);
static void dump_blkd_tasks(struct rcu_node *rnp, int ncheck); static void dump_blkd_tasks(struct rcu_node *rnp, int ncheck);
static void rcu_initiate_boost(struct rcu_node *rnp, unsigned long flags); static void rcu_initiate_boost(struct rcu_node *rnp, unsigned long flags);
...@@ -431,7 +415,6 @@ static void __init rcu_spawn_boost_kthreads(void); ...@@ -431,7 +415,6 @@ static void __init rcu_spawn_boost_kthreads(void);
static void rcu_prepare_kthreads(int cpu); static void rcu_prepare_kthreads(int cpu);
static void rcu_cleanup_after_idle(void); static void rcu_cleanup_after_idle(void);
static void rcu_prepare_for_idle(void); static void rcu_prepare_for_idle(void);
static void rcu_idle_count_callbacks_posted(void);
static bool rcu_preempt_has_tasks(struct rcu_node *rnp); static bool rcu_preempt_has_tasks(struct rcu_node *rnp);
static bool rcu_preempt_need_deferred_qs(struct task_struct *t); static bool rcu_preempt_need_deferred_qs(struct task_struct *t);
static void rcu_preempt_deferred_qs(struct task_struct *t); static void rcu_preempt_deferred_qs(struct task_struct *t);
...@@ -451,7 +434,7 @@ static bool rcu_nocb_adopt_orphan_cbs(struct rcu_data *my_rdp, ...@@ -451,7 +434,7 @@ static bool rcu_nocb_adopt_orphan_cbs(struct rcu_data *my_rdp,
static int rcu_nocb_need_deferred_wakeup(struct rcu_data *rdp); static int rcu_nocb_need_deferred_wakeup(struct rcu_data *rdp);
static void do_nocb_deferred_wakeup(struct rcu_data *rdp); static void do_nocb_deferred_wakeup(struct rcu_data *rdp);
static void rcu_boot_init_nocb_percpu_data(struct rcu_data *rdp); static void rcu_boot_init_nocb_percpu_data(struct rcu_data *rdp);
static void rcu_spawn_all_nocb_kthreads(int cpu); static void rcu_spawn_cpu_nocb_kthread(int cpu);
static void __init rcu_spawn_nocb_kthreads(void); static void __init rcu_spawn_nocb_kthreads(void);
#ifdef CONFIG_RCU_NOCB_CPU #ifdef CONFIG_RCU_NOCB_CPU
static void __init rcu_organize_nocb_kthreads(void); static void __init rcu_organize_nocb_kthreads(void);
...@@ -462,11 +445,3 @@ static void rcu_bind_gp_kthread(void); ...@@ -462,11 +445,3 @@ static void rcu_bind_gp_kthread(void);
static bool rcu_nohz_full_cpu(void); static bool rcu_nohz_full_cpu(void);
static void rcu_dynticks_task_enter(void); static void rcu_dynticks_task_enter(void);
static void rcu_dynticks_task_exit(void); static void rcu_dynticks_task_exit(void);
#ifdef CONFIG_SRCU
void srcu_online_cpu(unsigned int cpu);
void srcu_offline_cpu(unsigned int cpu);
#else /* #ifdef CONFIG_SRCU */
void srcu_online_cpu(unsigned int cpu) { }
void srcu_offline_cpu(unsigned int cpu) { }
#endif /* #else #ifdef CONFIG_SRCU */
This diff is collapsed.
This diff is collapsed.
// SPDX-License-Identifier: GPL-2.0+
/* /*
* Read-Copy Update mechanism for mutual exclusion * Read-Copy Update mechanism for mutual exclusion
* *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you can access it online at
* http://www.gnu.org/licenses/gpl-2.0.html.
*
* Copyright IBM Corporation, 2001 * Copyright IBM Corporation, 2001
* *
* Authors: Dipankar Sarma <dipankar@in.ibm.com> * Authors: Dipankar Sarma <dipankar@in.ibm.com>
* Manfred Spraul <manfred@colorfullife.com> * Manfred Spraul <manfred@colorfullife.com>
* *
* Based on the original work by Paul McKenney <paulmck@us.ibm.com> * Based on the original work by Paul McKenney <paulmck@linux.ibm.com>
* and inputs from Rusty Russell, Andrea Arcangeli and Andi Kleen. * and inputs from Rusty Russell, Andrea Arcangeli and Andi Kleen.
* Papers: * Papers:
* http://www.rdrop.com/users/paulmck/paper/rclockpdcsproof.pdf * http://www.rdrop.com/users/paulmck/paper/rclockpdcsproof.pdf
......
...@@ -48,8 +48,8 @@ EXPORT_SYMBOL_GPL(cpufreq_add_update_util_hook); ...@@ -48,8 +48,8 @@ EXPORT_SYMBOL_GPL(cpufreq_add_update_util_hook);
* *
* Clear the update_util_data pointer for the given CPU. * Clear the update_util_data pointer for the given CPU.
* *
* Callers must use RCU-sched callbacks to free any memory that might be * Callers must use RCU callbacks to free any memory that might be
* accessed via the old update_util_data pointer or invoke synchronize_sched() * accessed via the old update_util_data pointer or invoke synchronize_rcu()
* right after this function to avoid use-after-free. * right after this function to avoid use-after-free.
*/ */
void cpufreq_remove_update_util_hook(int cpu) void cpufreq_remove_update_util_hook(int cpu)
......
...@@ -859,7 +859,7 @@ static void sugov_stop(struct cpufreq_policy *policy) ...@@ -859,7 +859,7 @@ static void sugov_stop(struct cpufreq_policy *policy)
for_each_cpu(cpu, policy->cpus) for_each_cpu(cpu, policy->cpus)
cpufreq_remove_update_util_hook(cpu); cpufreq_remove_update_util_hook(cpu);
synchronize_sched(); synchronize_rcu();
if (!policy->fast_switch_enabled) { if (!policy->fast_switch_enabled) {
irq_work_sync(&sg_policy->irq_work); irq_work_sync(&sg_policy->irq_work);
......
...@@ -1260,7 +1260,7 @@ extern void sched_ttwu_pending(void); ...@@ -1260,7 +1260,7 @@ extern void sched_ttwu_pending(void);
/* /*
* The domain tree (rq->sd) is protected by RCU's quiescent state transition. * The domain tree (rq->sd) is protected by RCU's quiescent state transition.
* See detach_destroy_domains: synchronize_sched for details. * See destroy_sched_domains: call_rcu for details.
* *
* The domain tree of any CPU may only be accessed from within * The domain tree of any CPU may only be accessed from within
* preempt-disabled sections. * preempt-disabled sections.
......
...@@ -442,7 +442,7 @@ void rq_attach_root(struct rq *rq, struct root_domain *rd) ...@@ -442,7 +442,7 @@ void rq_attach_root(struct rq *rq, struct root_domain *rd)
raw_spin_unlock_irqrestore(&rq->lock, flags); raw_spin_unlock_irqrestore(&rq->lock, flags);
if (old_rd) if (old_rd)
call_rcu_sched(&old_rd->rcu, free_rootdomain); call_rcu(&old_rd->rcu, free_rootdomain);
} }
void sched_get_rd(struct root_domain *rd) void sched_get_rd(struct root_domain *rd)
...@@ -455,7 +455,7 @@ void sched_put_rd(struct root_domain *rd) ...@@ -455,7 +455,7 @@ void sched_put_rd(struct root_domain *rd)
if (!atomic_dec_and_test(&rd->refcount)) if (!atomic_dec_and_test(&rd->refcount))
return; return;
call_rcu_sched(&rd->rcu, free_rootdomain); call_rcu(&rd->rcu, free_rootdomain);
} }
static int init_rootdomain(struct root_domain *rd) static int init_rootdomain(struct root_domain *rd)
......
...@@ -1632,7 +1632,7 @@ void update_process_times(int user_tick) ...@@ -1632,7 +1632,7 @@ void update_process_times(int user_tick)
/* Note: this timer irq context must be accounted for as well. */ /* Note: this timer irq context must be accounted for as well. */
account_process_tick(p, user_tick); account_process_tick(p, user_tick);
run_local_timers(); run_local_timers();
rcu_check_callbacks(user_tick); rcu_sched_clock_irq(user_tick);
#ifdef CONFIG_IRQ_WORK #ifdef CONFIG_IRQ_WORK
if (in_irq()) if (in_irq())
irq_work_tick(); irq_work_tick();
......
// SPDX-License-Identifier: GPL-2.0+
/* /*
* Common functions for in-kernel torture tests. * Common functions for in-kernel torture tests.
* *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you can access it online at
* http://www.gnu.org/licenses/gpl-2.0.html.
*
* Copyright (C) IBM Corporation, 2014 * Copyright (C) IBM Corporation, 2014
* *
* Author: Paul E. McKenney <paulmck@us.ibm.com> * Author: Paul E. McKenney <paulmck@linux.ibm.com>
* Based on kernel/rcu/torture.c. * Based on kernel/rcu/torture.c.
*/ */
...@@ -53,7 +40,7 @@ ...@@ -53,7 +40,7 @@
#include "rcu/rcu.h" #include "rcu/rcu.h"
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_AUTHOR("Paul E. McKenney <paulmck@us.ibm.com>"); MODULE_AUTHOR("Paul E. McKenney <paulmck@linux.ibm.com>");
static char *torture_type; static char *torture_type;
static int verbose; static int verbose;
...@@ -75,6 +62,7 @@ static DEFINE_MUTEX(fullstop_mutex); ...@@ -75,6 +62,7 @@ static DEFINE_MUTEX(fullstop_mutex);
static struct task_struct *onoff_task; static struct task_struct *onoff_task;
static long onoff_holdoff; static long onoff_holdoff;
static long onoff_interval; static long onoff_interval;
static torture_ofl_func *onoff_f;
static long n_offline_attempts; static long n_offline_attempts;
static long n_offline_successes; static long n_offline_successes;
static unsigned long sum_offline; static unsigned long sum_offline;
...@@ -118,6 +106,8 @@ bool torture_offline(int cpu, long *n_offl_attempts, long *n_offl_successes, ...@@ -118,6 +106,8 @@ bool torture_offline(int cpu, long *n_offl_attempts, long *n_offl_successes,
pr_alert("%s" TORTURE_FLAG pr_alert("%s" TORTURE_FLAG
"torture_onoff task: offlined %d\n", "torture_onoff task: offlined %d\n",
torture_type, cpu); torture_type, cpu);
if (onoff_f)
onoff_f();
(*n_offl_successes)++; (*n_offl_successes)++;
delta = jiffies - starttime; delta = jiffies - starttime;
*sum_offl += delta; *sum_offl += delta;
...@@ -243,11 +233,12 @@ torture_onoff(void *arg) ...@@ -243,11 +233,12 @@ torture_onoff(void *arg)
/* /*
* Initiate online-offline handling. * Initiate online-offline handling.
*/ */
int torture_onoff_init(long ooholdoff, long oointerval) int torture_onoff_init(long ooholdoff, long oointerval, torture_ofl_func *f)
{ {
#ifdef CONFIG_HOTPLUG_CPU #ifdef CONFIG_HOTPLUG_CPU
onoff_holdoff = ooholdoff; onoff_holdoff = ooholdoff;
onoff_interval = oointerval; onoff_interval = oointerval;
onoff_f = f;
if (onoff_interval <= 0) if (onoff_interval <= 0)
return 0; return 0;
return torture_create_kthread(torture_onoff, NULL, onoff_task); return torture_create_kthread(torture_onoff, NULL, onoff_task);
......
...@@ -3,7 +3,85 @@ ...@@ -3,7 +3,85 @@
* Copyright (C) 2017-2018 Willy Tarreau <w@1wt.eu> * Copyright (C) 2017-2018 Willy Tarreau <w@1wt.eu>
*/ */
/* some archs (at least aarch64) don't expose the regular syscalls anymore by /*
* This file is designed to be used as a libc alternative for minimal programs
* with very limited requirements. It consists of a small number of syscall and
* type definitions, and the minimal startup code needed to call main().
* All syscalls are declared as static functions so that they can be optimized
* away by the compiler when not used.
*
* Syscalls are split into 3 levels:
* - The lower level is the arch-specific syscall() definition, consisting in
* assembly code in compound expressions. These are called my_syscall0() to
* my_syscall6() depending on the number of arguments. The MIPS
* implementation is limited to 5 arguments. All input arguments are cast
* to a long stored in a register. These expressions always return the
* syscall's return value as a signed long value which is often either a
* pointer or the negated errno value.
*
* - The second level is mostly architecture-independent. It is made of
* static functions called sys_<name>() which rely on my_syscallN()
* depending on the syscall definition. These functions are responsible
* for exposing the appropriate types for the syscall arguments (int,
* pointers, etc) and for setting the appropriate return type (often int).
* A few of them are architecture-specific because the syscalls are not all
* mapped exactly the same among architectures. For example, some archs do
* not implement select() and need pselect6() instead, so the sys_select()
* function will have to abstract this.
*
* - The third level is the libc call definition. It exposes the lower raw
* sys_<name>() calls in a way that looks like what a libc usually does,
* takes care of specific input values, and of setting errno upon error.
* There can be minor variations compared to standard libc calls. For
* example the open() call always takes 3 args here.
*
* The errno variable is declared static and unused. This way it can be
* optimized away if not used. However this means that a program made of
* multiple C files may observe different errno values (one per C file). For
* the type of programs this project targets it usually is not a problem. The
* resulting program may even be reduced by defining the NOLIBC_IGNORE_ERRNO
* macro, in which case the errno value will never be assigned.
*
* Some stdint-like integer types are defined. These are valid on all currently
* supported architectures, because signs are enforced, ints are assumed to be
* 32 bits, longs the size of a pointer and long long 64 bits. If more
* architectures have to be supported, this may need to be adapted.
*
* Some macro definitions like the O_* values passed to open(), and some
* structures like the sys_stat struct depend on the architecture.
*
* The definitions start with the architecture-specific parts, which are picked
* based on what the compiler knows about the target architecture, and are
* completed with the generic code. Since it is the compiler which sets the
* target architecture, cross-compiling normally works out of the box without
* having to specify anything.
*
* Finally some very common libc-level functions are provided. It is the case
* for a few functions usually found in string.h, ctype.h, or stdlib.h. Nothing
* is currently provided regarding stdio emulation.
*
* The macro NOLIBC is always defined, so that it is possible for a program to
* check this macro to know if it is being built against and decide to disable
* some features or simply not to include some standard libc files.
*
* Ideally this file should be split in multiple files for easier long term
* maintenance, but provided as a single file as it is now, it's quite
* convenient to use. Maybe some variations involving a set of includes at the
* top could work.
*
* A simple static executable may be built this way :
* $ gcc -fno-asynchronous-unwind-tables -fno-ident -s -Os -nostdlib \
* -static -include nolibc.h -lgcc -o hello hello.c
*
* A very useful calling convention table may be found here :
* http://man7.org/linux/man-pages/man2/syscall.2.html
*
* This doc is quite convenient though not necessarily up to date :
* https://w3challs.com/syscalls/
*
*/
/* Some archs (at least aarch64) don't expose the regular syscalls anymore by
* default, either because they have an "_at" replacement, or because there are * default, either because they have an "_at" replacement, or because there are
* more modern alternatives. For now we'd rather still use them. * more modern alternatives. For now we'd rather still use them.
*/ */
...@@ -19,18 +97,6 @@ ...@@ -19,18 +97,6 @@
#define NOLIBC #define NOLIBC
/* Build a static executable this way :
* $ gcc -fno-asynchronous-unwind-tables -fno-ident -s -Os -nostdlib \
* -static -include nolibc.h -lgcc -o hello hello.c
*
* Useful calling convention table found here :
* http://man7.org/linux/man-pages/man2/syscall.2.html
*
* This doc is even better :
* https://w3challs.com/syscalls/
*/
/* this way it will be removed if unused */ /* this way it will be removed if unused */
static int errno; static int errno;
...@@ -1006,7 +1072,7 @@ struct sys_stat_struct { ...@@ -1006,7 +1072,7 @@ struct sys_stat_struct {
: "=r"(_num), "=r"(_arg4) \ : "=r"(_num), "=r"(_arg4) \
: "r"(_num) \ : "r"(_num) \
: "memory", "cc", "at", "v1", "hi", "lo", \ : "memory", "cc", "at", "v1", "hi", "lo", \
\ "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9" \
); \ ); \
_arg4 ? -_num : _num; \ _arg4 ? -_num : _num; \
}) })
...@@ -1025,7 +1091,7 @@ struct sys_stat_struct { ...@@ -1025,7 +1091,7 @@ struct sys_stat_struct {
: "0"(_num), \ : "0"(_num), \
"r"(_arg1) \ "r"(_arg1) \
: "memory", "cc", "at", "v1", "hi", "lo", \ : "memory", "cc", "at", "v1", "hi", "lo", \
\ "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9" \
); \ ); \
_arg4 ? -_num : _num; \ _arg4 ? -_num : _num; \
}) })
...@@ -1045,7 +1111,7 @@ struct sys_stat_struct { ...@@ -1045,7 +1111,7 @@ struct sys_stat_struct {
: "0"(_num), \ : "0"(_num), \
"r"(_arg1), "r"(_arg2) \ "r"(_arg1), "r"(_arg2) \
: "memory", "cc", "at", "v1", "hi", "lo", \ : "memory", "cc", "at", "v1", "hi", "lo", \
\ "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9" \
); \ ); \
_arg4 ? -_num : _num; \ _arg4 ? -_num : _num; \
}) })
...@@ -1066,7 +1132,7 @@ struct sys_stat_struct { ...@@ -1066,7 +1132,7 @@ struct sys_stat_struct {
: "0"(_num), \ : "0"(_num), \
"r"(_arg1), "r"(_arg2), "r"(_arg3) \ "r"(_arg1), "r"(_arg2), "r"(_arg3) \
: "memory", "cc", "at", "v1", "hi", "lo", \ : "memory", "cc", "at", "v1", "hi", "lo", \
\ "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9" \
); \ ); \
_arg4 ? -_num : _num; \ _arg4 ? -_num : _num; \
}) })
...@@ -1087,7 +1153,7 @@ struct sys_stat_struct { ...@@ -1087,7 +1153,7 @@ struct sys_stat_struct {
: "0"(_num), \ : "0"(_num), \
"r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4) \ "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4) \
: "memory", "cc", "at", "v1", "hi", "lo", \ : "memory", "cc", "at", "v1", "hi", "lo", \
\ "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9" \
); \ ); \
_arg4 ? -_num : _num; \ _arg4 ? -_num : _num; \
}) })
...@@ -1110,7 +1176,7 @@ struct sys_stat_struct { ...@@ -1110,7 +1176,7 @@ struct sys_stat_struct {
: "0"(_num), \ : "0"(_num), \
"r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5) \ "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5) \
: "memory", "cc", "at", "v1", "hi", "lo", \ : "memory", "cc", "at", "v1", "hi", "lo", \
\ "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9" \
); \ ); \
_arg4 ? -_num : _num; \ _arg4 ? -_num : _num; \
}) })
......
...@@ -156,6 +156,8 @@ lock.cat ...@@ -156,6 +156,8 @@ lock.cat
README README
This file. This file.
scripts Various scripts, see scripts/README.
=========== ===========
LIMITATIONS LIMITATIONS
......
...@@ -29,7 +29,8 @@ enum Barriers = 'wmb (*smp_wmb*) || ...@@ -29,7 +29,8 @@ enum Barriers = 'wmb (*smp_wmb*) ||
'sync-rcu (*synchronize_rcu*) || 'sync-rcu (*synchronize_rcu*) ||
'before-atomic (*smp_mb__before_atomic*) || 'before-atomic (*smp_mb__before_atomic*) ||
'after-atomic (*smp_mb__after_atomic*) || 'after-atomic (*smp_mb__after_atomic*) ||
'after-spinlock (*smp_mb__after_spinlock*) 'after-spinlock (*smp_mb__after_spinlock*) ||
'after-unlock-lock (*smp_mb__after_unlock_lock*)
instructions F[Barriers] instructions F[Barriers]
(* Compute matching pairs of nested Rcu-lock and Rcu-unlock *) (* Compute matching pairs of nested Rcu-lock and Rcu-unlock *)
......
...@@ -30,7 +30,9 @@ let wmb = [W] ; fencerel(Wmb) ; [W] ...@@ -30,7 +30,9 @@ let wmb = [W] ; fencerel(Wmb) ; [W]
let mb = ([M] ; fencerel(Mb) ; [M]) | let mb = ([M] ; fencerel(Mb) ; [M]) |
([M] ; fencerel(Before-atomic) ; [RMW] ; po? ; [M]) | ([M] ; fencerel(Before-atomic) ; [RMW] ; po? ; [M]) |
([M] ; po? ; [RMW] ; fencerel(After-atomic) ; [M]) | ([M] ; po? ; [RMW] ; fencerel(After-atomic) ; [M]) |
([M] ; po? ; [LKW] ; fencerel(After-spinlock) ; [M]) ([M] ; po? ; [LKW] ; fencerel(After-spinlock) ; [M]) |
([M] ; po ; [UL] ; (co | po) ; [LKW] ;
fencerel(After-unlock-lock) ; [M])
let gp = po ; [Sync-rcu] ; po? let gp = po ; [Sync-rcu] ; po?
let strong-fence = mb | gp let strong-fence = mb | gp
......
...@@ -23,6 +23,7 @@ smp_wmb() { __fence{wmb}; } ...@@ -23,6 +23,7 @@ smp_wmb() { __fence{wmb}; }
smp_mb__before_atomic() { __fence{before-atomic}; } smp_mb__before_atomic() { __fence{before-atomic}; }
smp_mb__after_atomic() { __fence{after-atomic}; } smp_mb__after_atomic() { __fence{after-atomic}; }
smp_mb__after_spinlock() { __fence{after-spinlock}; } smp_mb__after_spinlock() { __fence{after-spinlock}; }
smp_mb__after_unlock_lock() { __fence{after-unlock-lock}; }
// Exchange // Exchange
xchg(X,V) __xchg{mb}(X,V) xchg(X,V) __xchg{mb}(X,V)
......
============
LKMM SCRIPTS
============
These scripts are run from the tools/memory-model directory.
checkalllitmus.sh
Run all litmus tests in the litmus-tests directory, checking
the results against the expected results recorded in the
"Result:" comment lines.
checkghlitmus.sh
Run all litmus tests in the https://github.com/paulmckrcu/litmus
archive that are C-language and that have "Result:" comment lines
documenting expected results, comparing the actual results to
those expected.
checklitmushist.sh
Run all litmus tests having .litmus.out files from previous
initlitmushist.sh or newlitmushist.sh runs, comparing the
herd output to that of the original runs.
checklitmus.sh
Check a single litmus test against its "Result:" expected result.
cmplitmushist.sh
Compare output from two different runs of the same litmus tests,
with the absolute pathnames of the tests to run provided one
name per line on standard input. Not normally run manually,
provided instead for use by other scripts.
initlitmushist.sh
Run all litmus tests having no more than the specified number
of processes given a specified timeout, recording the results
in .litmus.out files.
judgelitmus.sh
Given a .litmus file and its .litmus.out herd output, check the
.litmus.out file against the .litmus file's "Result:" comment to
judge whether the test ran correctly. Not normally run manually,
provided instead for use by other scripts.
newlitmushist.sh
For all new or updated litmus tests having no more than the
specified number of processes given a specified timeout, run
and record the results in .litmus.out files.
parseargs.sh
Parse command-line arguments. Not normally run manually,
provided instead for use by other scripts.
runlitmushist.sh
Run the litmus tests whose absolute pathnames are provided one
name per line on standard input. Not normally run manually,
provided instead for use by other scripts.
README
This file
#!/bin/sh #!/bin/sh
# SPDX-License-Identifier: GPL-2.0+
# #
# Run herd tests on all .litmus files in the specified directory (which # Run herd tests on all .litmus files in the litmus-tests directory
# defaults to litmus-tests) and check each file's result against a "Result:" # and check each file's result against a "Result:" comment within that
# comment within that litmus test. If the verification result does not # litmus test. If the verification result does not match that specified
# match that specified in the litmus test, this script prints an error # in the litmus test, this script prints an error message prefixed with
# message prefixed with "^^^". It also outputs verification results to # "^^^". It also outputs verification results to a file whose name is
# a file whose name is that of the specified litmus test, but with ".out" # that of the specified litmus test, but with ".out" appended.
# appended.
# #
# Usage: # Usage:
# checkalllitmus.sh [ directory ] # checkalllitmus.sh
# #
# The LINUX_HERD_OPTIONS environment variable may be used to specify # Run this in the directory containing the memory model.
# arguments to herd, whose default is defined by the checklitmus.sh script.
# Thus, one would normally run this in the directory containing the memory
# model, specifying the pathname of the litmus test to check.
# #
# This script makes no attempt to run the litmus tests concurrently. # This script makes no attempt to run the litmus tests concurrently.
# #
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, you can access it online at
# http://www.gnu.org/licenses/gpl-2.0.html.
#
# Copyright IBM Corporation, 2018 # Copyright IBM Corporation, 2018
# #
# Author: Paul E. McKenney <paulmck@linux.vnet.ibm.com> # Author: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
litmusdir=${1-litmus-tests} . scripts/parseargs.sh
litmusdir=litmus-tests
if test -d "$litmusdir" -a -r "$litmusdir" -a -x "$litmusdir" if test -d "$litmusdir" -a -r "$litmusdir" -a -x "$litmusdir"
then then
: :
...@@ -45,6 +30,14 @@ else ...@@ -45,6 +30,14 @@ else
exit 255 exit 255
fi fi
# Create any new directories that have appeared in the github litmus
# repo since the last run.
if test "$LKMM_DESTDIR" != "."
then
find $litmusdir -type d -print |
( cd "$LKMM_DESTDIR"; sed -e 's/^/mkdir -p /' | sh )
fi
# Find the checklitmus script. If it is not where we expect it, then # Find the checklitmus script. If it is not where we expect it, then
# assume that the caller has the PATH environment variable set # assume that the caller has the PATH environment variable set
# appropriately. # appropriately.
...@@ -57,7 +50,7 @@ fi ...@@ -57,7 +50,7 @@ fi
# Run the script on all the litmus tests in the specified directory # Run the script on all the litmus tests in the specified directory
ret=0 ret=0
for i in litmus-tests/*.litmus for i in $litmusdir/*.litmus
do do
if ! $clscript $i if ! $clscript $i
then then
...@@ -66,8 +59,8 @@ do ...@@ -66,8 +59,8 @@ do
done done
if test "$ret" -ne 0 if test "$ret" -ne 0
then then
echo " ^^^ VERIFICATION MISMATCHES" echo " ^^^ VERIFICATION MISMATCHES" 1>&2
else else
echo All litmus tests verified as was expected. echo All litmus tests verified as was expected. 1>&2
fi fi
exit $ret exit $ret
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0+
#
# Runs the C-language litmus tests having a maximum number of processes
# to run, defaults to 6.
#
# sh checkghlitmus.sh
#
# Run from the Linux kernel tools/memory-model directory. See the
# parseargs.sh scripts for arguments.
. scripts/parseargs.sh
T=/tmp/checkghlitmus.sh.$$
trap 'rm -rf $T' 0
mkdir $T
# Clone the repository if it is not already present.
if test -d litmus
then
:
else
git clone https://github.com/paulmckrcu/litmus
( cd litmus; git checkout origin/master )
fi
# Create any new directories that have appeared in the github litmus
# repo since the last run.
if test "$LKMM_DESTDIR" != "."
then
find litmus -type d -print |
( cd "$LKMM_DESTDIR"; sed -e 's/^/mkdir -p /' | sh )
fi
# Create a list of the C-language litmus tests previously run.
( cd $LKMM_DESTDIR; find litmus -name '*.litmus.out' -print ) |
sed -e 's/\.out$//' |
xargs -r egrep -l '^ \* Result: (Never|Sometimes|Always|DEADLOCK)' |
xargs -r grep -L "^P${LKMM_PROCS}"> $T/list-C-already
# Create a list of C-language litmus tests with "Result:" commands and
# no more than the specified number of processes.
find litmus -name '*.litmus' -exec grep -l -m 1 "^C " {} \; > $T/list-C
xargs < $T/list-C -r egrep -l '^ \* Result: (Never|Sometimes|Always|DEADLOCK)' > $T/list-C-result
xargs < $T/list-C-result -r grep -L "^P${LKMM_PROCS}" > $T/list-C-result-short
# Form list of tests without corresponding .litmus.out files
sort $T/list-C-already $T/list-C-result-short | uniq -u > $T/list-C-needed
# Run any needed tests.
if scripts/runlitmushist.sh < $T/list-C-needed > $T/run.stdout 2> $T/run.stderr
then
errs=
else
errs=1
fi
sed < $T/list-C-result-short -e 's,^,scripts/judgelitmus.sh ,' |
sh > $T/judge.stdout 2> $T/judge.stderr
if test -n "$errs"
then
cat $T/run.stderr 1>&2
fi
grep '!!!' $T/judge.stdout
#!/bin/sh #!/bin/sh
# SPDX-License-Identifier: GPL-2.0+
# #
# Run a herd test and check the result against a "Result:" comment within # Run a herd test and invokes judgelitmus.sh to check the result against
# the litmus test. If the verification result does not match that specified # a "Result:" comment within the litmus test. It also outputs verification
# in the litmus test, this script prints an error message prefixed with
# "^^^" and exits with a non-zero status. It also outputs verification
# results to a file whose name is that of the specified litmus test, but # results to a file whose name is that of the specified litmus test, but
# with ".out" appended. # with ".out" appended.
# #
# Usage: # Usage:
# checklitmus.sh file.litmus # checklitmus.sh file.litmus
# #
# The LINUX_HERD_OPTIONS environment variable may be used to specify # Run this in the directory containing the memory model, specifying the
# arguments to herd, which default to "-conf linux-kernel.cfg". Thus, # pathname of the litmus test to check. The caller is expected to have
# one would normally run this in the directory containing the memory model, # properly set up the LKMM environment variables.
# specifying the pathname of the litmus test to check.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, you can access it online at
# http://www.gnu.org/licenses/gpl-2.0.html.
# #
# Copyright IBM Corporation, 2018 # Copyright IBM Corporation, 2018
# #
# Author: Paul E. McKenney <paulmck@linux.vnet.ibm.com> # Author: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
litmus=$1 litmus=$1
herdoptions=${LINUX_HERD_OPTIONS--conf linux-kernel.cfg} herdoptions=${LKMM_HERD_OPTIONS--conf linux-kernel.cfg}
if test -f "$litmus" -a -r "$litmus" if test -f "$litmus" -a -r "$litmus"
then then
...@@ -43,44 +27,8 @@ else ...@@ -43,44 +27,8 @@ else
echo ' --- ' error: \"$litmus\" is not a readable file echo ' --- ' error: \"$litmus\" is not a readable file
exit 255 exit 255
fi fi
if grep -q '^ \* Result: ' $litmus
then
outcome=`grep -m 1 '^ \* Result: ' $litmus | awk '{ print $3 }'`
else
outcome=specified
fi
echo Herd options: $herdoptions > $litmus.out echo Herd options: $herdoptions > $LKMM_DESTDIR/$litmus.out
/usr/bin/time herd7 -o ~/tmp $herdoptions $litmus >> $litmus.out 2>&1 /usr/bin/time $LKMM_TIMEOUT_CMD herd7 $herdoptions $litmus >> $LKMM_DESTDIR/$litmus.out 2>&1
grep "Herd options:" $litmus.out
grep '^Observation' $litmus.out scripts/judgelitmus.sh $litmus
if grep -q '^Observation' $litmus.out
then
:
else
cat $litmus.out
echo ' ^^^ Verification error'
echo ' ^^^ Verification error' >> $litmus.out 2>&1
exit 255
fi
if test "$outcome" = DEADLOCK
then
echo grep 3 and 4
if grep '^Observation' $litmus.out | grep -q 'Never 0 0$'
then
ret=0
else
echo " ^^^ Unexpected non-$outcome verification"
echo " ^^^ Unexpected non-$outcome verification" >> $litmus.out 2>&1
ret=1
fi
elif grep '^Observation' $litmus.out | grep -q $outcome || test "$outcome" = Maybe
then
ret=0
else
echo " ^^^ Unexpected non-$outcome verification"
echo " ^^^ Unexpected non-$outcome verification" >> $litmus.out 2>&1
ret=1
fi
tail -2 $litmus.out | head -1
exit $ret
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0+
#
# Reruns the C-language litmus tests previously run that match the
# specified criteria, and compares the result to that of the previous
# runs from initlitmushist.sh and/or newlitmushist.sh.
#
# sh checklitmushist.sh
#
# Run from the Linux kernel tools/memory-model directory.
# See scripts/parseargs.sh for list of arguments.
#
# Copyright IBM Corporation, 2018
#
# Author: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
. scripts/parseargs.sh
T=/tmp/checklitmushist.sh.$$
trap 'rm -rf $T' 0
mkdir $T
if test -d litmus
then
:
else
echo Run scripts/initlitmushist.sh first, need litmus repo.
exit 1
fi
# Create the results directory and populate it with subdirectories.
# The initial output is created here to avoid clobbering the output
# generated earlier.
mkdir $T/results
find litmus -type d -print | ( cd $T/results; sed -e 's/^/mkdir -p /' | sh )
# Create the list of litmus tests already run, then remove those that
# are excluded by this run's --procs argument.
( cd $LKMM_DESTDIR; find litmus -name '*.litmus.out' -print ) |
sed -e 's/\.out$//' |
xargs -r grep -L "^P${LKMM_PROCS}"> $T/list-C-already
xargs < $T/list-C-already -r grep -L "^P${LKMM_PROCS}" > $T/list-C-short
# Redirect output, run tests, then restore destination directory.
destdir="$LKMM_DESTDIR"
LKMM_DESTDIR=$T/results; export LKMM_DESTDIR
scripts/runlitmushist.sh < $T/list-C-short > $T/runlitmushist.sh.out 2>&1
LKMM_DESTDIR="$destdir"; export LKMM_DESTDIR
# Move the newly generated .litmus.out files to .litmus.out.new files
# in the destination directory.
cdir=`pwd`
ddir=`awk -v c="$cdir" -v d="$LKMM_DESTDIR" \
'END { if (d ~ /^\//) print d; else print c "/" d; }' < /dev/null`
( cd $T/results; find litmus -type f -name '*.litmus.out' -print |
sed -e 's,^.*$,cp & '"$ddir"'/&.new,' | sh )
sed < $T/list-C-short -e 's,^,'"$LKMM_DESTDIR/"',' |
sh scripts/cmplitmushist.sh
exit $?
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0+
#
# Compares .out and .out.new files for each name on standard input,
# one full pathname per line. Outputs comparison results followed by
# a summary.
#
# sh cmplitmushist.sh
T=/tmp/cmplitmushist.sh.$$
trap 'rm -rf $T' 0
mkdir $T
# comparetest oldpath newpath
perfect=0
obsline=0
noobsline=0
obsresult=0
badcompare=0
comparetest () {
grep -v 'maxresident)k\|minor)pagefaults\|^Time' $1 > $T/oldout
grep -v 'maxresident)k\|minor)pagefaults\|^Time' $2 > $T/newout
if cmp -s $T/oldout $T/newout && grep -q '^Observation' $1
then
echo Exact output match: $2
perfect=`expr "$perfect" + 1`
return 0
fi
grep '^Observation' $1 > $T/oldout
grep '^Observation' $2 > $T/newout
if test -s $T/oldout -o -s $T/newout
then
if cmp -s $T/oldout $T/newout
then
echo Matching Observation result and counts: $2
obsline=`expr "$obsline" + 1`
return 0
fi
else
echo Missing Observation line "(e.g., herd7 timeout)": $2
noobsline=`expr "$noobsline" + 1`
return 0
fi
grep '^Observation' $1 | awk '{ print $3 }' > $T/oldout
grep '^Observation' $2 | awk '{ print $3 }' > $T/newout
if cmp -s $T/oldout $T/newout
then
echo Matching Observation Always/Sometimes/Never result: $2
obsresult=`expr "$obsresult" + 1`
return 0
fi
echo ' !!!' Result changed: $2
badcompare=`expr "$badcompare" + 1`
return 1
}
sed -e 's/^.*$/comparetest &.out &.out.new/' > $T/cmpscript
. $T/cmpscript > $T/cmpscript.out
cat $T/cmpscript.out
echo ' ---' Summary: 1>&2
grep '!!!' $T/cmpscript.out 1>&2
if test "$perfect" -ne 0
then
echo Exact output matches: $perfect 1>&2
fi
if test "$obsline" -ne 0
then
echo Matching Observation result and counts: $obsline 1>&2
fi
if test "$noobsline" -ne 0
then
echo Missing Observation line "(e.g., herd7 timeout)": $noobsline 1>&2
fi
if test "$obsresult" -ne 0
then
echo Matching Observation Always/Sometimes/Never result: $obsresult 1>&2
fi
if test "$badcompare" -ne 0
then
echo "!!!" Result changed: $badcompare 1>&2
exit 1
fi
exit 0
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0+
#
# Runs the C-language litmus tests matching the specified criteria.
# Generates the output for each .litmus file into a corresponding
# .litmus.out file, and does not judge the result.
#
# sh initlitmushist.sh
#
# Run from the Linux kernel tools/memory-model directory.
# See scripts/parseargs.sh for list of arguments.
#
# This script can consume significant wallclock time and CPU, especially as
# the value of --procs rises. On a four-core (eight hardware threads)
# 2.5GHz x86 with a one-minute per-run timeout:
#
# --procs wallclock CPU timeouts tests
# 1 0m11.241s 0m1.086s 0 19
# 2 1m12.598s 2m8.459s 2 393
# 3 1m30.007s 6m2.479s 4 2291
# 4 3m26.042s 18m5.139s 9 3217
# 5 4m26.661s 23m54.128s 13 3784
# 6 4m41.900s 26m4.721s 13 4352
# 7 5m51.463s 35m50.868s 13 4626
# 8 10m5.235s 68m43.672s 34 5117
# 9 15m57.80s 105m58.101s 69 5156
# 10 16m14.13s 103m35.009s 69 5165
# 20 27m48.55s 198m3.286s 156 5269
#
# Increasing the timeout on the 20-process run to five minutes increases
# the runtime to about 90 minutes with the CPU time rising to about
# 10 hours. On the other hand, it decreases the number of timeouts to 101.
#
# Note that there are historical tests for which herd7 will fail
# completely, for example, litmus/manual/atomic/C-unlock-wait-00.litmus
# contains a call to spin_unlock_wait(), which no longer exists in either
# the kernel or LKMM.
. scripts/parseargs.sh
T=/tmp/initlitmushist.sh.$$
trap 'rm -rf $T' 0
mkdir $T
if test -d litmus
then
:
else
git clone https://github.com/paulmckrcu/litmus
( cd litmus; git checkout origin/master )
fi
# Create any new directories that have appeared in the github litmus
# repo since the last run.
if test "$LKMM_DESTDIR" != "."
then
find litmus -type d -print |
( cd "$LKMM_DESTDIR"; sed -e 's/^/mkdir -p /' | sh )
fi
# Create a list of the C-language litmus tests with no more than the
# specified number of processes (per the --procs argument).
find litmus -name '*.litmus' -exec grep -l -m 1 "^C " {} \; > $T/list-C
xargs < $T/list-C -r grep -L "^P${LKMM_PROCS}" > $T/list-C-short
scripts/runlitmushist.sh < $T/list-C-short
exit 0
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0+
#
# Given a .litmus test and the corresponding .litmus.out file, check
# the .litmus.out file against the "Result:" comment to judge whether
# the test ran correctly.
#
# Usage:
# judgelitmus.sh file.litmus
#
# Run this in the directory containing the memory model, specifying the
# pathname of the litmus test to check.
#
# Copyright IBM Corporation, 2018
#
# Author: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
litmus=$1
if test -f "$litmus" -a -r "$litmus"
then
:
else
echo ' --- ' error: \"$litmus\" is not a readable file
exit 255
fi
if test -f "$LKMM_DESTDIR/$litmus".out -a -r "$LKMM_DESTDIR/$litmus".out
then
:
else
echo ' --- ' error: \"$LKMM_DESTDIR/$litmus\".out is not a readable file
exit 255
fi
if grep -q '^ \* Result: ' $litmus
then
outcome=`grep -m 1 '^ \* Result: ' $litmus | awk '{ print $3 }'`
else
outcome=specified
fi
grep '^Observation' $LKMM_DESTDIR/$litmus.out
if grep -q '^Observation' $LKMM_DESTDIR/$litmus.out
then
:
else
echo ' !!! Verification error' $litmus
if ! grep -q '!!!' $LKMM_DESTDIR/$litmus.out
then
echo ' !!! Verification error' >> $LKMM_DESTDIR/$litmus.out 2>&1
fi
exit 255
fi
if test "$outcome" = DEADLOCK
then
if grep '^Observation' $LKMM_DESTDIR/$litmus.out | grep -q 'Never 0 0$'
then
ret=0
else
echo " !!! Unexpected non-$outcome verification" $litmus
if ! grep -q '!!!' $LKMM_DESTDIR/$litmus.out
then
echo " !!! Unexpected non-$outcome verification" >> $LKMM_DESTDIR/$litmus.out 2>&1
fi
ret=1
fi
elif grep '^Observation' $LKMM_DESTDIR/$litmus.out | grep -q $outcome || test "$outcome" = Maybe
then
ret=0
else
echo " !!! Unexpected non-$outcome verification" $litmus
if ! grep -q '!!!' $LKMM_DESTDIR/$litmus.out
then
echo " !!! Unexpected non-$outcome verification" >> $LKMM_DESTDIR/$litmus.out 2>&1
fi
ret=1
fi
tail -2 $LKMM_DESTDIR/$litmus.out | head -1
exit $ret
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0+
#
# Runs the C-language litmus tests matching the specified criteria
# that do not already have a corresponding .litmus.out file, and does
# not judge the result.
#
# sh newlitmushist.sh
#
# Run from the Linux kernel tools/memory-model directory.
# See scripts/parseargs.sh for list of arguments.
#
# Copyright IBM Corporation, 2018
#
# Author: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
. scripts/parseargs.sh
T=/tmp/newlitmushist.sh.$$
trap 'rm -rf $T' 0
mkdir $T
if test -d litmus
then
:
else
echo Run scripts/initlitmushist.sh first, need litmus repo.
exit 1
fi
# Create any new directories that have appeared in the github litmus
# repo since the last run.
if test "$LKMM_DESTDIR" != "."
then
find litmus -type d -print |
( cd "$LKMM_DESTDIR"; sed -e 's/^/mkdir -p /' | sh )
fi
# Create a list of the C-language litmus tests previously run.
( cd $LKMM_DESTDIR; find litmus -name '*.litmus.out' -print ) |
sed -e 's/\.out$//' |
xargs -r grep -L "^P${LKMM_PROCS}"> $T/list-C-already
# Form full list of litmus tests with no more than the specified
# number of processes (per the --procs argument).
find litmus -name '*.litmus' -exec grep -l -m 1 "^C " {} \; > $T/list-C-all
xargs < $T/list-C-all -r grep -L "^P${LKMM_PROCS}" > $T/list-C-short
# Form list of new tests. Note: This does not handle litmus-test deletion!
sort $T/list-C-already $T/list-C-short | uniq -u > $T/list-C-new
# Form list of litmus tests that have changed since the last run.
sed < $T/list-C-short -e 's,^.*$,if test & -nt '"$LKMM_DESTDIR"'/&.out; then echo &; fi,' > $T/list-C-script
sh $T/list-C-script > $T/list-C-newer
# Merge the list of new and of updated litmus tests: These must be (re)run.
sort -u $T/list-C-new $T/list-C-newer > $T/list-C-needed
scripts/runlitmushist.sh < $T/list-C-needed
exit 0
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0+
#
# the corresponding .litmus.out file, and does not judge the result.
#
# . scripts/parseargs.sh
#
# Include into other Linux kernel tools/memory-model scripts.
#
# Copyright IBM Corporation, 2018
#
# Author: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
T=/tmp/parseargs.sh.$$
mkdir $T
# Initialize one parameter: initparam name default
initparam () {
echo if test -z '"$'$1'"' > $T/s
echo then >> $T/s
echo $1='"'$2'"' >> $T/s
echo export $1 >> $T/s
echo fi >> $T/s
echo $1_DEF='$'$1 >> $T/s
. $T/s
}
initparam LKMM_DESTDIR "."
initparam LKMM_HERD_OPTIONS "-conf linux-kernel.cfg"
initparam LKMM_JOBS `getconf _NPROCESSORS_ONLN`
initparam LKMM_PROCS "3"
initparam LKMM_TIMEOUT "1m"
scriptname=$0
usagehelp () {
echo "Usage $scriptname [ arguments ]"
echo " --destdir path (place for .litmus.out, default by .litmus)"
echo " --herdopts -conf linux-kernel.cfg ..."
echo " --jobs N (number of jobs, default one per CPU)"
echo " --procs N (litmus tests with at most this many processes)"
echo " --timeout N (herd7 timeout (e.g., 10s, 1m, 2hr, 1d, '')"
echo "Defaults: --destdir '$LKMM_DESTDIR_DEF' --herdopts '$LKMM_HERD_OPTIONS_DEF' --jobs '$LKMM_JOBS_DEF' --procs '$LKMM_PROCS_DEF' --timeout '$LKMM_TIMEOUT_DEF'"
exit 1
}
usage () {
usagehelp 1>&2
}
# checkarg --argname argtype $# arg mustmatch cannotmatch
checkarg () {
if test $3 -le 1
then
echo $1 needs argument $2 matching \"$5\"
usage
fi
if echo "$4" | grep -q -e "$5"
then
:
else
echo $1 $2 \"$4\" must match \"$5\"
usage
fi
if echo "$4" | grep -q -e "$6"
then
echo $1 $2 \"$4\" must not match \"$6\"
usage
fi
}
while test $# -gt 0
do
case "$1" in
--destdir)
checkarg --destdir "(path to directory)" "$#" "$2" '.\+' '^--'
LKMM_DESTDIR="$2"
mkdir $LKMM_DESTDIR > /dev/null 2>&1
if ! test -e "$LKMM_DESTDIR"
then
echo "Cannot create directory --destdir '$LKMM_DESTDIR'"
usage
fi
if test -d "$LKMM_DESTDIR" -a -w "$LKMM_DESTDIR" -a -x "$LKMM_DESTDIR"
then
:
else
echo "Directory --destdir '$LKMM_DESTDIR' insufficient permissions to create files"
usage
fi
shift
;;
--herdopts|--herdopt)
checkarg --destdir "(herd options)" "$#" "$2" '.*' '^--'
LKMM_HERD_OPTIONS="$2"
shift
;;
-j[1-9]*)
njobs="`echo $1 | sed -e 's/^-j//'`"
trailchars="`echo $njobs | sed -e 's/[0-9]\+\(.*\)$/\1/'`"
if test -n "$trailchars"
then
echo $1 trailing characters "'$trailchars'"
usagehelp
fi
LKMM_JOBS="`echo $njobs | sed -e 's/^\([0-9]\+\).*$/\1/'`"
;;
--jobs|--job|-j)
checkarg --jobs "(number)" "$#" "$2" '^[1-9][0-9]\+$' '^--'
LKMM_JOBS="$2"
shift
;;
--procs|--proc)
checkarg --procs "(number)" "$#" "$2" '^[0-9]\+$' '^--'
LKMM_PROCS="$2"
shift
;;
--timeout)
checkarg --timeout "(timeout spec)" "$#" "$2" '^\([0-9]\+[smhd]\?\|\)$' '^--'
LKMM_TIMEOUT="$2"
shift
;;
*)
echo Unknown argument $1
usage
;;
esac
shift
done
if test -z "$LKMM_TIMEOUT"
then
LKMM_TIMEOUT_CMD=""; export LKMM_TIMEOUT_CMD
else
LKMM_TIMEOUT_CMD="timeout $LKMM_TIMEOUT"; export LKMM_TIMEOUT_CMD
fi
rm -rf $T
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0+
#
# Runs the C-language litmus tests specified on standard input, using up
# to the specified number of CPUs (defaulting to all of them) and placing
# the results in the specified directory (defaulting to the same place
# the litmus test came from).
#
# sh runlitmushist.sh
#
# Run from the Linux kernel tools/memory-model directory.
# This script uses environment variables produced by parseargs.sh.
#
# Copyright IBM Corporation, 2018
#
# Author: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
T=/tmp/runlitmushist.sh.$$
trap 'rm -rf $T' 0
mkdir $T
if test -d litmus
then
:
else
echo Directory \"litmus\" missing, aborting run.
exit 1
fi
# Prefixes for per-CPU scripts
for ((i=0;i<$LKMM_JOBS;i++))
do
echo dir="$LKMM_DESTDIR" > $T/$i.sh
echo T=$T >> $T/$i.sh
echo herdoptions=\"$LKMM_HERD_OPTIONS\" >> $T/$i.sh
cat << '___EOF___' >> $T/$i.sh
runtest () {
echo ' ... ' /usr/bin/time $LKMM_TIMEOUT_CMD herd7 $herdoptions $1 '>' $dir/$1.out '2>&1'
if /usr/bin/time $LKMM_TIMEOUT_CMD herd7 $herdoptions $1 > $dir/$1.out 2>&1
then
if ! grep -q '^Observation ' $dir/$1.out
then
echo ' !!! Herd failed, no Observation:' $1
fi
else
exitcode=$?
if test "$exitcode" -eq 124
then
exitmsg="timed out"
else
exitmsg="failed, exit code $exitcode"
fi
echo ' !!! Herd' ${exitmsg}: $1
fi
}
___EOF___
done
awk -v q="'" -v b='\\' '
{
print "echo `grep " q "^P[0-9]" b "+(" q " " $0 " | tail -1 | sed -e " q "s/^P" b "([0-9]" b "+" b ")(.*$/" b "1/" q "` " $0
}' | bash |
sort -k1n |
awk -v ncpu=$LKMM_JOBS -v t=$T '
{
print "runtest " $2 >> t "/" NR % ncpu ".sh";
}
END {
for (i = 0; i < ncpu; i++) {
print "sh " t "/" i ".sh > " t "/" i ".sh.out 2>&1 &";
close(t "/" i ".sh");
}
print "wait";
}' | sh
cat $T/*.sh.out
if grep -q '!!!' $T/*.sh.out
then
echo ' ---' Summary: 1>&2
grep '!!!' $T/*.sh.out 1>&2
nfail="`grep '!!!' $T/*.sh.out | wc -l`"
echo 'Number of failed herd runs (e.g., timeout): ' $nfail 1>&2
exit 1
else
echo All runs completed successfully. 1>&2
exit 0
fi
...@@ -40,17 +40,24 @@ mkdir $T ...@@ -40,17 +40,24 @@ mkdir $T
cat > $T/init << '__EOF___' cat > $T/init << '__EOF___'
#!/bin/sh #!/bin/sh
# Run in userspace a few milliseconds every second. This helps to # Run in userspace a few milliseconds every second. This helps to
# exercise the NO_HZ_FULL portions of RCU. # exercise the NO_HZ_FULL portions of RCU. The 192 instances of "a" was
# empirically shown to give a nice multi-millisecond burst of user-mode
# execution on a 2GHz CPU, as desired. Modern CPUs will vary from a
# couple of milliseconds up to perhaps 100 milliseconds, which is an
# acceptable range.
#
# Why not calibrate an exact delay? Because within this initrd, we
# are restricted to Bourne-shell builtins, which as far as I know do not
# provide any means of obtaining a fine-grained timestamp.
a4="a a a a"
a16="$a4 $a4 $a4 $a4"
a64="$a16 $a16 $a16 $a16"
a192="$a64 $a64 $a64"
while : while :
do do
q= q=
for i in \ for i in $a192
a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a \
a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a \
a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a \
a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a \
a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a \
a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a
do do
q="$q $i" q="$q $i"
done done
...@@ -124,8 +131,8 @@ if echo -e "#if __x86_64__||__i386__||__i486__||__i586__||__i686__" \ ...@@ -124,8 +131,8 @@ if echo -e "#if __x86_64__||__i386__||__i486__||__i586__||__i686__" \
| grep -q '^yes'; then | grep -q '^yes'; then
# architecture supported by nolibc # architecture supported by nolibc
${CROSS_COMPILE}gcc -fno-asynchronous-unwind-tables -fno-ident \ ${CROSS_COMPILE}gcc -fno-asynchronous-unwind-tables -fno-ident \
-nostdlib -include ../bin/nolibc.h -lgcc -s -static -Os \ -nostdlib -include ../../../../include/nolibc/nolibc.h \
-o init init.c -lgcc -s -static -Os -o init init.c
else else
${CROSS_COMPILE}gcc -s -static -Os -o init init.c ${CROSS_COMPILE}gcc -s -static -Os -o init init.c
fi fi
......
...@@ -4084,7 +4084,7 @@ static int kvm_suspend(void) ...@@ -4084,7 +4084,7 @@ static int kvm_suspend(void)
static void kvm_resume(void) static void kvm_resume(void)
{ {
if (kvm_usage_count) { if (kvm_usage_count) {
WARN_ON(raw_spin_is_locked(&kvm_count_lock)); lockdep_assert_held(&kvm_count_lock);
hardware_enable_nolock(NULL); hardware_enable_nolock(NULL);
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment