Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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
...

+1396 -1269
+11 -7
Documentation/RCU/Design/Expedited-Grace-Periods/ExpSchedFlow.svg
··· 328 328 inkscape:window-height="1148" 329 329 id="namedview90" 330 330 showgrid="true" 331 - inkscape:zoom="0.80021373" 332 - inkscape:cx="462.49289" 333 - inkscape:cy="473.6718" 331 + inkscape:zoom="0.69092787" 332 + inkscape:cx="476.34085" 333 + inkscape:cy="712.80957" 334 334 inkscape:window-x="770" 335 335 inkscape:window-y="24" 336 336 inkscape:window-maximized="0" 337 - inkscape:current-layer="g4114-9-3-9" 337 + inkscape:current-layer="g4" 338 338 inkscape:snap-grids="false" 339 339 fit-margin-top="5" 340 340 fit-margin-right="5" ··· 813 813 <text 814 814 sodipodi:linespacing="125%" 815 815 id="text4110-5-7-6-2-4-0" 816 - y="841.88086" 816 + y="670.74316" 817 817 x="1460.1007" 818 818 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" 819 819 xml:space="preserve"><tspan 820 - y="841.88086" 820 + y="670.74316" 821 821 x="1460.1007" 822 822 sodipodi:role="line" 823 - id="tspan4925-1-2-4-5">reched_cpu()</tspan></text> 823 + id="tspan4925-1-2-4-5">Request</tspan><tspan 824 + y="1004.7976" 825 + x="1460.1007" 826 + sodipodi:role="line" 827 + id="tspan3100">context switch</tspan></text> 824 828 </g> 825 829 </g> 826 830 </svg>
+13 -13
Documentation/RCU/Design/Expedited-Grace-Periods/Expedited-Grace-Periods.html
··· 72 72 in quiescent states. 73 73 Otherwise, the expedited grace period will use 74 74 <tt>smp_call_function_single()</tt> to send the CPU an IPI, which 75 - is handled by <tt>sync_rcu_exp_handler()</tt>. 75 + is handled by <tt>rcu_exp_handler()</tt>. 76 76 77 77 <p> 78 - However, because this is preemptible RCU, <tt>sync_rcu_exp_handler()</tt> 78 + However, because this is preemptible RCU, <tt>rcu_exp_handler()</tt> 79 79 can check to see if the CPU is currently running in an RCU read-side 80 80 critical section. 81 81 If not, the handler can immediately report a quiescent state. ··· 145 145 <p><img src="ExpSchedFlow.svg" alt="ExpSchedFlow.svg" width="55%"> 146 146 147 147 <p> 148 - As with RCU-preempt's <tt>synchronize_rcu_expedited()</tt>, 148 + As with RCU-preempt, RCU-sched's 149 149 <tt>synchronize_sched_expedited()</tt> ignores offline and 150 150 idle CPUs, again because they are in remotely detectable 151 151 quiescent states. 152 - However, the <tt>synchronize_rcu_expedited()</tt> handler 153 - is <tt>sync_sched_exp_handler()</tt>, and because the 152 + However, because the 154 153 <tt>rcu_read_lock_sched()</tt> and <tt>rcu_read_unlock_sched()</tt> 155 154 leave no trace of their invocation, in general it is not possible to tell 156 155 whether or not the current CPU is in an RCU read-side critical section. 157 - The best that <tt>sync_sched_exp_handler()</tt> can do is to check 156 + The best that RCU-sched's <tt>rcu_exp_handler()</tt> can do is to check 158 157 for idle, on the off-chance that the CPU went idle while the IPI 159 158 was in flight. 160 - If the CPU is idle, then <tt>sync_sched_exp_handler()</tt> reports 159 + If the CPU is idle, then <tt>rcu_exp_handler()</tt> reports 161 160 the quiescent state. 162 161 163 162 <p> Otherwise, the handler forces a future context switch by setting the ··· 297 298 idle CPUs in the mask passed to <tt>rcu_report_exp_cpu_mult()</tt>. 298 299 299 300 <p> 300 - For RCU-sched, there is an additional check for idle in the IPI 301 - handler, <tt>sync_sched_exp_handler()</tt>. 301 + For RCU-sched, there is an additional check: 302 302 If the IPI has interrupted the idle loop, then 303 - <tt>sync_sched_exp_handler()</tt> invokes <tt>rcu_report_exp_rdp()</tt> 303 + <tt>rcu_exp_handler()</tt> invokes <tt>rcu_report_exp_rdp()</tt> 304 304 to report the corresponding quiescent state. 305 305 306 306 <p> 307 307 For RCU-preempt, there is no specific check for idle in the 308 - IPI handler (<tt>sync_rcu_exp_handler()</tt>), but because 308 + IPI handler (<tt>rcu_exp_handler()</tt>), but because 309 309 RCU read-side critical sections are not permitted within the 310 - idle loop, if <tt>sync_rcu_exp_handler()</tt> sees that the CPU is within 310 + idle loop, if <tt>rcu_exp_handler()</tt> sees that the CPU is within 311 311 RCU read-side critical section, the CPU cannot possibly be idle. 312 - Otherwise, <tt>sync_rcu_exp_handler()</tt> invokes 312 + Otherwise, <tt>rcu_exp_handler()</tt> invokes 313 313 <tt>rcu_report_exp_rdp()</tt> to report the corresponding quiescent 314 314 state, regardless of whether or not that quiescent state was due to 315 315 the CPU being idle. ··· 623 625 <p> 624 626 With this refinement, synchronous grace periods can now be used from 625 627 task context pretty much any time during the life of the kernel. 628 + That is, aside from some points in the suspend, hibernate, or shutdown 629 + code path. 626 630 627 631 <h3><a name="Summary"> 628 632 Summary</a></h3>
+3 -3
Documentation/RCU/Design/Memory-Ordering/Tree-RCU-Memory-Ordering.html
··· 485 485 noted by <tt>rcu_node_context_switch()</tt> on the left. 486 486 On the other hand, if the CPU takes a scheduler-clock interrupt 487 487 while executing in usermode, a quiescent state will be noted by 488 - <tt>rcu_check_callbacks()</tt> on the right. 488 + <tt>rcu_sched_clock_irq()</tt> on the right. 489 489 Either way, the passage through a quiescent state will be noted 490 490 in a per-CPU variable. 491 491 492 492 <p>The next time an <tt>RCU_SOFTIRQ</tt> handler executes on 493 493 this CPU (for example, after the next scheduler-clock 494 - interrupt), <tt>__rcu_process_callbacks()</tt> will invoke 494 + interrupt), <tt>rcu_core()</tt> will invoke 495 495 <tt>rcu_check_quiescent_state()</tt>, which will notice the 496 496 recorded quiescent state, and invoke 497 497 <tt>rcu_report_qs_rdp()</tt>. ··· 651 651 These callbacks are identified by <tt>rcu_advance_cbs()</tt>, 652 652 which is usually invoked by <tt>__note_gp_changes()</tt>. 653 653 As shown in the diagram below, this invocation can be triggered by 654 - the scheduling-clock interrupt (<tt>rcu_check_callbacks()</tt> on 654 + the scheduling-clock interrupt (<tt>rcu_sched_clock_irq()</tt> on 655 655 the left) or by idle entry (<tt>rcu_cleanup_after_idle()</tt> on 656 656 the right, but only for kernels build with 657 657 <tt>CONFIG_RCU_FAST_NO_HZ=y</tt>).
+1 -1
Documentation/RCU/Design/Memory-Ordering/TreeRCU-callback-invocation.svg
··· 349 349 font-weight="bold" 350 350 font-size="192" 351 351 id="text202-7-5" 352 - 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> 352 + 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> 353 353 <rect 354 354 x="7069.6187" 355 355 y="5087.4678"
+4 -4
Documentation/RCU/Design/Memory-Ordering/TreeRCU-gp.svg
··· 3902 3902 font-style="normal" 3903 3903 y="-4418.6582" 3904 3904 x="3745.7725" 3905 - xml:space="preserve">rcu_check_callbacks()</text> 3905 + xml:space="preserve">rcu_sched_clock_irq()</text> 3906 3906 </g> 3907 3907 <g 3908 3908 transform="translate(-850.30204,55463.106)" ··· 3924 3924 font-style="normal" 3925 3925 y="-4418.6582" 3926 3926 x="3745.7725" 3927 - xml:space="preserve">rcu_process_callbacks()</text> 3927 + xml:space="preserve">rcu_core()</text> 3928 3928 <text 3929 3929 style="font-size:192px;font-style:normal;font-weight:bold;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier" 3930 3930 id="text202-7-5-3-27-0" ··· 3933 3933 font-style="normal" 3934 3934 y="-4165.7954" 3935 3935 x="3745.7725" 3936 - xml:space="preserve">rcu_check_quiescent_state())</text> 3936 + xml:space="preserve">rcu_check_quiescent_state()</text> 3937 3937 <text 3938 3938 style="font-size:192px;font-style:normal;font-weight:bold;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier" 3939 3939 id="text202-7-5-3-27-0-9" ··· 4968 4968 font-weight="bold" 4969 4969 font-size="192" 4970 4970 id="text202-7-5-19" 4971 - 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> 4971 + 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> 4972 4972 <rect 4973 4973 x="5314.2671" 4974 4974 y="82817.688"
+3 -3
Documentation/RCU/Design/Memory-Ordering/TreeRCU-qs.svg
··· 775 775 font-style="normal" 776 776 y="-4418.6582" 777 777 x="3745.7725" 778 - xml:space="preserve">rcu_check_callbacks()</text> 778 + xml:space="preserve">rcu_sched_clock_irq()</text> 779 779 </g> 780 780 <g 781 781 transform="translate(399.7744,828.86448)" ··· 797 797 font-style="normal" 798 798 y="-4418.6582" 799 799 x="3745.7725" 800 - xml:space="preserve">rcu_process_callbacks()</text> 800 + xml:space="preserve">rcu_core()</text> 801 801 <text 802 802 style="font-size:192px;font-style:normal;font-weight:bold;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier" 803 803 id="text202-7-5-3-27-0" ··· 806 806 font-style="normal" 807 807 y="-4165.7954" 808 808 x="3745.7725" 809 - xml:space="preserve">rcu_check_quiescent_state())</text> 809 + xml:space="preserve">rcu_check_quiescent_state()</text> 810 810 <text 811 811 style="font-size:192px;font-style:normal;font-weight:bold;text-anchor:start;fill:#000000;stroke-width:0.025in;font-family:Courier" 812 812 id="text202-7-5-3-27-0-9"
+13 -7
Documentation/RCU/Design/Requirements/Requirements.html
··· 3099 3099 sections, then that domain's grace periods will also be blocked forever. 3100 3100 Of course, one good way to block forever is to deadlock, which can 3101 3101 happen if any operation in a given domain's SRCU read-side critical 3102 - section can block waiting, either directly or indirectly, for that domain's 3102 + section can wait, either directly or indirectly, for that domain's 3103 3103 grace period to elapse. 3104 3104 For example, this results in a self-deadlock: 3105 3105 ··· 3139 3139 guarantees a full memory barrier. 3140 3140 3141 3141 <p> 3142 - Also unlike other RCU flavors, SRCU's callbacks-wait function 3143 - <tt>srcu_barrier()</tt> may be invoked from CPU-hotplug notifiers, 3144 - though this is not necessarily a good idea. 3145 - The reason that this is possible is that SRCU is insensitive 3146 - to whether or not a CPU is online, which means that <tt>srcu_barrier()</tt> 3147 - need not exclude CPU-hotplug operations. 3142 + Also unlike other RCU flavors, <tt>synchronize_srcu()</tt> may <b>not</b> 3143 + be invoked from CPU-hotplug notifiers, due to the fact that SRCU grace 3144 + periods make use of timers and the possibility of timers being temporarily 3145 + &ldquo;stranded&rdquo; on the outgoing CPU. 3146 + This stranding of timers means that timers posted to the outgoing CPU 3147 + will not fire until late in the CPU-hotplug process. 3148 + The problem is that if a notifier is waiting on an SRCU grace period, 3149 + that grace period is waiting on a timer, and that timer is stranded on the 3150 + outgoing CPU, then the notifier will never be awakened, in other words, 3151 + deadlock has occurred. 3152 + This same situation of course also prohibits <tt>srcu_barrier()</tt> 3153 + from being invoked from CPU-hotplug notifiers. 3148 3154 3149 3155 <p> 3150 3156 SRCU also differs from other RCU flavors in that SRCU's expedited and
+8 -7
Documentation/RCU/stallwarn.txt
··· 219 219 In kernels with CONFIG_RCU_FAST_NO_HZ, more information is printed 220 220 for each CPU: 221 221 222 - 0: (64628 ticks this GP) idle=dd5/3fffffffffffffff/0 softirq=82/543 last_accelerate: a345/d342 nonlazy_posted: 25 .D 222 + 0: (64628 ticks this GP) idle=dd5/3fffffffffffffff/0 softirq=82/543 last_accelerate: a345/d342 Nonlazy posted: ..D 223 223 224 224 The "last_accelerate:" prints the low-order 16 bits (in hex) of the 225 225 jiffies counter when this CPU last invoked rcu_try_advance_all_cbs() 226 226 from rcu_needs_cpu() or last invoked rcu_accelerate_cbs() from 227 - rcu_prepare_for_idle(). The "nonlazy_posted:" prints the number 228 - of non-lazy callbacks posted since the last call to rcu_needs_cpu(). 229 - Finally, an "L" indicates that there are currently no non-lazy callbacks 230 - ("." is printed otherwise, as shown above) and "D" indicates that 231 - dyntick-idle processing is enabled ("." is printed otherwise, for example, 232 - if disabled via the "nohz=" kernel boot parameter). 227 + rcu_prepare_for_idle(). The "Nonlazy posted:" indicates lazy-callback 228 + status, so that an "l" indicates that all callbacks were lazy at the start 229 + of the last idle period and an "L" indicates that there are currently 230 + no non-lazy callbacks (in both cases, "." is printed otherwise, as 231 + shown above) and "D" indicates that dyntick-idle processing is enabled 232 + ("." is printed otherwise, for example, if disabled via the "nohz=" 233 + kernel boot parameter). 233 234 234 235 If the grace period ends just as the stall warning starts printing, 235 236 there will be a spurious stall-warning message, which will include
+2 -167
Documentation/RCU/torture.txt
··· 10 10 command (perhaps grepping for "torture"). The test is started 11 11 when the module is loaded, and stops when the module is unloaded. 12 12 13 - 14 - MODULE PARAMETERS 15 - 16 - This module has the following parameters: 17 - 18 - fqs_duration Duration (in microseconds) of artificially induced bursts 19 - of force_quiescent_state() invocations. In RCU 20 - implementations having force_quiescent_state(), these 21 - bursts help force races between forcing a given grace 22 - period and that grace period ending on its own. 23 - 24 - fqs_holdoff Holdoff time (in microseconds) between consecutive calls 25 - to force_quiescent_state() within a burst. 26 - 27 - fqs_stutter Wait time (in seconds) between consecutive bursts 28 - of calls to force_quiescent_state(). 29 - 30 - gp_normal Make the fake writers use normal synchronous grace-period 31 - primitives. 32 - 33 - gp_exp Make the fake writers use expedited synchronous grace-period 34 - primitives. If both gp_normal and gp_exp are set, or 35 - if neither gp_normal nor gp_exp are set, then randomly 36 - choose the primitive so that about 50% are normal and 37 - 50% expedited. By default, neither are set, which 38 - gives best overall test coverage. 39 - 40 - irqreader Says to invoke RCU readers from irq level. This is currently 41 - done via timers. Defaults to "1" for variants of RCU that 42 - permit this. (Or, more accurately, variants of RCU that do 43 - -not- permit this know to ignore this variable.) 44 - 45 - n_barrier_cbs If this is nonzero, RCU barrier testing will be conducted, 46 - in which case n_barrier_cbs specifies the number of 47 - RCU callbacks (and corresponding kthreads) to use for 48 - this testing. The value cannot be negative. If you 49 - specify this to be non-zero when torture_type indicates a 50 - synchronous RCU implementation (one for which a member of 51 - the synchronize_rcu() rather than the call_rcu() family is 52 - used -- see the documentation for torture_type below), an 53 - error will be reported and no testing will be carried out. 54 - 55 - nfakewriters This is the number of RCU fake writer threads to run. Fake 56 - writer threads repeatedly use the synchronous "wait for 57 - current readers" function of the interface selected by 58 - torture_type, with a delay between calls to allow for various 59 - different numbers of writers running in parallel. 60 - nfakewriters defaults to 4, which provides enough parallelism 61 - to trigger special cases caused by multiple writers, such as 62 - the synchronize_srcu() early return optimization. 63 - 64 - nreaders This is the number of RCU reading threads supported. 65 - The default is twice the number of CPUs. Why twice? 66 - To properly exercise RCU implementations with preemptible 67 - read-side critical sections. 68 - 69 - onoff_interval 70 - The number of seconds between each attempt to execute a 71 - randomly selected CPU-hotplug operation. Defaults to 72 - zero, which disables CPU hotplugging. In HOTPLUG_CPU=n 73 - kernels, rcutorture will silently refuse to do any 74 - CPU-hotplug operations regardless of what value is 75 - specified for onoff_interval. 76 - 77 - onoff_holdoff The number of seconds to wait until starting CPU-hotplug 78 - operations. This would normally only be used when 79 - rcutorture was built into the kernel and started 80 - automatically at boot time, in which case it is useful 81 - in order to avoid confusing boot-time code with CPUs 82 - coming and going. 83 - 84 - shuffle_interval 85 - The number of seconds to keep the test threads affinitied 86 - to a particular subset of the CPUs, defaults to 3 seconds. 87 - Used in conjunction with test_no_idle_hz. 88 - 89 - shutdown_secs The number of seconds to run the test before terminating 90 - the test and powering off the system. The default is 91 - zero, which disables test termination and system shutdown. 92 - This capability is useful for automated testing. 93 - 94 - stall_cpu The number of seconds that a CPU should be stalled while 95 - within both an rcu_read_lock() and a preempt_disable(). 96 - This stall happens only once per rcutorture run. 97 - If you need multiple stalls, use modprobe and rmmod to 98 - repeatedly run rcutorture. The default for stall_cpu 99 - is zero, which prevents rcutorture from stalling a CPU. 100 - 101 - Note that attempts to rmmod rcutorture while the stall 102 - is ongoing will hang, so be careful what value you 103 - choose for this module parameter! In addition, too-large 104 - values for stall_cpu might well induce failures and 105 - warnings in other parts of the kernel. You have been 106 - warned! 107 - 108 - stall_cpu_holdoff 109 - The number of seconds to wait after rcutorture starts 110 - before stalling a CPU. Defaults to 10 seconds. 111 - 112 - stat_interval The number of seconds between output of torture 113 - statistics (via printk()). Regardless of the interval, 114 - statistics are printed when the module is unloaded. 115 - Setting the interval to zero causes the statistics to 116 - be printed -only- when the module is unloaded, and this 117 - is the default. 118 - 119 - stutter The length of time to run the test before pausing for this 120 - same period of time. Defaults to "stutter=5", so as 121 - to run and pause for (roughly) five-second intervals. 122 - Specifying "stutter=0" causes the test to run continuously 123 - without pausing, which is the old default behavior. 124 - 125 - test_boost Whether or not to test the ability of RCU to do priority 126 - boosting. Defaults to "test_boost=1", which performs 127 - RCU priority-inversion testing only if the selected 128 - RCU implementation supports priority boosting. Specifying 129 - "test_boost=0" never performs RCU priority-inversion 130 - testing. Specifying "test_boost=2" performs RCU 131 - priority-inversion testing even if the selected RCU 132 - implementation does not support RCU priority boosting, 133 - which can be used to test rcutorture's ability to 134 - carry out RCU priority-inversion testing. 135 - 136 - test_boost_interval 137 - The number of seconds in an RCU priority-inversion test 138 - cycle. Defaults to "test_boost_interval=7". It is 139 - usually wise for this value to be relatively prime to 140 - the value selected for "stutter". 141 - 142 - test_boost_duration 143 - The number of seconds to do RCU priority-inversion testing 144 - within any given "test_boost_interval". Defaults to 145 - "test_boost_duration=4". 146 - 147 - test_no_idle_hz Whether or not to test the ability of RCU to operate in 148 - a kernel that disables the scheduling-clock interrupt to 149 - idle CPUs. Boolean parameter, "1" to test, "0" otherwise. 150 - Defaults to omitting this test. 151 - 152 - torture_type The type of RCU to test, with string values as follows: 153 - 154 - "rcu": rcu_read_lock(), rcu_read_unlock() and call_rcu(), 155 - along with expedited, synchronous, and polling 156 - variants. 157 - 158 - "rcu_bh": rcu_read_lock_bh(), rcu_read_unlock_bh(), and 159 - call_rcu_bh(), along with expedited and synchronous 160 - variants. 161 - 162 - "rcu_busted": This tests an intentionally incorrect version 163 - of RCU in order to help test rcutorture itself. 164 - 165 - "srcu": srcu_read_lock(), srcu_read_unlock() and 166 - call_srcu(), along with expedited and 167 - synchronous variants. 168 - 169 - "sched": preempt_disable(), preempt_enable(), and 170 - call_rcu_sched(), along with expedited, 171 - synchronous, and polling variants. 172 - 173 - "tasks": voluntary context switch and call_rcu_tasks(), 174 - along with expedited and synchronous variants. 175 - 176 - Defaults to "rcu". 177 - 178 - verbose Enable debug printk()s. Default is disabled. 179 - 13 + Module parameters are prefixed by "rcutorture." in 14 + Documentation/admin-guide/kernel-parameters.txt. 180 15 181 16 OUTPUT 182 17
+2 -2
Documentation/RCU/whatisRCU.txt
··· 302 302 must prohibit. The rcu_dereference_protected() variant takes 303 303 a lockdep expression to indicate which locks must be acquired 304 304 by the caller. If the indicated protection is not provided, 305 - a lockdep splat is emitted. See RCU/Design/Requirements.html 305 + a lockdep splat is emitted. See RCU/Design/Requirements/Requirements.html 306 306 and the API's code comments for more details and example usage. 307 307 308 308 The following diagram shows how each API communicates among the ··· 560 560 in terms of familiar locking primitives, and another that more closely 561 561 resembles "classic" RCU. Both are way too simple for real-world use, 562 562 lacking both functionality and performance. However, they are useful 563 - in getting a feel for how RCU works. See kernel/rcupdate.c for a 563 + in getting a feel for how RCU works. See kernel/rcu/update.c for a 564 564 production-quality implementation, and see: 565 565 566 566 http://www.rdrop.com/users/paulmck/RCU
+19 -13
Documentation/admin-guide/kernel-parameters.txt
··· 3658 3658 latencies, which will choose a value aligned 3659 3659 with the appropriate hardware boundaries. 3660 3660 3661 - rcutree.jiffies_till_sched_qs= [KNL] 3662 - Set required age in jiffies for a 3663 - given grace period before RCU starts 3664 - soliciting quiescent-state help from 3665 - rcu_note_context_switch(). If not specified, the 3666 - kernel will calculate a value based on the most 3667 - recent settings of rcutree.jiffies_till_first_fqs 3668 - and rcutree.jiffies_till_next_fqs. 3669 - This calculated value may be viewed in 3670 - rcutree.jiffies_to_sched_qs. Any attempt to 3671 - set rcutree.jiffies_to_sched_qs will be 3672 - cheerfully overwritten. 3673 - 3674 3661 rcutree.jiffies_till_first_fqs= [KNL] 3675 3662 Set delay from grace-period initialization to 3676 3663 first attempt to force quiescent states. ··· 3668 3681 Set delay between subsequent attempts to force 3669 3682 quiescent states. Units are jiffies, minimum 3670 3683 value is one, and maximum value is HZ. 3684 + 3685 + rcutree.jiffies_till_sched_qs= [KNL] 3686 + Set required age in jiffies for a 3687 + given grace period before RCU starts 3688 + soliciting quiescent-state help from 3689 + rcu_note_context_switch() and cond_resched(). 3690 + If not specified, the kernel will calculate 3691 + a value based on the most recent settings 3692 + of rcutree.jiffies_till_first_fqs 3693 + and rcutree.jiffies_till_next_fqs. 3694 + This calculated value may be viewed in 3695 + rcutree.jiffies_to_sched_qs. Any attempt to set 3696 + rcutree.jiffies_to_sched_qs will be cheerfully 3697 + overwritten. 3671 3698 3672 3699 rcutree.kthread_prio= [KNL,BOOT] 3673 3700 Set the SCHED_FIFO priority of the RCU per-CPU ··· 3725 3724 it should at force-quiescent-state time. 3726 3725 This wake_up() will be accompanied by a 3727 3726 WARN_ONCE() splat and an ftrace_dump(). 3727 + 3728 + rcutree.sysrq_rcu= [KNL] 3729 + Commandeer a sysrq key to dump out Tree RCU's 3730 + rcu_node tree with an eye towards determining 3731 + why a new grace period has not yet started. 3728 3732 3729 3733 rcuperf.gp_async= [KNL] 3730 3734 Measure performance of asynchronous
+6
MAINTAINERS
··· 10827 10827 F: drivers/power/supply/isp1704_charger.c 10828 10828 F: drivers/power/supply/rx51_battery.c 10829 10829 10830 + NOLIBC HEADER FILE 10831 + M: Willy Tarreau <w@1wt.eu> 10832 + S: Maintained 10833 + T: git git://git.kernel.org/pub/scm/linux/kernel/git/wtarreau/nolibc.git 10834 + F: tools/include/nolibc/ 10835 + 10830 10836 NTB AMD DRIVER 10831 10837 M: Shyam Sundar S K <Shyam-sundar.S-k@amd.com> 10832 10838 L: linux-ntb@googlegroups.com
-3
include/asm-generic/bug.h
··· 211 211 /* 212 212 * WARN_ON_SMP() is for cases that the warning is either 213 213 * meaningless for !SMP or may even cause failures. 214 - * This is usually used for cases that we have 215 - * WARN_ON(!spin_is_locked(&lock)) checks, as spin_is_locked() 216 - * returns 0 for uniprocessor settings. 217 214 * It can also be used with values that are only defined 218 215 * on SMP: 219 216 *
+2 -15
include/linux/rcu_node_tree.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0+ */ 1 2 /* 2 3 * RCU node combining tree definitions. These are used to compute 3 4 * global attributes while avoiding common-case global contention. A key ··· 12 11 * because the size of the TREE SRCU srcu_struct structure depends 13 12 * on these definitions. 14 13 * 15 - * This program is free software; you can redistribute it and/or modify 16 - * it under the terms of the GNU General Public License as published by 17 - * the Free Software Foundation; either version 2 of the License, or 18 - * (at your option) any later version. 19 - * 20 - * This program is distributed in the hope that it will be useful, 21 - * but WITHOUT ANY WARRANTY; without even the implied warranty of 22 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 - * GNU General Public License for more details. 24 - * 25 - * You should have received a copy of the GNU General Public License 26 - * along with this program; if not, you can access it online at 27 - * http://www.gnu.org/licenses/gpl-2.0.html. 28 - * 29 14 * Copyright IBM Corporation, 2017 30 15 * 31 - * Author: Paul E. McKenney <paulmck@linux.vnet.ibm.com> 16 + * Author: Paul E. McKenney <paulmck@linux.ibm.com> 32 17 */ 33 18 34 19 #ifndef __LINUX_RCU_NODE_TREE_H
+2 -15
include/linux/rcu_segcblist.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0+ */ 1 2 /* 2 3 * RCU segmented callback lists 3 4 * ··· 6 5 * because the size of the TREE SRCU srcu_struct structure depends 7 6 * on these definitions. 8 7 * 9 - * This program is free software; you can redistribute it and/or modify 10 - * it under the terms of the GNU General Public License as published by 11 - * the Free Software Foundation; either version 2 of the License, or 12 - * (at your option) any later version. 13 - * 14 - * This program is distributed in the hope that it will be useful, 15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 - * GNU General Public License for more details. 18 - * 19 - * You should have received a copy of the GNU General Public License 20 - * along with this program; if not, you can access it online at 21 - * http://www.gnu.org/licenses/gpl-2.0.html. 22 - * 23 8 * Copyright IBM Corporation, 2017 24 9 * 25 - * Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com> 10 + * Authors: Paul E. McKenney <paulmck@linux.net.ibm.com> 26 11 */ 27 12 28 13 #ifndef __INCLUDE_LINUX_RCU_SEGCBLIST_H
+1 -14
include/linux/rcu_sync.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0+ */ 1 2 /* 2 3 * RCU-based infrastructure for lightweight reader-writer locking 3 - * 4 - * This program is free software; you can redistribute it and/or modify 5 - * it under the terms of the GNU General Public License as published by 6 - * the Free Software Foundation; either version 2 of the License, or 7 - * (at your option) any later version. 8 - * 9 - * This program is distributed in the hope that it will be useful, 10 - * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 - * GNU General Public License for more details. 13 - * 14 - * You should have received a copy of the GNU General Public License 15 - * along with this program; if not, you can access it online at 16 - * http://www.gnu.org/licenses/gpl-2.0.html. 17 4 * 18 5 * Copyright (c) 2015, Red Hat, Inc. 19 6 *
+13 -78
include/linux/rcupdate.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0+ */ 1 2 /* 2 3 * Read-Copy Update mechanism for mutual exclusion 3 - * 4 - * This program is free software; you can redistribute it and/or modify 5 - * it under the terms of the GNU General Public License as published by 6 - * the Free Software Foundation; either version 2 of the License, or 7 - * (at your option) any later version. 8 - * 9 - * This program is distributed in the hope that it will be useful, 10 - * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 - * GNU General Public License for more details. 13 - * 14 - * You should have received a copy of the GNU General Public License 15 - * along with this program; if not, you can access it online at 16 - * http://www.gnu.org/licenses/gpl-2.0.html. 17 4 * 18 5 * Copyright IBM Corporation, 2001 19 6 * 20 7 * Author: Dipankar Sarma <dipankar@in.ibm.com> 21 8 * 22 - * Based on the original work by Paul McKenney <paulmck@us.ibm.com> 9 + * Based on the original work by Paul McKenney <paulmck@vnet.ibm.com> 23 10 * and inputs from Rusty Russell, Andrea Arcangeli and Andi Kleen. 24 11 * Papers: 25 12 * http://www.rdrop.com/users/paulmck/paper/rclockpdcsproof.pdf ··· 76 89 /* Internal to kernel */ 77 90 void rcu_init(void); 78 91 extern int rcu_scheduler_active __read_mostly; 79 - void rcu_check_callbacks(int user); 92 + void rcu_sched_clock_irq(int user); 80 93 void rcu_report_dead(unsigned int cpu); 81 94 void rcutree_migrate_callbacks(int cpu); 82 95 ··· 296 309 */ 297 310 298 311 #ifdef __CHECKER__ 299 - #define rcu_dereference_sparse(p, space) \ 312 + #define rcu_check_sparse(p, space) \ 300 313 ((void)(((typeof(*p) space *)p) == p)) 301 314 #else /* #ifdef __CHECKER__ */ 302 - #define rcu_dereference_sparse(p, space) 315 + #define rcu_check_sparse(p, space) 303 316 #endif /* #else #ifdef __CHECKER__ */ 304 317 305 318 #define __rcu_access_pointer(p, space) \ 306 319 ({ \ 307 320 typeof(*p) *_________p1 = (typeof(*p) *__force)READ_ONCE(p); \ 308 - rcu_dereference_sparse(p, space); \ 321 + rcu_check_sparse(p, space); \ 309 322 ((typeof(*p) __force __kernel *)(_________p1)); \ 310 323 }) 311 324 #define __rcu_dereference_check(p, c, space) \ ··· 313 326 /* Dependency order vs. p above. */ \ 314 327 typeof(*p) *________p1 = (typeof(*p) *__force)READ_ONCE(p); \ 315 328 RCU_LOCKDEP_WARN(!(c), "suspicious rcu_dereference_check() usage"); \ 316 - rcu_dereference_sparse(p, space); \ 329 + rcu_check_sparse(p, space); \ 317 330 ((typeof(*p) __force __kernel *)(________p1)); \ 318 331 }) 319 332 #define __rcu_dereference_protected(p, c, space) \ 320 333 ({ \ 321 334 RCU_LOCKDEP_WARN(!(c), "suspicious rcu_dereference_protected() usage"); \ 322 - rcu_dereference_sparse(p, space); \ 335 + rcu_check_sparse(p, space); \ 323 336 ((typeof(*p) __force __kernel *)(p)); \ 324 337 }) 325 338 #define rcu_dereference_raw(p) \ ··· 369 382 #define rcu_assign_pointer(p, v) \ 370 383 ({ \ 371 384 uintptr_t _r_a_p__v = (uintptr_t)(v); \ 385 + rcu_check_sparse(p, __rcu); \ 372 386 \ 373 387 if (__builtin_constant_p(v) && (_r_a_p__v) == (uintptr_t)NULL) \ 374 388 WRITE_ONCE((p), (typeof(p))(_r_a_p__v)); \ ··· 773 785 */ 774 786 #define RCU_INIT_POINTER(p, v) \ 775 787 do { \ 776 - rcu_dereference_sparse(p, __rcu); \ 788 + rcu_check_sparse(p, __rcu); \ 777 789 WRITE_ONCE(p, RCU_INITIALIZER(v)); \ 778 790 } while (0) 779 791 ··· 847 859 848 860 /* Has the specified rcu_head structure been handed to call_rcu()? */ 849 861 850 - /* 862 + /** 851 863 * rcu_head_init - Initialize rcu_head for rcu_head_after_call_rcu() 852 864 * @rhp: The rcu_head structure to initialize. 853 865 * ··· 862 874 rhp->func = (rcu_callback_t)~0L; 863 875 } 864 876 865 - /* 877 + /** 866 878 * rcu_head_after_call_rcu - Has this rcu_head been passed to call_rcu()? 867 879 * @rhp: The rcu_head structure to test. 868 - * @func: The function passed to call_rcu() along with @rhp. 880 + * @f: The function passed to call_rcu() along with @rhp. 869 881 * 870 882 * Returns @true if the @rhp has been passed to call_rcu() with @func, 871 883 * and @false otherwise. Emits a warning in any other case, including ··· 882 894 return true; 883 895 WARN_ON_ONCE(READ_ONCE(rhp->func) != (rcu_callback_t)~0L); 884 896 return false; 885 - } 886 - 887 - 888 - /* Transitional pre-consolidation compatibility definitions. */ 889 - 890 - static inline void synchronize_rcu_bh(void) 891 - { 892 - synchronize_rcu(); 893 - } 894 - 895 - static inline void synchronize_rcu_bh_expedited(void) 896 - { 897 - synchronize_rcu_expedited(); 898 - } 899 - 900 - static inline void call_rcu_bh(struct rcu_head *head, rcu_callback_t func) 901 - { 902 - call_rcu(head, func); 903 - } 904 - 905 - static inline void rcu_barrier_bh(void) 906 - { 907 - rcu_barrier(); 908 - } 909 - 910 - static inline void synchronize_sched(void) 911 - { 912 - synchronize_rcu(); 913 - } 914 - 915 - static inline void synchronize_sched_expedited(void) 916 - { 917 - synchronize_rcu_expedited(); 918 - } 919 - 920 - static inline void call_rcu_sched(struct rcu_head *head, rcu_callback_t func) 921 - { 922 - call_rcu(head, func); 923 - } 924 - 925 - static inline void rcu_barrier_sched(void) 926 - { 927 - rcu_barrier(); 928 - } 929 - 930 - static inline unsigned long get_state_synchronize_sched(void) 931 - { 932 - return get_state_synchronize_rcu(); 933 - } 934 - 935 - static inline void cond_synchronize_sched(unsigned long oldstate) 936 - { 937 - cond_synchronize_rcu(oldstate); 938 897 } 939 898 940 899 #endif /* __LINUX_RCUPDATE_H */
+2 -15
include/linux/rcutiny.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0+ */ 1 2 /* 2 3 * Read-Copy Update mechanism for mutual exclusion, the Bloatwatch edition. 3 4 * 4 - * This program is free software; you can redistribute it and/or modify 5 - * it under the terms of the GNU General Public License as published by 6 - * the Free Software Foundation; either version 2 of the License, or 7 - * (at your option) any later version. 8 - * 9 - * This program is distributed in the hope that it will be useful, 10 - * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 - * GNU General Public License for more details. 13 - * 14 - * You should have received a copy of the GNU General Public License 15 - * along with this program; if not, you can access it online at 16 - * http://www.gnu.org/licenses/gpl-2.0.html. 17 - * 18 5 * Copyright IBM Corporation, 2008 19 6 * 20 - * Author: Paul E. McKenney <paulmck@linux.vnet.ibm.com> 7 + * Author: Paul E. McKenney <paulmck@linux.ibm.com> 21 8 * 22 9 * For detailed explanation of Read-Copy Update mechanism see - 23 10 * Documentation/RCU
+3 -16
include/linux/rcutree.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0+ */ 1 2 /* 2 3 * Read-Copy Update mechanism for mutual exclusion (tree-based version) 3 - * 4 - * This program is free software; you can redistribute it and/or modify 5 - * it under the terms of the GNU General Public License as published by 6 - * the Free Software Foundation; either version 2 of the License, or 7 - * (at your option) any later version. 8 - * 9 - * This program is distributed in the hope that it will be useful, 10 - * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 - * GNU General Public License for more details. 13 - * 14 - * You should have received a copy of the GNU General Public License 15 - * along with this program; if not, you can access it online at 16 - * http://www.gnu.org/licenses/gpl-2.0.html. 17 4 * 18 5 * Copyright IBM Corporation, 2008 19 6 * 20 7 * Author: Dipankar Sarma <dipankar@in.ibm.com> 21 - * Paul E. McKenney <paulmck@linux.vnet.ibm.com> Hierarchical algorithm 8 + * Paul E. McKenney <paulmck@linux.ibm.com> Hierarchical algorithm 22 9 * 23 - * Based on the original work by Paul McKenney <paulmck@us.ibm.com> 10 + * Based on the original work by Paul McKenney <paulmck@linux.ibm.com> 24 11 * and inputs from Rusty Russell, Andrea Arcangeli and Andi Kleen. 25 12 * 26 13 * For detailed explanation of Read-Copy Update mechanism see -
+3 -15
include/linux/srcu.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0+ */ 1 2 /* 2 3 * Sleepable Read-Copy Update mechanism for mutual exclusion 3 - * 4 - * This program is free software; you can redistribute it and/or modify 5 - * it under the terms of the GNU General Public License as published by 6 - * the Free Software Foundation; either version 2 of the License, or 7 - * (at your option) any later version. 8 - * 9 - * This program is distributed in the hope that it will be useful, 10 - * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 - * GNU General Public License for more details. 13 - * 14 - * You should have received a copy of the GNU General Public License 15 - * along with this program; if not, you can access it online at 16 - * http://www.gnu.org/licenses/gpl-2.0.html. 17 4 * 18 5 * Copyright (C) IBM Corporation, 2006 19 6 * Copyright (C) Fujitsu, 2012 20 7 * 21 - * Author: Paul McKenney <paulmck@us.ibm.com> 8 + * Author: Paul McKenney <paulmck@linux.ibm.com> 22 9 * Lai Jiangshan <laijs@cn.fujitsu.com> 23 10 * 24 11 * For detailed explanation of Read-Copy Update mechanism see - ··· 210 223 static inline void srcu_read_unlock(struct srcu_struct *ssp, int idx) 211 224 __releases(ssp) 212 225 { 226 + WARN_ON_ONCE(idx & ~0x1); 213 227 rcu_lock_release(&(ssp)->dep_map); 214 228 __srcu_read_unlock(ssp, idx); 215 229 }
+2 -15
include/linux/srcutiny.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0+ */ 1 2 /* 2 3 * Sleepable Read-Copy Update mechanism for mutual exclusion, 3 4 * tiny variant. 4 5 * 5 - * This program is free software; you can redistribute it and/or modify 6 - * it under the terms of the GNU General Public License as published by 7 - * the Free Software Foundation; either version 2 of the License, or 8 - * (at your option) any later version. 9 - * 10 - * This program is distributed in the hope that it will be useful, 11 - * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 - * GNU General Public License for more details. 14 - * 15 - * You should have received a copy of the GNU General Public License 16 - * along with this program; if not, you can access it online at 17 - * http://www.gnu.org/licenses/gpl-2.0.html. 18 - * 19 6 * Copyright (C) IBM Corporation, 2017 20 7 * 21 - * Author: Paul McKenney <paulmck@us.ibm.com> 8 + * Author: Paul McKenney <paulmck@linux.ibm.com> 22 9 */ 23 10 24 11 #ifndef _LINUX_SRCU_TINY_H
+4 -16
include/linux/srcutree.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0+ */ 1 2 /* 2 3 * Sleepable Read-Copy Update mechanism for mutual exclusion, 3 4 * tree variant. 4 5 * 5 - * This program is free software; you can redistribute it and/or modify 6 - * it under the terms of the GNU General Public License as published by 7 - * the Free Software Foundation; either version 2 of the License, or 8 - * (at your option) any later version. 9 - * 10 - * This program is distributed in the hope that it will be useful, 11 - * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 - * GNU General Public License for more details. 14 - * 15 - * You should have received a copy of the GNU General Public License 16 - * along with this program; if not, you can access it online at 17 - * http://www.gnu.org/licenses/gpl-2.0.html. 18 - * 19 6 * Copyright (C) IBM Corporation, 2017 20 7 * 21 - * Author: Paul McKenney <paulmck@us.ibm.com> 8 + * Author: Paul McKenney <paulmck@linux.ibm.com> 22 9 */ 23 10 24 11 #ifndef _LINUX_SRCU_TREE_H ··· 32 45 unsigned long srcu_gp_seq_needed; /* Furthest future GP needed. */ 33 46 unsigned long srcu_gp_seq_needed_exp; /* Furthest future exp GP. */ 34 47 bool srcu_cblist_invoking; /* Invoking these CBs? */ 35 - struct delayed_work work; /* Context for CB invoking. */ 48 + struct timer_list delay_work; /* Delay for CB invoking */ 49 + struct work_struct work; /* Context for CB invoking. */ 36 50 struct rcu_head srcu_barrier_head; /* For srcu_barrier() use. */ 37 51 struct srcu_node *mynode; /* Leaf srcu_node. */ 38 52 unsigned long grpmask; /* Mask for leaf srcu_node */
+4 -16
include/linux/torture.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0+ */ 1 2 /* 2 3 * Common functions for in-kernel torture tests. 3 4 * 4 - * This program is free software; you can redistribute it and/or modify 5 - * it under the terms of the GNU General Public License as published by 6 - * the Free Software Foundation; either version 2 of the License, or 7 - * (at your option) any later version. 8 - * 9 - * This program is distributed in the hope that it will be useful, 10 - * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 - * GNU General Public License for more details. 13 - * 14 - * You should have received a copy of the GNU General Public License 15 - * along with this program; if not, you can access it online at 16 - * http://www.gnu.org/licenses/gpl-2.0.html. 17 - * 18 5 * Copyright IBM Corporation, 2014 19 6 * 20 - * Author: Paul E. McKenney <paulmck@linux.vnet.ibm.com> 7 + * Author: Paul E. McKenney <paulmck@linux.ibm.com> 21 8 */ 22 9 23 10 #ifndef __LINUX_TORTURE_H ··· 37 50 do { if (verbose) pr_alert("%s" TORTURE_FLAG "!!! %s\n", torture_type, s); } while (0) 38 51 39 52 /* Definitions for online/offline exerciser. */ 53 + typedef void torture_ofl_func(void); 40 54 bool torture_offline(int cpu, long *n_onl_attempts, long *n_onl_successes, 41 55 unsigned long *sum_offl, int *min_onl, int *max_onl); 42 56 bool torture_online(int cpu, long *n_onl_attempts, long *n_onl_successes, 43 57 unsigned long *sum_onl, int *min_onl, int *max_onl); 44 - int torture_onoff_init(long ooholdoff, long oointerval); 58 + int torture_onoff_init(long ooholdoff, long oointerval, torture_ofl_func *f); 45 59 void torture_onoff_stats(void); 46 60 bool torture_onoff_failures(void); 47 61
+4 -17
kernel/locking/locktorture.c
··· 1 + // SPDX-License-Identifier: GPL-2.0+ 1 2 /* 2 3 * Module-based torture test facility for locking 3 4 * 4 - * This program is free software; you can redistribute it and/or modify 5 - * it under the terms of the GNU General Public License as published by 6 - * the Free Software Foundation; either version 2 of the License, or 7 - * (at your option) any later version. 8 - * 9 - * This program is distributed in the hope that it will be useful, 10 - * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 - * GNU General Public License for more details. 13 - * 14 - * You should have received a copy of the GNU General Public License 15 - * along with this program; if not, you can access it online at 16 - * http://www.gnu.org/licenses/gpl-2.0.html. 17 - * 18 5 * Copyright (C) IBM Corporation, 2014 19 6 * 20 - * Authors: Paul E. McKenney <paulmck@us.ibm.com> 7 + * Authors: Paul E. McKenney <paulmck@linux.ibm.com> 21 8 * Davidlohr Bueso <dave@stgolabs.net> 22 9 * Based on kernel/rcu/torture.c. 23 10 */ ··· 32 45 #include <linux/torture.h> 33 46 34 47 MODULE_LICENSE("GPL"); 35 - MODULE_AUTHOR("Paul E. McKenney <paulmck@us.ibm.com>"); 48 + MODULE_AUTHOR("Paul E. McKenney <paulmck@linux.ibm.com>"); 36 49 37 50 torture_param(int, nwriters_stress, -1, 38 51 "Number of write-locking stress-test threads"); ··· 957 970 /* Prepare torture context. */ 958 971 if (onoff_interval > 0) { 959 972 firsterr = torture_onoff_init(onoff_holdoff * HZ, 960 - onoff_interval * HZ); 973 + onoff_interval * HZ, NULL); 961 974 if (firsterr) 962 975 goto unwind; 963 976 }
+3 -18
kernel/rcu/rcu.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0+ */ 1 2 /* 2 3 * Read-Copy Update definitions shared among RCU implementations. 3 4 * 4 - * This program is free software; you can redistribute it and/or modify 5 - * it under the terms of the GNU General Public License as published by 6 - * the Free Software Foundation; either version 2 of the License, or 7 - * (at your option) any later version. 8 - * 9 - * This program is distributed in the hope that it will be useful, 10 - * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 - * GNU General Public License for more details. 13 - * 14 - * You should have received a copy of the GNU General Public License 15 - * along with this program; if not, you can access it online at 16 - * http://www.gnu.org/licenses/gpl-2.0.html. 17 - * 18 5 * Copyright IBM Corporation, 2011 19 6 * 20 - * Author: Paul E. McKenney <paulmck@linux.vnet.ibm.com> 7 + * Author: Paul E. McKenney <paulmck@linux.ibm.com> 21 8 */ 22 9 23 10 #ifndef __LINUX_RCU_H ··· 17 30 #define RCU_TRACE(stmt) 18 31 #endif /* #else #ifdef CONFIG_RCU_TRACE */ 19 32 20 - /* Offset to allow for unmatched rcu_irq_{enter,exit}(). */ 33 + /* Offset to allow distinguishing irq vs. task-based idle entry/exit. */ 21 34 #define DYNTICK_IRQ_NONIDLE ((LONG_MAX / 2) + 1) 22 35 23 36 ··· 449 462 450 463 enum rcutorture_type { 451 464 RCU_FLAVOR, 452 - RCU_BH_FLAVOR, 453 - RCU_SCHED_FLAVOR, 454 465 RCU_TASKS_FLAVOR, 455 466 SRCU_FLAVOR, 456 467 INVALID_RCU_FLAVOR
+2 -15
kernel/rcu/rcu_segcblist.c
··· 1 + // SPDX-License-Identifier: GPL-2.0+ 1 2 /* 2 3 * RCU segmented callback lists, function definitions 3 4 * 4 - * This program is free software; you can redistribute it and/or modify 5 - * it under the terms of the GNU General Public License as published by 6 - * the Free Software Foundation; either version 2 of the License, or 7 - * (at your option) any later version. 8 - * 9 - * This program is distributed in the hope that it will be useful, 10 - * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 - * GNU General Public License for more details. 13 - * 14 - * You should have received a copy of the GNU General Public License 15 - * along with this program; if not, you can access it online at 16 - * http://www.gnu.org/licenses/gpl-2.0.html. 17 - * 18 5 * Copyright IBM Corporation, 2017 19 6 * 20 - * Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com> 7 + * Authors: Paul E. McKenney <paulmck@linux.ibm.com> 21 8 */ 22 9 23 10 #include <linux/types.h>
+2 -15
kernel/rcu/rcu_segcblist.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0+ */ 1 2 /* 2 3 * RCU segmented callback lists, internal-to-rcu header file 3 4 * 4 - * This program is free software; you can redistribute it and/or modify 5 - * it under the terms of the GNU General Public License as published by 6 - * the Free Software Foundation; either version 2 of the License, or 7 - * (at your option) any later version. 8 - * 9 - * This program is distributed in the hope that it will be useful, 10 - * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 - * GNU General Public License for more details. 13 - * 14 - * You should have received a copy of the GNU General Public License 15 - * along with this program; if not, you can access it online at 16 - * http://www.gnu.org/licenses/gpl-2.0.html. 17 - * 18 5 * Copyright IBM Corporation, 2017 19 6 * 20 - * Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com> 7 + * Authors: Paul E. McKenney <paulmck@linux.ibm.com> 21 8 */ 22 9 23 10 #include <linux/rcu_segcblist.h>
+10 -17
kernel/rcu/rcuperf.c
··· 1 + // SPDX-License-Identifier: GPL-2.0+ 1 2 /* 2 3 * Read-Copy Update module-based performance-test facility 3 4 * 4 - * This program is free software; you can redistribute it and/or modify 5 - * it under the terms of the GNU General Public License as published by 6 - * the Free Software Foundation; either version 2 of the License, or 7 - * (at your option) any later version. 8 - * 9 - * This program is distributed in the hope that it will be useful, 10 - * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 - * GNU General Public License for more details. 13 - * 14 - * You should have received a copy of the GNU General Public License 15 - * along with this program; if not, you can access it online at 16 - * http://www.gnu.org/licenses/gpl-2.0.html. 17 - * 18 5 * Copyright (C) IBM Corporation, 2015 19 6 * 20 - * Authors: Paul E. McKenney <paulmck@us.ibm.com> 7 + * Authors: Paul E. McKenney <paulmck@linux.ibm.com> 21 8 */ 22 9 23 10 #define pr_fmt(fmt) fmt ··· 41 54 #include "rcu.h" 42 55 43 56 MODULE_LICENSE("GPL"); 44 - MODULE_AUTHOR("Paul E. McKenney <paulmck@linux.vnet.ibm.com>"); 57 + MODULE_AUTHOR("Paul E. McKenney <paulmck@linux.ibm.com>"); 45 58 46 59 #define PERF_FLAG "-perf:" 47 60 #define PERFOUT_STRING(s) \ ··· 70 83 * Various other use cases may of course be specified. 71 84 */ 72 85 86 + #ifdef MODULE 87 + # define RCUPERF_SHUTDOWN 0 88 + #else 89 + # define RCUPERF_SHUTDOWN 1 90 + #endif 91 + 73 92 torture_param(bool, gp_async, false, "Use asynchronous GP wait primitives"); 74 93 torture_param(int, gp_async_max, 1000, "Max # outstanding waits per reader"); 75 94 torture_param(bool, gp_exp, false, "Use expedited GP wait primitives"); 76 95 torture_param(int, holdoff, 10, "Holdoff time before test start (s)"); 77 96 torture_param(int, nreaders, -1, "Number of RCU reader threads"); 78 97 torture_param(int, nwriters, -1, "Number of RCU updater threads"); 79 - torture_param(bool, shutdown, !IS_ENABLED(MODULE), 98 + torture_param(bool, shutdown, RCUPERF_SHUTDOWN, 80 99 "Shutdown at end of performance tests."); 81 100 torture_param(int, verbose, 1, "Enable verbose debugging printk()s"); 82 101 torture_param(int, writer_holdoff, 0, "Holdoff (us) between GPs, zero to disable");
+35 -24
kernel/rcu/rcutorture.c
··· 1 + // SPDX-License-Identifier: GPL-2.0+ 1 2 /* 2 3 * Read-Copy Update module-based torture test facility 3 4 * 4 - * This program is free software; you can redistribute it and/or modify 5 - * it under the terms of the GNU General Public License as published by 6 - * the Free Software Foundation; either version 2 of the License, or 7 - * (at your option) any later version. 8 - * 9 - * This program is distributed in the hope that it will be useful, 10 - * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 - * GNU General Public License for more details. 13 - * 14 - * You should have received a copy of the GNU General Public License 15 - * along with this program; if not, you can access it online at 16 - * http://www.gnu.org/licenses/gpl-2.0.html. 17 - * 18 5 * Copyright (C) IBM Corporation, 2005, 2006 19 6 * 20 - * Authors: Paul E. McKenney <paulmck@us.ibm.com> 7 + * Authors: Paul E. McKenney <paulmck@linux.ibm.com> 21 8 * Josh Triplett <josh@joshtriplett.org> 22 9 * 23 10 * See also: Documentation/RCU/torture.txt ··· 48 61 #include "rcu.h" 49 62 50 63 MODULE_LICENSE("GPL"); 51 - MODULE_AUTHOR("Paul E. McKenney <paulmck@us.ibm.com> and Josh Triplett <josh@joshtriplett.org>"); 64 + MODULE_AUTHOR("Paul E. McKenney <paulmck@linux.ibm.com> and Josh Triplett <josh@joshtriplett.org>"); 52 65 53 66 54 67 /* Bits for ->extendables field, extendables param, and related definitions. */ ··· 1617 1630 #define MIN_FWD_CB_LAUNDERS 3 /* This many CB invocations to count. */ 1618 1631 #define MIN_FWD_CBS_LAUNDERED 100 /* Number of counted CBs. */ 1619 1632 #define FWD_CBS_HIST_DIV 10 /* Histogram buckets/second. */ 1620 - static long n_launders_hist[2 * MAX_FWD_CB_JIFFIES / (HZ / FWD_CBS_HIST_DIV)]; 1633 + struct rcu_launder_hist { 1634 + long n_launders; 1635 + unsigned long launder_gp_seq; 1636 + }; 1637 + #define N_LAUNDERS_HIST (2 * MAX_FWD_CB_JIFFIES / (HZ / FWD_CBS_HIST_DIV)) 1638 + static struct rcu_launder_hist n_launders_hist[N_LAUNDERS_HIST]; 1639 + static unsigned long rcu_launder_gp_seq_start; 1621 1640 1622 1641 static void rcu_torture_fwd_cb_hist(void) 1623 1642 { 1643 + unsigned long gps; 1644 + unsigned long gps_old; 1624 1645 int i; 1625 1646 int j; 1626 1647 1627 1648 for (i = ARRAY_SIZE(n_launders_hist) - 1; i > 0; i--) 1628 - if (n_launders_hist[i] > 0) 1649 + if (n_launders_hist[i].n_launders > 0) 1629 1650 break; 1630 1651 pr_alert("%s: Callback-invocation histogram (duration %lu jiffies):", 1631 1652 __func__, jiffies - rcu_fwd_startat); 1632 - for (j = 0; j <= i; j++) 1633 - pr_cont(" %ds/%d: %ld", 1634 - j + 1, FWD_CBS_HIST_DIV, n_launders_hist[j]); 1653 + gps_old = rcu_launder_gp_seq_start; 1654 + for (j = 0; j <= i; j++) { 1655 + gps = n_launders_hist[j].launder_gp_seq; 1656 + pr_cont(" %ds/%d: %ld:%ld", 1657 + j + 1, FWD_CBS_HIST_DIV, n_launders_hist[j].n_launders, 1658 + rcutorture_seq_diff(gps, gps_old)); 1659 + gps_old = gps; 1660 + } 1635 1661 pr_cont("\n"); 1636 1662 } 1637 1663 ··· 1666 1666 i = ((jiffies - rcu_fwd_startat) / (HZ / FWD_CBS_HIST_DIV)); 1667 1667 if (i >= ARRAY_SIZE(n_launders_hist)) 1668 1668 i = ARRAY_SIZE(n_launders_hist) - 1; 1669 - n_launders_hist[i]++; 1669 + n_launders_hist[i].n_launders++; 1670 + n_launders_hist[i].launder_gp_seq = cur_ops->get_gp_seq(); 1670 1671 spin_unlock_irqrestore(&rcu_fwd_lock, flags); 1671 1672 } 1672 1673 ··· 1787 1786 n_max_cbs = 0; 1788 1787 n_max_gps = 0; 1789 1788 for (i = 0; i < ARRAY_SIZE(n_launders_hist); i++) 1790 - n_launders_hist[i] = 0; 1789 + n_launders_hist[i].n_launders = 0; 1791 1790 cver = READ_ONCE(rcu_torture_current_version); 1792 1791 gps = cur_ops->get_gp_seq(); 1792 + rcu_launder_gp_seq_start = gps; 1793 1793 while (time_before(jiffies, stopat) && 1794 1794 !READ_ONCE(rcu_fwd_emergency_stop) && !torture_must_stop()) { 1795 1795 rfcp = READ_ONCE(rcu_fwd_cb_head); ··· 2230 2228 #endif /* #else #ifdef CONFIG_DEBUG_OBJECTS_RCU_HEAD */ 2231 2229 } 2232 2230 2231 + static void rcutorture_sync(void) 2232 + { 2233 + static unsigned long n; 2234 + 2235 + if (cur_ops->sync && !(++n & 0xfff)) 2236 + cur_ops->sync(); 2237 + } 2238 + 2233 2239 static int __init 2234 2240 rcu_torture_init(void) 2235 2241 { ··· 2399 2389 firsterr = torture_shutdown_init(shutdown_secs, rcu_torture_cleanup); 2400 2390 if (firsterr) 2401 2391 goto unwind; 2402 - firsterr = torture_onoff_init(onoff_holdoff * HZ, onoff_interval); 2392 + firsterr = torture_onoff_init(onoff_holdoff * HZ, onoff_interval, 2393 + rcutorture_sync); 2403 2394 if (firsterr) 2404 2395 goto unwind; 2405 2396 firsterr = rcu_torture_stall_init();
+2 -15
kernel/rcu/srcutiny.c
··· 1 + // SPDX-License-Identifier: GPL-2.0+ 1 2 /* 2 3 * Sleepable Read-Copy Update mechanism for mutual exclusion, 3 4 * tiny version for non-preemptible single-CPU use. 4 5 * 5 - * This program is free software; you can redistribute it and/or modify 6 - * it under the terms of the GNU General Public License as published by 7 - * the Free Software Foundation; either version 2 of the License, or 8 - * (at your option) any later version. 9 - * 10 - * This program is distributed in the hope that it will be useful, 11 - * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 - * GNU General Public License for more details. 14 - * 15 - * You should have received a copy of the GNU General Public License 16 - * along with this program; if not, you can access it online at 17 - * http://www.gnu.org/licenses/gpl-2.0.html. 18 - * 19 6 * Copyright (C) IBM Corporation, 2017 20 7 * 21 - * Author: Paul McKenney <paulmck@us.ibm.com> 8 + * Author: Paul McKenney <paulmck@linux.ibm.com> 22 9 */ 23 10 24 11 #include <linux/export.h>
+27 -47
kernel/rcu/srcutree.c
··· 1 + // SPDX-License-Identifier: GPL-2.0+ 1 2 /* 2 3 * Sleepable Read-Copy Update mechanism for mutual exclusion. 3 - * 4 - * This program is free software; you can redistribute it and/or modify 5 - * it under the terms of the GNU General Public License as published by 6 - * the Free Software Foundation; either version 2 of the License, or 7 - * (at your option) any later version. 8 - * 9 - * This program is distributed in the hope that it will be useful, 10 - * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 - * GNU General Public License for more details. 13 - * 14 - * You should have received a copy of the GNU General Public License 15 - * along with this program; if not, you can access it online at 16 - * http://www.gnu.org/licenses/gpl-2.0.html. 17 4 * 18 5 * Copyright (C) IBM Corporation, 2006 19 6 * Copyright (C) Fujitsu, 2012 20 7 * 21 - * Author: Paul McKenney <paulmck@us.ibm.com> 8 + * Author: Paul McKenney <paulmck@linux.ibm.com> 22 9 * Lai Jiangshan <laijs@cn.fujitsu.com> 23 10 * 24 11 * For detailed explanation of Read-Copy Update mechanism see - ··· 45 58 static void srcu_invoke_callbacks(struct work_struct *work); 46 59 static void srcu_reschedule(struct srcu_struct *ssp, unsigned long delay); 47 60 static void process_srcu(struct work_struct *work); 61 + static void srcu_delay_timer(struct timer_list *t); 48 62 49 63 /* Wrappers for lock acquisition and release, see raw_spin_lock_rcu_node(). */ 50 64 #define spin_lock_rcu_node(p) \ ··· 144 156 snp->grphi = cpu; 145 157 } 146 158 sdp->cpu = cpu; 147 - INIT_DELAYED_WORK(&sdp->work, srcu_invoke_callbacks); 159 + INIT_WORK(&sdp->work, srcu_invoke_callbacks); 160 + timer_setup(&sdp->delay_work, srcu_delay_timer, 0); 148 161 sdp->ssp = ssp; 149 162 sdp->grpmask = 1 << (cpu - sdp->mynode->grplo); 150 163 if (is_static) ··· 375 386 } else { 376 387 flush_delayed_work(&ssp->work); 377 388 } 378 - for_each_possible_cpu(cpu) 389 + for_each_possible_cpu(cpu) { 390 + struct srcu_data *sdp = per_cpu_ptr(ssp->sda, cpu); 391 + 379 392 if (quiesced) { 380 - if (WARN_ON(delayed_work_pending(&per_cpu_ptr(ssp->sda, cpu)->work))) 393 + if (WARN_ON(timer_pending(&sdp->delay_work))) 394 + return; /* Just leak it! */ 395 + if (WARN_ON(work_pending(&sdp->work))) 381 396 return; /* Just leak it! */ 382 397 } else { 383 - flush_delayed_work(&per_cpu_ptr(ssp->sda, cpu)->work); 398 + del_timer_sync(&sdp->delay_work); 399 + flush_work(&sdp->work); 384 400 } 401 + } 385 402 if (WARN_ON(rcu_seq_state(READ_ONCE(ssp->srcu_gp_seq)) != SRCU_STATE_IDLE) || 386 403 WARN_ON(srcu_readers_active(ssp))) { 387 404 pr_info("%s: Active srcu_struct %p state: %d\n", ··· 458 463 WARN_ON_ONCE(state != SRCU_STATE_SCAN1); 459 464 } 460 465 461 - /* 462 - * Track online CPUs to guide callback workqueue placement. 463 - */ 464 - DEFINE_PER_CPU(bool, srcu_online); 465 466 466 - void srcu_online_cpu(unsigned int cpu) 467 + static void srcu_delay_timer(struct timer_list *t) 467 468 { 468 - WRITE_ONCE(per_cpu(srcu_online, cpu), true); 469 + struct srcu_data *sdp = container_of(t, struct srcu_data, delay_work); 470 + 471 + queue_work_on(sdp->cpu, rcu_gp_wq, &sdp->work); 469 472 } 470 473 471 - void srcu_offline_cpu(unsigned int cpu) 472 - { 473 - WRITE_ONCE(per_cpu(srcu_online, cpu), false); 474 - } 475 - 476 - /* 477 - * Place the workqueue handler on the specified CPU if online, otherwise 478 - * just run it whereever. This is useful for placing workqueue handlers 479 - * that are to invoke the specified CPU's callbacks. 480 - */ 481 - static bool srcu_queue_delayed_work_on(int cpu, struct workqueue_struct *wq, 482 - struct delayed_work *dwork, 474 + static void srcu_queue_delayed_work_on(struct srcu_data *sdp, 483 475 unsigned long delay) 484 476 { 485 - bool ret; 477 + if (!delay) { 478 + queue_work_on(sdp->cpu, rcu_gp_wq, &sdp->work); 479 + return; 480 + } 486 481 487 - preempt_disable(); 488 - if (READ_ONCE(per_cpu(srcu_online, cpu))) 489 - ret = queue_delayed_work_on(cpu, wq, dwork, delay); 490 - else 491 - ret = queue_delayed_work(wq, dwork, delay); 492 - preempt_enable(); 493 - return ret; 482 + timer_reduce(&sdp->delay_work, jiffies + delay); 494 483 } 495 484 496 485 /* ··· 483 504 */ 484 505 static void srcu_schedule_cbs_sdp(struct srcu_data *sdp, unsigned long delay) 485 506 { 486 - srcu_queue_delayed_work_on(sdp->cpu, rcu_gp_wq, &sdp->work, delay); 507 + srcu_queue_delayed_work_on(sdp, delay); 487 508 } 488 509 489 510 /* ··· 1165 1186 struct srcu_data *sdp; 1166 1187 struct srcu_struct *ssp; 1167 1188 1168 - sdp = container_of(work, struct srcu_data, work.work); 1189 + sdp = container_of(work, struct srcu_data, work); 1190 + 1169 1191 ssp = sdp->ssp; 1170 1192 rcu_cblist_init(&ready_cbs); 1171 1193 spin_lock_irq_rcu_node(sdp);
+1 -14
kernel/rcu/sync.c
··· 1 + // SPDX-License-Identifier: GPL-2.0+ 1 2 /* 2 3 * RCU-based infrastructure for lightweight reader-writer locking 3 - * 4 - * This program is free software; you can redistribute it and/or modify 5 - * it under the terms of the GNU General Public License as published by 6 - * the Free Software Foundation; either version 2 of the License, or 7 - * (at your option) any later version. 8 - * 9 - * This program is distributed in the hope that it will be useful, 10 - * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 - * GNU General Public License for more details. 13 - * 14 - * You should have received a copy of the GNU General Public License 15 - * along with this program; if not, you can access it online at 16 - * http://www.gnu.org/licenses/gpl-2.0.html. 17 4 * 18 5 * Copyright (c) 2015, Red Hat, Inc. 19 6 *
+3 -16
kernel/rcu/tiny.c
··· 1 + // SPDX-License-Identifier: GPL-2.0+ 1 2 /* 2 3 * Read-Copy Update mechanism for mutual exclusion, the Bloatwatch edition. 3 4 * 4 - * This program is free software; you can redistribute it and/or modify 5 - * it under the terms of the GNU General Public License as published by 6 - * the Free Software Foundation; either version 2 of the License, or 7 - * (at your option) any later version. 8 - * 9 - * This program is distributed in the hope that it will be useful, 10 - * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 - * GNU General Public License for more details. 13 - * 14 - * You should have received a copy of the GNU General Public License 15 - * along with this program; if not, you can access it online at 16 - * http://www.gnu.org/licenses/gpl-2.0.html. 17 - * 18 5 * Copyright IBM Corporation, 2008 19 6 * 20 - * Author: Paul E. McKenney <paulmck@linux.vnet.ibm.com> 7 + * Author: Paul E. McKenney <paulmck@linux.ibm.com> 21 8 * 22 9 * For detailed explanation of Read-Copy Update mechanism see - 23 10 * Documentation/RCU ··· 63 76 * be called from hardirq context. It is normally called from the 64 77 * scheduling-clock interrupt. 65 78 */ 66 - void rcu_check_callbacks(int user) 79 + void rcu_sched_clock_irq(int user) 67 80 { 68 81 if (user) { 69 82 rcu_qs();
+162 -105
kernel/rcu/tree.c
··· 1 + // SPDX-License-Identifier: GPL-2.0+ 1 2 /* 2 3 * Read-Copy Update mechanism for mutual exclusion 3 - * 4 - * This program is free software; you can redistribute it and/or modify 5 - * it under the terms of the GNU General Public License as published by 6 - * the Free Software Foundation; either version 2 of the License, or 7 - * (at your option) any later version. 8 - * 9 - * This program is distributed in the hope that it will be useful, 10 - * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 - * GNU General Public License for more details. 13 - * 14 - * You should have received a copy of the GNU General Public License 15 - * along with this program; if not, you can access it online at 16 - * http://www.gnu.org/licenses/gpl-2.0.html. 17 4 * 18 5 * Copyright IBM Corporation, 2008 19 6 * 20 7 * Authors: Dipankar Sarma <dipankar@in.ibm.com> 21 8 * Manfred Spraul <manfred@colorfullife.com> 22 - * Paul E. McKenney <paulmck@linux.vnet.ibm.com> Hierarchical version 9 + * Paul E. McKenney <paulmck@linux.ibm.com> Hierarchical version 23 10 * 24 - * Based on the original work by Paul McKenney <paulmck@us.ibm.com> 11 + * Based on the original work by Paul McKenney <paulmck@linux.ibm.com> 25 12 * and inputs from Rusty Russell, Andrea Arcangeli and Andi Kleen. 26 13 * 27 14 * For detailed explanation of Read-Copy Update mechanism see - ··· 49 62 #include <linux/suspend.h> 50 63 #include <linux/ftrace.h> 51 64 #include <linux/tick.h> 65 + #include <linux/sysrq.h> 52 66 53 67 #include "tree.h" 54 68 #include "rcu.h" ··· 103 115 int rcu_num_nodes __read_mostly = NUM_RCU_NODES; /* Total # rcu_nodes in use. */ 104 116 /* panic() on RCU Stall sysctl. */ 105 117 int sysctl_panic_on_rcu_stall __read_mostly; 118 + /* Commandeer a sysrq key to dump RCU's tree. */ 119 + static bool sysrq_rcu; 120 + module_param(sysrq_rcu, bool, 0444); 106 121 107 122 /* 108 123 * The rcu_scheduler_active variable is initialized to the value ··· 470 479 module_param(rcu_kick_kthreads, bool, 0644); 471 480 472 481 static void force_qs_rnp(int (*f)(struct rcu_data *rdp)); 473 - static void force_quiescent_state(void); 474 482 static int rcu_pending(void); 475 483 476 484 /* ··· 494 504 EXPORT_SYMBOL_GPL(rcu_exp_batches_completed); 495 505 496 506 /* 497 - * Force a quiescent state. 507 + * Return the root node of the rcu_state structure. 498 508 */ 499 - void rcu_force_quiescent_state(void) 509 + static struct rcu_node *rcu_get_root(void) 500 510 { 501 - force_quiescent_state(); 511 + return &rcu_state.node[0]; 502 512 } 503 - EXPORT_SYMBOL_GPL(rcu_force_quiescent_state); 504 513 505 514 /* 506 515 * Convert a ->gp_state value to a character string. ··· 518 529 { 519 530 int cpu; 520 531 unsigned long j; 532 + unsigned long ja; 533 + unsigned long jr; 534 + unsigned long jw; 521 535 struct rcu_data *rdp; 522 536 struct rcu_node *rnp; 523 537 524 - j = jiffies - READ_ONCE(rcu_state.gp_activity); 525 - pr_info("%s: wait state: %s(%d) ->state: %#lx delta ->gp_activity %ld\n", 538 + j = jiffies; 539 + ja = j - READ_ONCE(rcu_state.gp_activity); 540 + jr = j - READ_ONCE(rcu_state.gp_req_activity); 541 + jw = j - READ_ONCE(rcu_state.gp_wake_time); 542 + pr_info("%s: wait state: %s(%d) ->state: %#lx delta ->gp_activity %lu ->gp_req_activity %lu ->gp_wake_time %lu ->gp_wake_seq %ld ->gp_seq %ld ->gp_seq_needed %ld ->gp_flags %#x\n", 526 543 rcu_state.name, gp_state_getname(rcu_state.gp_state), 527 - rcu_state.gp_state, rcu_state.gp_kthread->state, j); 544 + rcu_state.gp_state, 545 + rcu_state.gp_kthread ? rcu_state.gp_kthread->state : 0x1ffffL, 546 + ja, jr, jw, (long)READ_ONCE(rcu_state.gp_wake_seq), 547 + (long)READ_ONCE(rcu_state.gp_seq), 548 + (long)READ_ONCE(rcu_get_root()->gp_seq_needed), 549 + READ_ONCE(rcu_state.gp_flags)); 528 550 rcu_for_each_node_breadth_first(rnp) { 529 551 if (ULONG_CMP_GE(rcu_state.gp_seq, rnp->gp_seq_needed)) 530 552 continue; 531 - pr_info("\trcu_node %d:%d ->gp_seq %lu ->gp_seq_needed %lu\n", 532 - rnp->grplo, rnp->grphi, rnp->gp_seq, 533 - rnp->gp_seq_needed); 553 + pr_info("\trcu_node %d:%d ->gp_seq %ld ->gp_seq_needed %ld\n", 554 + rnp->grplo, rnp->grphi, (long)rnp->gp_seq, 555 + (long)rnp->gp_seq_needed); 534 556 if (!rcu_is_leaf_node(rnp)) 535 557 continue; 536 558 for_each_leaf_node_possible_cpu(rnp, cpu) { ··· 550 550 ULONG_CMP_GE(rcu_state.gp_seq, 551 551 rdp->gp_seq_needed)) 552 552 continue; 553 - pr_info("\tcpu %d ->gp_seq_needed %lu\n", 554 - cpu, rdp->gp_seq_needed); 553 + pr_info("\tcpu %d ->gp_seq_needed %ld\n", 554 + cpu, (long)rdp->gp_seq_needed); 555 555 } 556 556 } 557 557 /* sched_show_task(rcu_state.gp_kthread); */ 558 558 } 559 559 EXPORT_SYMBOL_GPL(show_rcu_gp_kthreads); 560 + 561 + /* Dump grace-period-request information due to commandeered sysrq. */ 562 + static void sysrq_show_rcu(int key) 563 + { 564 + show_rcu_gp_kthreads(); 565 + } 566 + 567 + static struct sysrq_key_op sysrq_rcudump_op = { 568 + .handler = sysrq_show_rcu, 569 + .help_msg = "show-rcu(y)", 570 + .action_msg = "Show RCU tree", 571 + .enable_mask = SYSRQ_ENABLE_DUMP, 572 + }; 573 + 574 + static int __init rcu_sysrq_init(void) 575 + { 576 + if (sysrq_rcu) 577 + return register_sysrq_key('y', &sysrq_rcudump_op); 578 + return 0; 579 + } 580 + early_initcall(rcu_sysrq_init); 560 581 561 582 /* 562 583 * Send along grace-period-related data for rcutorture diagnostics. ··· 587 566 { 588 567 switch (test_type) { 589 568 case RCU_FLAVOR: 590 - case RCU_BH_FLAVOR: 591 - case RCU_SCHED_FLAVOR: 592 569 *flags = READ_ONCE(rcu_state.gp_flags); 593 570 *gp_seq = rcu_seq_current(&rcu_state.gp_seq); 594 571 break; ··· 595 576 } 596 577 } 597 578 EXPORT_SYMBOL_GPL(rcutorture_get_gp_data); 598 - 599 - /* 600 - * Return the root node of the rcu_state structure. 601 - */ 602 - static struct rcu_node *rcu_get_root(void) 603 - { 604 - return &rcu_state.node[0]; 605 - } 606 579 607 580 /* 608 581 * Enter an RCU extended quiescent state, which can be either the ··· 712 701 713 702 /** 714 703 * rcu_nmi_exit - inform RCU of exit from NMI context 715 - * @irq: Is this call from rcu_irq_exit? 716 704 * 717 705 * If you add or remove a call to rcu_nmi_exit(), be sure to test 718 706 * with CONFIG_RCU_EQS_DEBUG=y. ··· 1125 1115 } 1126 1116 1127 1117 /* 1128 - * NO_HZ_FULL CPUs can run in-kernel without rcu_check_callbacks! 1118 + * NO_HZ_FULL CPUs can run in-kernel without rcu_sched_clock_irq! 1129 1119 * The above code handles this, but only for straight cond_resched(). 1130 1120 * And some in-kernel loops check need_resched() before calling 1131 1121 * cond_resched(), which defeats the above code for CPUs that are ··· 1191 1181 pr_err("%s kthread starved for %ld jiffies! g%ld f%#x %s(%d) ->state=%#lx ->cpu=%d\n", 1192 1182 rcu_state.name, j, 1193 1183 (long)rcu_seq_current(&rcu_state.gp_seq), 1194 - rcu_state.gp_flags, 1184 + READ_ONCE(rcu_state.gp_flags), 1195 1185 gp_state_getname(rcu_state.gp_state), rcu_state.gp_state, 1196 1186 gpk ? gpk->state : ~0, gpk ? task_cpu(gpk) : -1); 1197 1187 if (gpk) { ··· 1320 1310 1321 1311 panic_on_rcu_stall(); 1322 1312 1323 - force_quiescent_state(); /* Kick them all. */ 1313 + rcu_force_quiescent_state(); /* Kick them all. */ 1324 1314 } 1325 1315 1326 1316 static void print_cpu_stall(void) ··· 1567 1557 } 1568 1558 1569 1559 /* 1570 - * Awaken the grace-period kthread. Don't do a self-awaken, and don't 1571 - * bother awakening when there is nothing for the grace-period kthread 1572 - * to do (as in several CPUs raced to awaken, and we lost), and finally 1573 - * don't try to awaken a kthread that has not yet been created. 1560 + * Awaken the grace-period kthread. Don't do a self-awaken (unless in 1561 + * an interrupt or softirq handler), and don't bother awakening when there 1562 + * is nothing for the grace-period kthread to do (as in several CPUs raced 1563 + * to awaken, and we lost), and finally don't try to awaken a kthread that 1564 + * has not yet been created. If all those checks are passed, track some 1565 + * debug information and awaken. 1566 + * 1567 + * So why do the self-wakeup when in an interrupt or softirq handler 1568 + * in the grace-period kthread's context? Because the kthread might have 1569 + * been interrupted just as it was going to sleep, and just after the final 1570 + * pre-sleep check of the awaken condition. In this case, a wakeup really 1571 + * is required, and is therefore supplied. 1574 1572 */ 1575 1573 static void rcu_gp_kthread_wake(void) 1576 1574 { 1577 - if (current == rcu_state.gp_kthread || 1575 + if ((current == rcu_state.gp_kthread && 1576 + !in_interrupt() && !in_serving_softirq()) || 1578 1577 !READ_ONCE(rcu_state.gp_flags) || 1579 1578 !rcu_state.gp_kthread) 1580 1579 return; 1580 + WRITE_ONCE(rcu_state.gp_wake_time, jiffies); 1581 + WRITE_ONCE(rcu_state.gp_wake_seq, READ_ONCE(rcu_state.gp_seq)); 1581 1582 swake_up_one(&rcu_state.gp_wq); 1582 1583 } 1583 1584 ··· 1732 1711 zero_cpu_stall_ticks(rdp); 1733 1712 } 1734 1713 rdp->gp_seq = rnp->gp_seq; /* Remember new grace-period state. */ 1735 - if (ULONG_CMP_GE(rnp->gp_seq_needed, rdp->gp_seq_needed) || rdp->gpwrap) 1714 + if (ULONG_CMP_LT(rdp->gp_seq_needed, rnp->gp_seq_needed) || rdp->gpwrap) 1736 1715 rdp->gp_seq_needed = rnp->gp_seq_needed; 1737 1716 WRITE_ONCE(rdp->gpwrap, false); 1738 1717 rcu_gpnum_ovf(rnp, rdp); ··· 1960 1939 if (!ret) { 1961 1940 rcu_state.jiffies_force_qs = jiffies + j; 1962 1941 WRITE_ONCE(rcu_state.jiffies_kick_kthreads, 1963 - jiffies + 3 * j); 1942 + jiffies + (j ? 3 * j : 2)); 1964 1943 } 1965 1944 trace_rcu_grace_period(rcu_state.name, 1966 1945 READ_ONCE(rcu_state.gp_seq), ··· 2518 2497 } 2519 2498 2520 2499 /* 2521 - * Check to see if this CPU is in a non-context-switch quiescent state 2522 - * (user mode or idle loop for rcu, non-softirq execution for rcu_bh). 2523 - * Also schedule RCU core processing. 2524 - * 2525 - * This function must be called from hardirq context. It is normally 2526 - * invoked from the scheduling-clock interrupt. 2500 + * This function is invoked from each scheduling-clock interrupt, 2501 + * and checks to see if this CPU is in a non-context-switch quiescent 2502 + * state, for example, user mode or idle loop. It also schedules RCU 2503 + * core processing. If the current grace period has gone on too long, 2504 + * it will ask the scheduler to manufacture a context switch for the sole 2505 + * purpose of providing a providing the needed quiescent state. 2527 2506 */ 2528 - void rcu_check_callbacks(int user) 2507 + void rcu_sched_clock_irq(int user) 2529 2508 { 2530 2509 trace_rcu_utilization(TPS("Start scheduler-tick")); 2531 2510 raw_cpu_inc(rcu_data.ticks_this_gp); ··· 2538 2517 } 2539 2518 __this_cpu_write(rcu_data.rcu_urgent_qs, false); 2540 2519 } 2541 - rcu_flavor_check_callbacks(user); 2520 + rcu_flavor_sched_clock_irq(user); 2542 2521 if (rcu_pending()) 2543 2522 invoke_rcu_core(); 2544 2523 ··· 2599 2578 * Force quiescent states on reluctant CPUs, and also detect which 2600 2579 * CPUs are in dyntick-idle mode. 2601 2580 */ 2602 - static void force_quiescent_state(void) 2581 + void rcu_force_quiescent_state(void) 2603 2582 { 2604 2583 unsigned long flags; 2605 2584 bool ret; ··· 2631 2610 raw_spin_unlock_irqrestore_rcu_node(rnp_old, flags); 2632 2611 rcu_gp_kthread_wake(); 2633 2612 } 2613 + EXPORT_SYMBOL_GPL(rcu_force_quiescent_state); 2634 2614 2635 2615 /* 2636 2616 * This function checks for grace-period requests that fail to motivate ··· 2679 2657 raw_spin_unlock_irqrestore_rcu_node(rnp, flags); 2680 2658 return; 2681 2659 } 2682 - pr_alert("%s: g%ld->%ld gar:%lu ga:%lu f%#x gs:%d %s->state:%#lx\n", 2683 - __func__, (long)READ_ONCE(rcu_state.gp_seq), 2684 - (long)READ_ONCE(rnp_root->gp_seq_needed), 2685 - j - rcu_state.gp_req_activity, j - rcu_state.gp_activity, 2686 - rcu_state.gp_flags, rcu_state.gp_state, rcu_state.name, 2687 - rcu_state.gp_kthread ? rcu_state.gp_kthread->state : 0x1ffffL); 2688 2660 WARN_ON(1); 2689 2661 if (rnp_root != rnp) 2690 2662 raw_spin_unlock_rcu_node(rnp_root); 2691 2663 raw_spin_unlock_irqrestore_rcu_node(rnp, flags); 2664 + show_rcu_gp_kthreads(); 2692 2665 } 2693 2666 2694 2667 /* ··· 2728 2711 } 2729 2712 EXPORT_SYMBOL_GPL(rcu_fwd_progress_check); 2730 2713 2731 - /* 2732 - * This does the RCU core processing work for the specified rcu_data 2733 - * structures. This may be called only from the CPU to whom the rdp 2734 - * belongs. 2735 - */ 2736 - static __latent_entropy void rcu_process_callbacks(struct softirq_action *unused) 2714 + /* Perform RCU core processing work for the current CPU. */ 2715 + static __latent_entropy void rcu_core(struct softirq_action *unused) 2737 2716 { 2738 2717 unsigned long flags; 2739 2718 struct rcu_data *rdp = raw_cpu_ptr(&rcu_data); ··· 2814 2801 2815 2802 /* 2816 2803 * Force the grace period if too many callbacks or too long waiting. 2817 - * Enforce hysteresis, and don't invoke force_quiescent_state() 2804 + * Enforce hysteresis, and don't invoke rcu_force_quiescent_state() 2818 2805 * if some other CPU has recently done so. Also, don't bother 2819 - * invoking force_quiescent_state() if the newly enqueued callback 2806 + * invoking rcu_force_quiescent_state() if the newly enqueued callback 2820 2807 * is the only one waiting for a grace period to complete. 2821 2808 */ 2822 2809 if (unlikely(rcu_segcblist_n_cbs(&rdp->cblist) > ··· 2833 2820 rdp->blimit = LONG_MAX; 2834 2821 if (rcu_state.n_force_qs == rdp->n_force_qs_snap && 2835 2822 rcu_segcblist_first_pend_cb(&rdp->cblist) != head) 2836 - force_quiescent_state(); 2823 + rcu_force_quiescent_state(); 2837 2824 rdp->n_force_qs_snap = rcu_state.n_force_qs; 2838 2825 rdp->qlen_last_fqs_check = rcu_segcblist_n_cbs(&rdp->cblist); 2839 2826 } ··· 2902 2889 rcu_segcblist_init(&rdp->cblist); 2903 2890 } 2904 2891 rcu_segcblist_enqueue(&rdp->cblist, head, lazy); 2905 - if (!lazy) 2906 - rcu_idle_count_callbacks_posted(); 2907 - 2908 2892 if (__is_kfree_rcu_offset((unsigned long)func)) 2909 2893 trace_rcu_kfree_callback(rcu_state.name, head, 2910 2894 (unsigned long)func, ··· 2970 2960 __call_rcu(head, func, -1, 1); 2971 2961 } 2972 2962 EXPORT_SYMBOL_GPL(kfree_call_rcu); 2963 + 2964 + /* 2965 + * During early boot, any blocking grace-period wait automatically 2966 + * implies a grace period. Later on, this is never the case for PREEMPT. 2967 + * 2968 + * Howevr, because a context switch is a grace period for !PREEMPT, any 2969 + * blocking grace-period wait automatically implies a grace period if 2970 + * there is only one CPU online at any point time during execution of 2971 + * either synchronize_rcu() or synchronize_rcu_expedited(). It is OK to 2972 + * occasionally incorrectly indicate that there are multiple CPUs online 2973 + * when there was in fact only one the whole time, as this just adds some 2974 + * overhead: RCU still operates correctly. 2975 + */ 2976 + static int rcu_blocking_is_gp(void) 2977 + { 2978 + int ret; 2979 + 2980 + if (IS_ENABLED(CONFIG_PREEMPT)) 2981 + return rcu_scheduler_active == RCU_SCHEDULER_INACTIVE; 2982 + might_sleep(); /* Check for RCU read-side critical section. */ 2983 + preempt_disable(); 2984 + ret = num_online_cpus() <= 1; 2985 + preempt_enable(); 2986 + return ret; 2987 + } 2988 + 2989 + /** 2990 + * synchronize_rcu - wait until a grace period has elapsed. 2991 + * 2992 + * Control will return to the caller some time after a full grace 2993 + * period has elapsed, in other words after all currently executing RCU 2994 + * read-side critical sections have completed. Note, however, that 2995 + * upon return from synchronize_rcu(), the caller might well be executing 2996 + * concurrently with new RCU read-side critical sections that began while 2997 + * synchronize_rcu() was waiting. RCU read-side critical sections are 2998 + * delimited by rcu_read_lock() and rcu_read_unlock(), and may be nested. 2999 + * In addition, regions of code across which interrupts, preemption, or 3000 + * softirqs have been disabled also serve as RCU read-side critical 3001 + * sections. This includes hardware interrupt handlers, softirq handlers, 3002 + * and NMI handlers. 3003 + * 3004 + * Note that this guarantee implies further memory-ordering guarantees. 3005 + * On systems with more than one CPU, when synchronize_rcu() returns, 3006 + * each CPU is guaranteed to have executed a full memory barrier since 3007 + * the end of its last RCU read-side critical section whose beginning 3008 + * preceded the call to synchronize_rcu(). In addition, each CPU having 3009 + * an RCU read-side critical section that extends beyond the return from 3010 + * synchronize_rcu() is guaranteed to have executed a full memory barrier 3011 + * after the beginning of synchronize_rcu() and before the beginning of 3012 + * that RCU read-side critical section. Note that these guarantees include 3013 + * CPUs that are offline, idle, or executing in user mode, as well as CPUs 3014 + * that are executing in the kernel. 3015 + * 3016 + * Furthermore, if CPU A invoked synchronize_rcu(), which returned 3017 + * to its caller on CPU B, then both CPU A and CPU B are guaranteed 3018 + * to have executed a full memory barrier during the execution of 3019 + * synchronize_rcu() -- even if CPU A and CPU B are the same CPU (but 3020 + * again only if the system has more than one CPU). 3021 + */ 3022 + void synchronize_rcu(void) 3023 + { 3024 + RCU_LOCKDEP_WARN(lock_is_held(&rcu_bh_lock_map) || 3025 + lock_is_held(&rcu_lock_map) || 3026 + lock_is_held(&rcu_sched_lock_map), 3027 + "Illegal synchronize_rcu() in RCU read-side critical section"); 3028 + if (rcu_blocking_is_gp()) 3029 + return; 3030 + if (rcu_gp_is_expedited()) 3031 + synchronize_rcu_expedited(); 3032 + else 3033 + wait_rcu_gp(call_rcu); 3034 + } 3035 + EXPORT_SYMBOL_GPL(synchronize_rcu); 2973 3036 2974 3037 /** 2975 3038 * get_state_synchronize_rcu - Snapshot current RCU state ··· 3129 3046 3130 3047 /* nothing to do */ 3131 3048 return 0; 3132 - } 3133 - 3134 - /* 3135 - * Return true if the specified CPU has any callback. If all_lazy is 3136 - * non-NULL, store an indication of whether all callbacks are lazy. 3137 - * (If there are no callbacks, all of them are deemed to be lazy.) 3138 - */ 3139 - static bool rcu_cpu_has_callbacks(bool *all_lazy) 3140 - { 3141 - bool al = true; 3142 - bool hc = false; 3143 - struct rcu_data *rdp; 3144 - 3145 - rdp = this_cpu_ptr(&rcu_data); 3146 - if (!rcu_segcblist_empty(&rdp->cblist)) { 3147 - hc = true; 3148 - if (rcu_segcblist_n_nonlazy_cbs(&rdp->cblist)) 3149 - al = false; 3150 - } 3151 - if (all_lazy) 3152 - *all_lazy = al; 3153 - return hc; 3154 3049 } 3155 3050 3156 3051 /* ··· 3360 3299 trace_rcu_grace_period(rcu_state.name, rdp->gp_seq, TPS("cpuonl")); 3361 3300 raw_spin_unlock_irqrestore_rcu_node(rnp, flags); 3362 3301 rcu_prepare_kthreads(cpu); 3363 - rcu_spawn_all_nocb_kthreads(cpu); 3302 + rcu_spawn_cpu_nocb_kthread(cpu); 3364 3303 3365 3304 return 0; 3366 3305 } ··· 3390 3329 raw_spin_lock_irqsave_rcu_node(rnp, flags); 3391 3330 rnp->ffmask |= rdp->grpmask; 3392 3331 raw_spin_unlock_irqrestore_rcu_node(rnp, flags); 3393 - if (IS_ENABLED(CONFIG_TREE_SRCU)) 3394 - srcu_online_cpu(cpu); 3395 3332 if (rcu_scheduler_active == RCU_SCHEDULER_INACTIVE) 3396 3333 return 0; /* Too early in boot for scheduler work. */ 3397 3334 sync_sched_exp_online_cleanup(cpu); ··· 3414 3355 raw_spin_unlock_irqrestore_rcu_node(rnp, flags); 3415 3356 3416 3357 rcutree_affinity_setting(cpu, cpu); 3417 - if (IS_ENABLED(CONFIG_TREE_SRCU)) 3418 - srcu_offline_cpu(cpu); 3419 3358 return 0; 3420 3359 } 3421 3360 ··· 3834 3777 rcu_init_one(); 3835 3778 if (dump_tree) 3836 3779 rcu_dump_rcu_node_tree(); 3837 - open_softirq(RCU_SOFTIRQ, rcu_process_callbacks); 3780 + open_softirq(RCU_SOFTIRQ, rcu_core); 3838 3781 3839 3782 /* 3840 3783 * We don't need protection against CPU-hotplug here because
+14 -39
kernel/rcu/tree.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0+ */ 1 2 /* 2 3 * Read-Copy Update mechanism for mutual exclusion (tree-based version) 3 4 * Internal non-public definitions. 4 5 * 5 - * This program is free software; you can redistribute it and/or modify 6 - * it under the terms of the GNU General Public License as published by 7 - * the Free Software Foundation; either version 2 of the License, or 8 - * (at your option) any later version. 9 - * 10 - * This program is distributed in the hope that it will be useful, 11 - * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 - * GNU General Public License for more details. 14 - * 15 - * You should have received a copy of the GNU General Public License 16 - * along with this program; if not, you can access it online at 17 - * http://www.gnu.org/licenses/gpl-2.0.html. 18 - * 19 6 * Copyright IBM Corporation, 2008 20 7 * 21 8 * Author: Ingo Molnar <mingo@elte.hu> 22 - * Paul E. McKenney <paulmck@linux.vnet.ibm.com> 9 + * Paul E. McKenney <paulmck@linux.ibm.com> 23 10 */ 24 11 25 12 #include <linux/cache.h> ··· 23 36 24 37 /* Communicate arguments to a workqueue handler. */ 25 38 struct rcu_exp_work { 26 - smp_call_func_t rew_func; 27 39 unsigned long rew_s; 28 40 struct work_struct rew_work; 29 41 }; ··· 180 194 bool rcu_need_heavy_qs; /* GP old, so heavy quiescent state! */ 181 195 bool rcu_urgent_qs; /* GP old need light quiescent state. */ 182 196 #ifdef CONFIG_RCU_FAST_NO_HZ 183 - bool all_lazy; /* Are all CPU's CBs lazy? */ 184 - unsigned long nonlazy_posted; /* # times non-lazy CB posted to CPU. */ 185 - unsigned long nonlazy_posted_snap; 186 - /* Nonlazy_posted snapshot. */ 197 + bool all_lazy; /* All CPU's CBs lazy at idle start? */ 187 198 unsigned long last_accelerate; /* Last jiffy CBs were accelerated. */ 188 199 unsigned long last_advance_all; /* Last jiffy CBs were all advanced. */ 189 200 int tick_nohz_enabled_snap; /* Previously seen value from sysfs. */ ··· 217 234 /* Leader CPU takes GP-end wakeups. */ 218 235 #endif /* #ifdef CONFIG_RCU_NOCB_CPU */ 219 236 220 - /* 6) Diagnostic data, including RCU CPU stall warnings. */ 237 + /* 6) RCU priority boosting. */ 238 + struct task_struct *rcu_cpu_kthread_task; 239 + /* rcuc per-CPU kthread or NULL. */ 240 + unsigned int rcu_cpu_kthread_status; 241 + char rcu_cpu_has_work; 242 + 243 + /* 7) Diagnostic data, including RCU CPU stall warnings. */ 221 244 unsigned int softirq_snap; /* Snapshot of softirq activity. */ 222 245 /* ->rcu_iw* fields protected by leaf rcu_node ->lock. */ 223 246 struct irq_work rcu_iw; /* Check for non-irq activity. */ ··· 292 303 struct swait_queue_head gp_wq; /* Where GP task waits. */ 293 304 short gp_flags; /* Commands for GP task. */ 294 305 short gp_state; /* GP kthread sleep state. */ 306 + unsigned long gp_wake_time; /* Last GP kthread wake. */ 307 + unsigned long gp_wake_seq; /* ->gp_seq at ^^^. */ 295 308 296 309 /* End of fields guarded by root rcu_node's lock. */ 297 310 ··· 393 402 394 403 int rcu_dynticks_snap(struct rcu_data *rdp); 395 404 396 - #ifdef CONFIG_RCU_BOOST 397 - DECLARE_PER_CPU(unsigned int, rcu_cpu_kthread_status); 398 - DECLARE_PER_CPU(int, rcu_cpu_kthread_cpu); 399 - DECLARE_PER_CPU(unsigned int, rcu_cpu_kthread_loops); 400 - DECLARE_PER_CPU(char, rcu_cpu_has_work); 401 - #endif /* #ifdef CONFIG_RCU_BOOST */ 402 - 403 405 /* Forward declarations for rcutree_plugin.h */ 404 406 static void rcu_bootup_announce(void); 405 407 static void rcu_qs(void); ··· 404 420 static int rcu_print_task_stall(struct rcu_node *rnp); 405 421 static int rcu_print_task_exp_stall(struct rcu_node *rnp); 406 422 static void rcu_preempt_check_blocked_tasks(struct rcu_node *rnp); 407 - static void rcu_flavor_check_callbacks(int user); 423 + static void rcu_flavor_sched_clock_irq(int user); 408 424 void call_rcu(struct rcu_head *head, rcu_callback_t func); 409 425 static void dump_blkd_tasks(struct rcu_node *rnp, int ncheck); 410 426 static void rcu_initiate_boost(struct rcu_node *rnp, unsigned long flags); ··· 415 431 static void rcu_prepare_kthreads(int cpu); 416 432 static void rcu_cleanup_after_idle(void); 417 433 static void rcu_prepare_for_idle(void); 418 - static void rcu_idle_count_callbacks_posted(void); 419 434 static bool rcu_preempt_has_tasks(struct rcu_node *rnp); 420 435 static bool rcu_preempt_need_deferred_qs(struct task_struct *t); 421 436 static void rcu_preempt_deferred_qs(struct task_struct *t); ··· 434 451 static int rcu_nocb_need_deferred_wakeup(struct rcu_data *rdp); 435 452 static void do_nocb_deferred_wakeup(struct rcu_data *rdp); 436 453 static void rcu_boot_init_nocb_percpu_data(struct rcu_data *rdp); 437 - static void rcu_spawn_all_nocb_kthreads(int cpu); 454 + static void rcu_spawn_cpu_nocb_kthread(int cpu); 438 455 static void __init rcu_spawn_nocb_kthreads(void); 439 456 #ifdef CONFIG_RCU_NOCB_CPU 440 457 static void __init rcu_organize_nocb_kthreads(void); ··· 445 462 static bool rcu_nohz_full_cpu(void); 446 463 static void rcu_dynticks_task_enter(void); 447 464 static void rcu_dynticks_task_exit(void); 448 - 449 - #ifdef CONFIG_SRCU 450 - void srcu_online_cpu(unsigned int cpu); 451 - void srcu_offline_cpu(unsigned int cpu); 452 - #else /* #ifdef CONFIG_SRCU */ 453 - void srcu_online_cpu(unsigned int cpu) { } 454 - void srcu_offline_cpu(unsigned int cpu) { } 455 - #endif /* #else #ifdef CONFIG_SRCU */
+71 -130
kernel/rcu/tree_exp.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0+ */ 1 2 /* 2 3 * RCU expedited grace periods 3 4 * 4 - * This program is free software; you can redistribute it and/or modify 5 - * it under the terms of the GNU General Public License as published by 6 - * the Free Software Foundation; either version 2 of the License, or 7 - * (at your option) any later version. 8 - * 9 - * This program is distributed in the hope that it will be useful, 10 - * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 - * GNU General Public License for more details. 13 - * 14 - * You should have received a copy of the GNU General Public License 15 - * along with this program; if not, you can access it online at 16 - * http://www.gnu.org/licenses/gpl-2.0.html. 17 - * 18 5 * Copyright IBM Corporation, 2016 19 6 * 20 - * Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com> 7 + * Authors: Paul E. McKenney <paulmck@linux.ibm.com> 21 8 */ 22 9 23 10 #include <linux/lockdep.h> 11 + 12 + static void rcu_exp_handler(void *unused); 24 13 25 14 /* 26 15 * Record the start of an expedited grace period. ··· 333 344 { 334 345 int cpu; 335 346 unsigned long flags; 336 - smp_call_func_t func; 337 347 unsigned long mask_ofl_test; 338 348 unsigned long mask_ofl_ipi; 339 349 int ret; ··· 340 352 container_of(wp, struct rcu_exp_work, rew_work); 341 353 struct rcu_node *rnp = container_of(rewp, struct rcu_node, rew); 342 354 343 - func = rewp->rew_func; 344 355 raw_spin_lock_irqsave_rcu_node(rnp, flags); 345 356 346 357 /* Each pass checks a CPU for identity, offline, and idle. */ ··· 383 396 mask_ofl_test |= mask; 384 397 continue; 385 398 } 386 - ret = smp_call_function_single(cpu, func, NULL, 0); 399 + ret = smp_call_function_single(cpu, rcu_exp_handler, NULL, 0); 387 400 if (!ret) { 388 401 mask_ofl_ipi &= ~mask; 389 402 continue; ··· 413 426 * Select the nodes that the upcoming expedited grace period needs 414 427 * to wait for. 415 428 */ 416 - static void sync_rcu_exp_select_cpus(smp_call_func_t func) 429 + static void sync_rcu_exp_select_cpus(void) 417 430 { 418 431 int cpu; 419 432 struct rcu_node *rnp; ··· 427 440 rnp->exp_need_flush = false; 428 441 if (!READ_ONCE(rnp->expmask)) 429 442 continue; /* Avoid early boot non-existent wq. */ 430 - rnp->rew.rew_func = func; 431 443 if (!READ_ONCE(rcu_par_gp_wq) || 432 444 rcu_scheduler_active != RCU_SCHEDULER_RUNNING || 433 445 rcu_is_last_leaf_node(rnp)) { ··· 435 449 continue; 436 450 } 437 451 INIT_WORK(&rnp->rew.rew_work, sync_rcu_exp_select_node_cpus); 438 - preempt_disable(); 439 452 cpu = find_next_bit(&rnp->ffmask, BITS_PER_LONG, -1); 440 453 /* If all offline, queue the work on an unbound CPU. */ 441 454 if (unlikely(cpu > rnp->grphi - rnp->grplo)) ··· 442 457 else 443 458 cpu += rnp->grplo; 444 459 queue_work_on(cpu, rcu_par_gp_wq, &rnp->rew.rew_work); 445 - preempt_enable(); 446 460 rnp->exp_need_flush = true; 447 461 } 448 462 ··· 564 580 * Common code to drive an expedited grace period forward, used by 565 581 * workqueues and mid-boot-time tasks. 566 582 */ 567 - static void rcu_exp_sel_wait_wake(smp_call_func_t func, unsigned long s) 583 + static void rcu_exp_sel_wait_wake(unsigned long s) 568 584 { 569 585 /* Initialize the rcu_node tree in preparation for the wait. */ 570 - sync_rcu_exp_select_cpus(func); 586 + sync_rcu_exp_select_cpus(); 571 587 572 588 /* Wait and clean up, including waking everyone. */ 573 589 rcu_exp_wait_wake(s); ··· 581 597 struct rcu_exp_work *rewp; 582 598 583 599 rewp = container_of(wp, struct rcu_exp_work, rew_work); 584 - rcu_exp_sel_wait_wake(rewp->rew_func, rewp->rew_s); 585 - } 586 - 587 - /* 588 - * Given a smp_call_function() handler, kick off the specified 589 - * implementation of expedited grace period. 590 - */ 591 - static void _synchronize_rcu_expedited(smp_call_func_t func) 592 - { 593 - struct rcu_data *rdp; 594 - struct rcu_exp_work rew; 595 - struct rcu_node *rnp; 596 - unsigned long s; 597 - 598 - /* If expedited grace periods are prohibited, fall back to normal. */ 599 - if (rcu_gp_is_normal()) { 600 - wait_rcu_gp(call_rcu); 601 - return; 602 - } 603 - 604 - /* Take a snapshot of the sequence number. */ 605 - s = rcu_exp_gp_seq_snap(); 606 - if (exp_funnel_lock(s)) 607 - return; /* Someone else did our work for us. */ 608 - 609 - /* Ensure that load happens before action based on it. */ 610 - if (unlikely(rcu_scheduler_active == RCU_SCHEDULER_INIT)) { 611 - /* Direct call during scheduler init and early_initcalls(). */ 612 - rcu_exp_sel_wait_wake(func, s); 613 - } else { 614 - /* Marshall arguments & schedule the expedited grace period. */ 615 - rew.rew_func = func; 616 - rew.rew_s = s; 617 - INIT_WORK_ONSTACK(&rew.rew_work, wait_rcu_exp_gp); 618 - queue_work(rcu_gp_wq, &rew.rew_work); 619 - } 620 - 621 - /* Wait for expedited grace period to complete. */ 622 - rdp = per_cpu_ptr(&rcu_data, raw_smp_processor_id()); 623 - rnp = rcu_get_root(); 624 - wait_event(rnp->exp_wq[rcu_seq_ctr(s) & 0x3], 625 - sync_exp_work_done(s)); 626 - smp_mb(); /* Workqueue actions happen before return. */ 627 - 628 - /* Let the next expedited grace period start. */ 629 - mutex_unlock(&rcu_state.exp_mutex); 600 + rcu_exp_sel_wait_wake(rewp->rew_s); 630 601 } 631 602 632 603 #ifdef CONFIG_PREEMPT_RCU ··· 593 654 * ->expmask fields in the rcu_node tree. Otherwise, immediately 594 655 * report the quiescent state. 595 656 */ 596 - static void sync_rcu_exp_handler(void *unused) 657 + static void rcu_exp_handler(void *unused) 597 658 { 598 659 unsigned long flags; 599 660 struct rcu_data *rdp = this_cpu_ptr(&rcu_data); ··· 636 697 WRITE_ONCE(t->rcu_read_unlock_special.b.exp_hint, true); 637 698 } 638 699 raw_spin_unlock_irqrestore_rcu_node(rnp, flags); 700 + return; 639 701 } 640 702 641 703 /* ··· 670 730 { 671 731 } 672 732 673 - /** 674 - * synchronize_rcu_expedited - Brute-force RCU grace period 675 - * 676 - * Wait for an RCU-preempt grace period, but expedite it. The basic 677 - * idea is to IPI all non-idle non-nohz online CPUs. The IPI handler 678 - * checks whether the CPU is in an RCU-preempt critical section, and 679 - * if so, it sets a flag that causes the outermost rcu_read_unlock() 680 - * to report the quiescent state. On the other hand, if the CPU is 681 - * not in an RCU read-side critical section, the IPI handler reports 682 - * the quiescent state immediately. 683 - * 684 - * Although this is a greate improvement over previous expedited 685 - * implementations, it is still unfriendly to real-time workloads, so is 686 - * thus not recommended for any sort of common-case code. In fact, if 687 - * you are using synchronize_rcu_expedited() in a loop, please restructure 688 - * your code to batch your updates, and then Use a single synchronize_rcu() 689 - * instead. 690 - * 691 - * This has the same semantics as (but is more brutal than) synchronize_rcu(). 692 - */ 693 - void synchronize_rcu_expedited(void) 694 - { 695 - RCU_LOCKDEP_WARN(lock_is_held(&rcu_bh_lock_map) || 696 - lock_is_held(&rcu_lock_map) || 697 - lock_is_held(&rcu_sched_lock_map), 698 - "Illegal synchronize_rcu_expedited() in RCU read-side critical section"); 699 - 700 - if (rcu_scheduler_active == RCU_SCHEDULER_INACTIVE) 701 - return; 702 - _synchronize_rcu_expedited(sync_rcu_exp_handler); 703 - } 704 - EXPORT_SYMBOL_GPL(synchronize_rcu_expedited); 705 - 706 733 #else /* #ifdef CONFIG_PREEMPT_RCU */ 707 734 708 735 /* Invoked on each online non-idle CPU for expedited quiescent state. */ 709 - static void sync_sched_exp_handler(void *unused) 736 + static void rcu_exp_handler(void *unused) 710 737 { 711 738 struct rcu_data *rdp; 712 739 struct rcu_node *rnp; ··· 705 798 rnp = rdp->mynode; 706 799 if (!(READ_ONCE(rnp->expmask) & rdp->grpmask)) 707 800 return; 708 - ret = smp_call_function_single(cpu, sync_sched_exp_handler, NULL, 0); 801 + ret = smp_call_function_single(cpu, rcu_exp_handler, NULL, 0); 709 802 WARN_ON_ONCE(ret); 710 803 } 711 804 712 - /* 713 - * Because a context switch is a grace period for !PREEMPT, any 714 - * blocking grace-period wait automatically implies a grace period if 715 - * there is only one CPU online at any point time during execution of 716 - * either synchronize_rcu() or synchronize_rcu_expedited(). It is OK to 717 - * occasionally incorrectly indicate that there are multiple CPUs online 718 - * when there was in fact only one the whole time, as this just adds some 719 - * overhead: RCU still operates correctly. 805 + #endif /* #else #ifdef CONFIG_PREEMPT_RCU */ 806 + 807 + /** 808 + * synchronize_rcu_expedited - Brute-force RCU grace period 809 + * 810 + * Wait for an RCU grace period, but expedite it. The basic idea is to 811 + * IPI all non-idle non-nohz online CPUs. The IPI handler checks whether 812 + * the CPU is in an RCU critical section, and if so, it sets a flag that 813 + * causes the outermost rcu_read_unlock() to report the quiescent state 814 + * for RCU-preempt or asks the scheduler for help for RCU-sched. On the 815 + * other hand, if the CPU is not in an RCU read-side critical section, 816 + * the IPI handler reports the quiescent state immediately. 817 + * 818 + * Although this is a greate improvement over previous expedited 819 + * implementations, it is still unfriendly to real-time workloads, so is 820 + * thus not recommended for any sort of common-case code. In fact, if 821 + * you are using synchronize_rcu_expedited() in a loop, please restructure 822 + * your code to batch your updates, and then Use a single synchronize_rcu() 823 + * instead. 824 + * 825 + * This has the same semantics as (but is more brutal than) synchronize_rcu(). 720 826 */ 721 - static int rcu_blocking_is_gp(void) 722 - { 723 - int ret; 724 - 725 - might_sleep(); /* Check for RCU read-side critical section. */ 726 - preempt_disable(); 727 - ret = num_online_cpus() <= 1; 728 - preempt_enable(); 729 - return ret; 730 - } 731 - 732 - /* PREEMPT=n implementation of synchronize_rcu_expedited(). */ 733 827 void synchronize_rcu_expedited(void) 734 828 { 829 + struct rcu_data *rdp; 830 + struct rcu_exp_work rew; 831 + struct rcu_node *rnp; 832 + unsigned long s; 833 + 735 834 RCU_LOCKDEP_WARN(lock_is_held(&rcu_bh_lock_map) || 736 835 lock_is_held(&rcu_lock_map) || 737 836 lock_is_held(&rcu_sched_lock_map), 738 837 "Illegal synchronize_rcu_expedited() in RCU read-side critical section"); 739 838 740 - /* If only one CPU, this is automatically a grace period. */ 839 + /* Is the state is such that the call is a grace period? */ 741 840 if (rcu_blocking_is_gp()) 742 841 return; 743 842 744 - _synchronize_rcu_expedited(sync_sched_exp_handler); 843 + /* If expedited grace periods are prohibited, fall back to normal. */ 844 + if (rcu_gp_is_normal()) { 845 + wait_rcu_gp(call_rcu); 846 + return; 847 + } 848 + 849 + /* Take a snapshot of the sequence number. */ 850 + s = rcu_exp_gp_seq_snap(); 851 + if (exp_funnel_lock(s)) 852 + return; /* Someone else did our work for us. */ 853 + 854 + /* Ensure that load happens before action based on it. */ 855 + if (unlikely(rcu_scheduler_active == RCU_SCHEDULER_INIT)) { 856 + /* Direct call during scheduler init and early_initcalls(). */ 857 + rcu_exp_sel_wait_wake(s); 858 + } else { 859 + /* Marshall arguments & schedule the expedited grace period. */ 860 + rew.rew_s = s; 861 + INIT_WORK_ONSTACK(&rew.rew_work, wait_rcu_exp_gp); 862 + queue_work(rcu_gp_wq, &rew.rew_work); 863 + } 864 + 865 + /* Wait for expedited grace period to complete. */ 866 + rdp = per_cpu_ptr(&rcu_data, raw_smp_processor_id()); 867 + rnp = rcu_get_root(); 868 + wait_event(rnp->exp_wq[rcu_seq_ctr(s) & 0x3], 869 + sync_exp_work_done(s)); 870 + smp_mb(); /* Workqueue actions happen before return. */ 871 + 872 + /* Let the next expedited grace period start. */ 873 + mutex_unlock(&rcu_state.exp_mutex); 745 874 } 746 875 EXPORT_SYMBOL_GPL(synchronize_rcu_expedited); 747 - 748 - #endif /* #else #ifdef CONFIG_PREEMPT_RCU */
+57 -181
kernel/rcu/tree_plugin.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0+ */ 1 2 /* 2 3 * Read-Copy Update mechanism for mutual exclusion (tree-based version) 3 4 * Internal non-public definitions that provide either classic 4 5 * or preemptible semantics. 5 6 * 6 - * This program is free software; you can redistribute it and/or modify 7 - * it under the terms of the GNU General Public License as published by 8 - * the Free Software Foundation; either version 2 of the License, or 9 - * (at your option) any later version. 10 - * 11 - * This program is distributed in the hope that it will be useful, 12 - * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 - * GNU General Public License for more details. 15 - * 16 - * You should have received a copy of the GNU General Public License 17 - * along with this program; if not, you can access it online at 18 - * http://www.gnu.org/licenses/gpl-2.0.html. 19 - * 20 7 * Copyright Red Hat, 2009 21 8 * Copyright IBM Corporation, 2009 22 9 * 23 10 * Author: Ingo Molnar <mingo@elte.hu> 24 - * Paul E. McKenney <paulmck@linux.vnet.ibm.com> 11 + * Paul E. McKenney <paulmck@linux.ibm.com> 25 12 */ 26 13 27 14 #include <linux/delay.h> ··· 21 34 #include "../time/tick-internal.h" 22 35 23 36 #ifdef CONFIG_RCU_BOOST 24 - 25 37 #include "../locking/rtmutex_common.h" 26 - 27 - /* 28 - * Control variables for per-CPU and per-rcu_node kthreads. 29 - */ 30 - static DEFINE_PER_CPU(struct task_struct *, rcu_cpu_kthread_task); 31 - DEFINE_PER_CPU(unsigned int, rcu_cpu_kthread_status); 32 - DEFINE_PER_CPU(unsigned int, rcu_cpu_kthread_loops); 33 - DEFINE_PER_CPU(char, rcu_cpu_has_work); 34 - 35 38 #else /* #ifdef CONFIG_RCU_BOOST */ 36 39 37 40 /* ··· 284 307 __this_cpu_read(rcu_data.gp_seq), 285 308 TPS("cpuqs")); 286 309 __this_cpu_write(rcu_data.cpu_no_qs.b.norm, false); 287 - barrier(); /* Coordinate with rcu_flavor_check_callbacks(). */ 310 + barrier(); /* Coordinate with rcu_flavor_sched_clock_irq(). */ 288 311 current->rcu_read_unlock_special.b.need_qs = false; 289 312 } 290 313 } ··· 765 788 } 766 789 767 790 /* 768 - * Check for a quiescent state from the current CPU. When a task blocks, 769 - * the task is recorded in the corresponding CPU's rcu_node structure, 770 - * which is checked elsewhere. 771 - * 772 - * Caller must disable hard irqs. 791 + * Check for a quiescent state from the current CPU, including voluntary 792 + * context switches for Tasks RCU. When a task blocks, the task is 793 + * recorded in the corresponding CPU's rcu_node structure, which is checked 794 + * elsewhere, hence this function need only check for quiescent states 795 + * related to the current CPU, not to those related to tasks. 773 796 */ 774 - static void rcu_flavor_check_callbacks(int user) 797 + static void rcu_flavor_sched_clock_irq(int user) 775 798 { 776 799 struct task_struct *t = current; 777 800 ··· 801 824 time_after(jiffies, rcu_state.gp_start + HZ)) 802 825 t->rcu_read_unlock_special.b.need_qs = true; 803 826 } 804 - 805 - /** 806 - * synchronize_rcu - wait until a grace period has elapsed. 807 - * 808 - * Control will return to the caller some time after a full grace 809 - * period has elapsed, in other words after all currently executing RCU 810 - * read-side critical sections have completed. Note, however, that 811 - * upon return from synchronize_rcu(), the caller might well be executing 812 - * concurrently with new RCU read-side critical sections that began while 813 - * synchronize_rcu() was waiting. RCU read-side critical sections are 814 - * delimited by rcu_read_lock() and rcu_read_unlock(), and may be nested. 815 - * In addition, regions of code across which interrupts, preemption, or 816 - * softirqs have been disabled also serve as RCU read-side critical 817 - * sections. This includes hardware interrupt handlers, softirq handlers, 818 - * and NMI handlers. 819 - * 820 - * Note that this guarantee implies further memory-ordering guarantees. 821 - * On systems with more than one CPU, when synchronize_rcu() returns, 822 - * each CPU is guaranteed to have executed a full memory barrier since 823 - * the end of its last RCU read-side critical section whose beginning 824 - * preceded the call to synchronize_rcu(). In addition, each CPU having 825 - * an RCU read-side critical section that extends beyond the return from 826 - * synchronize_rcu() is guaranteed to have executed a full memory barrier 827 - * after the beginning of synchronize_rcu() and before the beginning of 828 - * that RCU read-side critical section. Note that these guarantees include 829 - * CPUs that are offline, idle, or executing in user mode, as well as CPUs 830 - * that are executing in the kernel. 831 - * 832 - * Furthermore, if CPU A invoked synchronize_rcu(), which returned 833 - * to its caller on CPU B, then both CPU A and CPU B are guaranteed 834 - * to have executed a full memory barrier during the execution of 835 - * synchronize_rcu() -- even if CPU A and CPU B are the same CPU (but 836 - * again only if the system has more than one CPU). 837 - */ 838 - void synchronize_rcu(void) 839 - { 840 - RCU_LOCKDEP_WARN(lock_is_held(&rcu_bh_lock_map) || 841 - lock_is_held(&rcu_lock_map) || 842 - lock_is_held(&rcu_sched_lock_map), 843 - "Illegal synchronize_rcu() in RCU read-side critical section"); 844 - if (rcu_scheduler_active == RCU_SCHEDULER_INACTIVE) 845 - return; 846 - if (rcu_gp_is_expedited()) 847 - synchronize_rcu_expedited(); 848 - else 849 - wait_rcu_gp(call_rcu); 850 - } 851 - EXPORT_SYMBOL_GPL(synchronize_rcu); 852 827 853 828 /* 854 829 * Check for a task exiting while in a preemptible-RCU read-side ··· 1017 1088 } 1018 1089 1019 1090 /* 1020 - * Check to see if this CPU is in a non-context-switch quiescent state 1021 - * (user mode or idle loop for rcu, non-softirq execution for rcu_bh). 1022 - * Also schedule RCU core processing. 1023 - * 1024 - * This function must be called from hardirq context. It is normally 1025 - * invoked from the scheduling-clock interrupt. 1091 + * Check to see if this CPU is in a non-context-switch quiescent state, 1092 + * namely user mode and idle loop. 1026 1093 */ 1027 - static void rcu_flavor_check_callbacks(int user) 1094 + static void rcu_flavor_sched_clock_irq(int user) 1028 1095 { 1029 1096 if (user || rcu_is_cpu_rrupt_from_idle()) { 1030 1097 ··· 1039 1114 rcu_qs(); 1040 1115 } 1041 1116 } 1042 - 1043 - /* PREEMPT=n implementation of synchronize_rcu(). */ 1044 - void synchronize_rcu(void) 1045 - { 1046 - RCU_LOCKDEP_WARN(lock_is_held(&rcu_bh_lock_map) || 1047 - lock_is_held(&rcu_lock_map) || 1048 - lock_is_held(&rcu_sched_lock_map), 1049 - "Illegal synchronize_rcu() in RCU read-side critical section"); 1050 - if (rcu_blocking_is_gp()) 1051 - return; 1052 - if (rcu_gp_is_expedited()) 1053 - synchronize_rcu_expedited(); 1054 - else 1055 - wait_rcu_gp(call_rcu); 1056 - } 1057 - EXPORT_SYMBOL_GPL(synchronize_rcu); 1058 1117 1059 1118 /* 1060 1119 * Because preemptible RCU does not exist, tasks cannot possibly exit ··· 1216 1307 unsigned long flags; 1217 1308 1218 1309 local_irq_save(flags); 1219 - __this_cpu_write(rcu_cpu_has_work, 1); 1220 - if (__this_cpu_read(rcu_cpu_kthread_task) != NULL && 1221 - current != __this_cpu_read(rcu_cpu_kthread_task)) { 1222 - rcu_wake_cond(__this_cpu_read(rcu_cpu_kthread_task), 1223 - __this_cpu_read(rcu_cpu_kthread_status)); 1310 + __this_cpu_write(rcu_data.rcu_cpu_has_work, 1); 1311 + if (__this_cpu_read(rcu_data.rcu_cpu_kthread_task) != NULL && 1312 + current != __this_cpu_read(rcu_data.rcu_cpu_kthread_task)) { 1313 + rcu_wake_cond(__this_cpu_read(rcu_data.rcu_cpu_kthread_task), 1314 + __this_cpu_read(rcu_data.rcu_cpu_kthread_status)); 1224 1315 } 1225 1316 local_irq_restore(flags); 1226 1317 } ··· 1231 1322 */ 1232 1323 static bool rcu_is_callbacks_kthread(void) 1233 1324 { 1234 - return __this_cpu_read(rcu_cpu_kthread_task) == current; 1325 + return __this_cpu_read(rcu_data.rcu_cpu_kthread_task) == current; 1235 1326 } 1236 1327 1237 1328 #define RCU_BOOST_DELAY_JIFFIES DIV_ROUND_UP(CONFIG_RCU_BOOST_DELAY * HZ, 1000) ··· 1278 1369 return 0; 1279 1370 } 1280 1371 1281 - static void rcu_kthread_do_work(void) 1282 - { 1283 - rcu_do_batch(this_cpu_ptr(&rcu_data)); 1284 - } 1285 - 1286 1372 static void rcu_cpu_kthread_setup(unsigned int cpu) 1287 1373 { 1288 1374 struct sched_param sp; ··· 1288 1384 1289 1385 static void rcu_cpu_kthread_park(unsigned int cpu) 1290 1386 { 1291 - per_cpu(rcu_cpu_kthread_status, cpu) = RCU_KTHREAD_OFFCPU; 1387 + per_cpu(rcu_data.rcu_cpu_kthread_status, cpu) = RCU_KTHREAD_OFFCPU; 1292 1388 } 1293 1389 1294 1390 static int rcu_cpu_kthread_should_run(unsigned int cpu) 1295 1391 { 1296 - return __this_cpu_read(rcu_cpu_has_work); 1392 + return __this_cpu_read(rcu_data.rcu_cpu_has_work); 1297 1393 } 1298 1394 1299 1395 /* ··· 1303 1399 */ 1304 1400 static void rcu_cpu_kthread(unsigned int cpu) 1305 1401 { 1306 - unsigned int *statusp = this_cpu_ptr(&rcu_cpu_kthread_status); 1307 - char work, *workp = this_cpu_ptr(&rcu_cpu_has_work); 1402 + unsigned int *statusp = this_cpu_ptr(&rcu_data.rcu_cpu_kthread_status); 1403 + char work, *workp = this_cpu_ptr(&rcu_data.rcu_cpu_has_work); 1308 1404 int spincnt; 1309 1405 1310 1406 for (spincnt = 0; spincnt < 10; spincnt++) { 1311 1407 trace_rcu_utilization(TPS("Start CPU kthread@rcu_wait")); 1312 1408 local_bh_disable(); 1313 1409 *statusp = RCU_KTHREAD_RUNNING; 1314 - this_cpu_inc(rcu_cpu_kthread_loops); 1315 1410 local_irq_disable(); 1316 1411 work = *workp; 1317 1412 *workp = 0; 1318 1413 local_irq_enable(); 1319 1414 if (work) 1320 - rcu_kthread_do_work(); 1415 + rcu_do_batch(this_cpu_ptr(&rcu_data)); 1321 1416 local_bh_enable(); 1322 1417 if (*workp == 0) { 1323 1418 trace_rcu_utilization(TPS("End CPU kthread@rcu_wait")); ··· 1362 1459 } 1363 1460 1364 1461 static struct smp_hotplug_thread rcu_cpu_thread_spec = { 1365 - .store = &rcu_cpu_kthread_task, 1462 + .store = &rcu_data.rcu_cpu_kthread_task, 1366 1463 .thread_should_run = rcu_cpu_kthread_should_run, 1367 1464 .thread_fn = rcu_cpu_kthread, 1368 1465 .thread_comm = "rcuc/%u", ··· 1379 1476 int cpu; 1380 1477 1381 1478 for_each_possible_cpu(cpu) 1382 - per_cpu(rcu_cpu_has_work, cpu) = 0; 1479 + per_cpu(rcu_data.rcu_cpu_has_work, cpu) = 0; 1383 1480 if (WARN_ONCE(smpboot_register_percpu_thread(&rcu_cpu_thread_spec), "%s: Could not start rcub kthread, OOM is now expected behavior\n", __func__)) 1384 1481 return; 1385 1482 rcu_for_each_leaf_node(rnp) ··· 1446 1543 int rcu_needs_cpu(u64 basemono, u64 *nextevt) 1447 1544 { 1448 1545 *nextevt = KTIME_MAX; 1449 - return rcu_cpu_has_callbacks(NULL); 1546 + return !rcu_segcblist_empty(&this_cpu_ptr(&rcu_data)->cblist); 1450 1547 } 1451 1548 1452 1549 /* ··· 1462 1559 * is nothing. 1463 1560 */ 1464 1561 static void rcu_prepare_for_idle(void) 1465 - { 1466 - } 1467 - 1468 - /* 1469 - * Don't bother keeping a running count of the number of RCU callbacks 1470 - * posted because CONFIG_RCU_FAST_NO_HZ=n. 1471 - */ 1472 - static void rcu_idle_count_callbacks_posted(void) 1473 1562 { 1474 1563 } 1475 1564 ··· 1547 1652 1548 1653 lockdep_assert_irqs_disabled(); 1549 1654 1550 - /* Snapshot to detect later posting of non-lazy callback. */ 1551 - rdp->nonlazy_posted_snap = rdp->nonlazy_posted; 1552 - 1553 1655 /* If no callbacks, RCU doesn't need the CPU. */ 1554 - if (!rcu_cpu_has_callbacks(&rdp->all_lazy)) { 1656 + if (rcu_segcblist_empty(&rdp->cblist)) { 1555 1657 *nextevt = KTIME_MAX; 1556 1658 return 0; 1557 1659 } ··· 1562 1670 rdp->last_accelerate = jiffies; 1563 1671 1564 1672 /* Request timer delay depending on laziness, and round. */ 1565 - if (!rdp->all_lazy) { 1673 + rdp->all_lazy = !rcu_segcblist_n_nonlazy_cbs(&rdp->cblist); 1674 + if (rdp->all_lazy) { 1675 + dj = round_jiffies(rcu_idle_lazy_gp_delay + jiffies) - jiffies; 1676 + } else { 1566 1677 dj = round_up(rcu_idle_gp_delay + jiffies, 1567 1678 rcu_idle_gp_delay) - jiffies; 1568 - } else { 1569 - dj = round_jiffies(rcu_idle_lazy_gp_delay + jiffies) - jiffies; 1570 1679 } 1571 1680 *nextevt = basemono + dj * TICK_NSEC; 1572 1681 return 0; ··· 1597 1704 /* Handle nohz enablement switches conservatively. */ 1598 1705 tne = READ_ONCE(tick_nohz_active); 1599 1706 if (tne != rdp->tick_nohz_enabled_snap) { 1600 - if (rcu_cpu_has_callbacks(NULL)) 1707 + if (!rcu_segcblist_empty(&rdp->cblist)) 1601 1708 invoke_rcu_core(); /* force nohz to see update. */ 1602 1709 rdp->tick_nohz_enabled_snap = tne; 1603 1710 return; ··· 1610 1717 * callbacks, invoke RCU core for the side-effect of recalculating 1611 1718 * idle duration on re-entry to idle. 1612 1719 */ 1613 - if (rdp->all_lazy && 1614 - rdp->nonlazy_posted != rdp->nonlazy_posted_snap) { 1720 + if (rdp->all_lazy && rcu_segcblist_n_nonlazy_cbs(&rdp->cblist)) { 1615 1721 rdp->all_lazy = false; 1616 - rdp->nonlazy_posted_snap = rdp->nonlazy_posted; 1617 1722 invoke_rcu_core(); 1618 1723 return; 1619 1724 } ··· 1647 1756 invoke_rcu_core(); 1648 1757 } 1649 1758 1650 - /* 1651 - * Keep a running count of the number of non-lazy callbacks posted 1652 - * on this CPU. This running counter (which is never decremented) allows 1653 - * rcu_prepare_for_idle() to detect when something out of the idle loop 1654 - * posts a callback, even if an equal number of callbacks are invoked. 1655 - * Of course, callbacks should only be posted from within a trace event 1656 - * designed to be called from idle or from within RCU_NONIDLE(). 1657 - */ 1658 - static void rcu_idle_count_callbacks_posted(void) 1659 - { 1660 - __this_cpu_add(rcu_data.nonlazy_posted, 1); 1661 - } 1662 - 1663 1759 #endif /* #else #if !defined(CONFIG_RCU_FAST_NO_HZ) */ 1664 1760 1665 1761 #ifdef CONFIG_RCU_FAST_NO_HZ ··· 1654 1776 static void print_cpu_stall_fast_no_hz(char *cp, int cpu) 1655 1777 { 1656 1778 struct rcu_data *rdp = &per_cpu(rcu_data, cpu); 1657 - unsigned long nlpd = rdp->nonlazy_posted - rdp->nonlazy_posted_snap; 1658 1779 1659 - sprintf(cp, "last_accelerate: %04lx/%04lx, nonlazy_posted: %ld, %c%c", 1780 + sprintf(cp, "last_accelerate: %04lx/%04lx, Nonlazy posted: %c%c%c", 1660 1781 rdp->last_accelerate & 0xffff, jiffies & 0xffff, 1661 - ulong2long(nlpd), 1662 - rdp->all_lazy ? 'L' : '.', 1663 - rdp->tick_nohz_enabled_snap ? '.' : 'D'); 1782 + ".l"[rdp->all_lazy], 1783 + ".L"[!rcu_segcblist_n_nonlazy_cbs(&rdp->cblist)], 1784 + ".D"[!rdp->tick_nohz_enabled_snap]); 1664 1785 } 1665 1786 1666 1787 #else /* #ifdef CONFIG_RCU_FAST_NO_HZ */ ··· 1745 1868 1746 1869 /* 1747 1870 * Offload callback processing from the boot-time-specified set of CPUs 1748 - * specified by rcu_nocb_mask. For each CPU in the set, there is a 1749 - * kthread created that pulls the callbacks from the corresponding CPU, 1750 - * waits for a grace period to elapse, and invokes the callbacks. 1751 - * The no-CBs CPUs do a wake_up() on their kthread when they insert 1752 - * a callback into any empty list, unless the rcu_nocb_poll boot parameter 1753 - * has been specified, in which case each kthread actively polls its 1754 - * CPU. (Which isn't so great for energy efficiency, but which does 1755 - * reduce RCU's overhead on that CPU.) 1871 + * specified by rcu_nocb_mask. For the CPUs in the set, there are kthreads 1872 + * created that pull the callbacks from the corresponding CPU, wait for 1873 + * a grace period to elapse, and invoke the callbacks. These kthreads 1874 + * are organized into leaders, which manage incoming callbacks, wait for 1875 + * grace periods, and awaken followers, and the followers, which only 1876 + * invoke callbacks. Each leader is its own follower. The no-CBs CPUs 1877 + * do a wake_up() on their kthread when they insert a callback into any 1878 + * empty list, unless the rcu_nocb_poll boot parameter has been specified, 1879 + * in which case each kthread actively polls its CPU. (Which isn't so great 1880 + * for energy efficiency, but which does reduce RCU's overhead on that CPU.) 1756 1881 * 1757 1882 * This is intended to be used in conjunction with Frederic Weisbecker's 1758 1883 * adaptive-idle work, which would seriously reduce OS jitter on CPUs 1759 1884 * running CPU-bound user-mode computations. 1760 1885 * 1761 - * Offloading of callback processing could also in theory be used as 1762 - * an energy-efficiency measure because CPUs with no RCU callbacks 1763 - * queued are more aggressive about entering dyntick-idle mode. 1886 + * Offloading of callbacks can also be used as an energy-efficiency 1887 + * measure because CPUs with no RCU callbacks queued are more aggressive 1888 + * about entering dyntick-idle mode. 1764 1889 */ 1765 1890 1766 1891 ··· 1866 1987 raw_spin_unlock_irqrestore(&rdp->nocb_lock, flags); 1867 1988 } 1868 1989 1869 - /* 1870 - * Does the specified CPU need an RCU callback for this invocation 1871 - * of rcu_barrier()? 1872 - */ 1990 + /* Does rcu_barrier need to queue an RCU callback on the specified CPU? */ 1873 1991 static bool rcu_nocb_cpu_needs_barrier(int cpu) 1874 1992 { 1875 1993 struct rcu_data *rdp = per_cpu_ptr(&rcu_data, cpu); ··· 1882 2006 * callbacks would be posted. In the worst case, the first 1883 2007 * barrier in rcu_barrier() suffices (but the caller cannot 1884 2008 * necessarily rely on this, not a substitute for the caller 1885 - * getting the concurrency design right!). There must also be 1886 - * a barrier between the following load an posting of a callback 2009 + * getting the concurrency design right!). There must also be a 2010 + * barrier between the following load and posting of a callback 1887 2011 * (if a callback is in fact needed). This is associated with an 1888 2012 * atomic_inc() in the caller. 1889 2013 */ ··· 2393 2517 2394 2518 /* 2395 2519 * If the specified CPU is a no-CBs CPU that does not already have its 2396 - * rcuo kthreads, spawn them. 2520 + * rcuo kthread, spawn it. 2397 2521 */ 2398 - static void rcu_spawn_all_nocb_kthreads(int cpu) 2522 + static void rcu_spawn_cpu_nocb_kthread(int cpu) 2399 2523 { 2400 2524 if (rcu_scheduler_fully_active) 2401 2525 rcu_spawn_one_nocb_kthread(cpu); ··· 2412 2536 int cpu; 2413 2537 2414 2538 for_each_online_cpu(cpu) 2415 - rcu_spawn_all_nocb_kthreads(cpu); 2539 + rcu_spawn_cpu_nocb_kthread(cpu); 2416 2540 } 2417 2541 2418 2542 /* How many follower CPU IDs per leader? Default of -1 for sqrt(nr_cpu_ids). */ ··· 2546 2670 { 2547 2671 } 2548 2672 2549 - static void rcu_spawn_all_nocb_kthreads(int cpu) 2673 + static void rcu_spawn_cpu_nocb_kthread(int cpu) 2550 2674 { 2551 2675 } 2552 2676
+2 -15
kernel/rcu/update.c
··· 1 + // SPDX-License-Identifier: GPL-2.0+ 1 2 /* 2 3 * Read-Copy Update mechanism for mutual exclusion 3 - * 4 - * This program is free software; you can redistribute it and/or modify 5 - * it under the terms of the GNU General Public License as published by 6 - * the Free Software Foundation; either version 2 of the License, or 7 - * (at your option) any later version. 8 - * 9 - * This program is distributed in the hope that it will be useful, 10 - * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 - * GNU General Public License for more details. 13 - * 14 - * You should have received a copy of the GNU General Public License 15 - * along with this program; if not, you can access it online at 16 - * http://www.gnu.org/licenses/gpl-2.0.html. 17 4 * 18 5 * Copyright IBM Corporation, 2001 19 6 * 20 7 * Authors: Dipankar Sarma <dipankar@in.ibm.com> 21 8 * Manfred Spraul <manfred@colorfullife.com> 22 9 * 23 - * Based on the original work by Paul McKenney <paulmck@us.ibm.com> 10 + * Based on the original work by Paul McKenney <paulmck@linux.ibm.com> 24 11 * and inputs from Rusty Russell, Andrea Arcangeli and Andi Kleen. 25 12 * Papers: 26 13 * http://www.rdrop.com/users/paulmck/paper/rclockpdcsproof.pdf
+2 -2
kernel/sched/cpufreq.c
··· 48 48 * 49 49 * Clear the update_util_data pointer for the given CPU. 50 50 * 51 - * Callers must use RCU-sched callbacks to free any memory that might be 52 - * accessed via the old update_util_data pointer or invoke synchronize_sched() 51 + * Callers must use RCU callbacks to free any memory that might be 52 + * accessed via the old update_util_data pointer or invoke synchronize_rcu() 53 53 * right after this function to avoid use-after-free. 54 54 */ 55 55 void cpufreq_remove_update_util_hook(int cpu)
+1 -1
kernel/sched/cpufreq_schedutil.c
··· 859 859 for_each_cpu(cpu, policy->cpus) 860 860 cpufreq_remove_update_util_hook(cpu); 861 861 862 - synchronize_sched(); 862 + synchronize_rcu(); 863 863 864 864 if (!policy->fast_switch_enabled) { 865 865 irq_work_sync(&sg_policy->irq_work);
+1 -1
kernel/sched/sched.h
··· 1260 1260 1261 1261 /* 1262 1262 * The domain tree (rq->sd) is protected by RCU's quiescent state transition. 1263 - * See detach_destroy_domains: synchronize_sched for details. 1263 + * See destroy_sched_domains: call_rcu for details. 1264 1264 * 1265 1265 * The domain tree of any CPU may only be accessed from within 1266 1266 * preempt-disabled sections.
+2 -2
kernel/sched/topology.c
··· 442 442 raw_spin_unlock_irqrestore(&rq->lock, flags); 443 443 444 444 if (old_rd) 445 - call_rcu_sched(&old_rd->rcu, free_rootdomain); 445 + call_rcu(&old_rd->rcu, free_rootdomain); 446 446 } 447 447 448 448 void sched_get_rd(struct root_domain *rd) ··· 455 455 if (!atomic_dec_and_test(&rd->refcount)) 456 456 return; 457 457 458 - call_rcu_sched(&rd->rcu, free_rootdomain); 458 + call_rcu(&rd->rcu, free_rootdomain); 459 459 } 460 460 461 461 static int init_rootdomain(struct root_domain *rd)
+1 -1
kernel/time/timer.c
··· 1632 1632 /* Note: this timer irq context must be accounted for as well. */ 1633 1633 account_process_tick(p, user_tick); 1634 1634 run_local_timers(); 1635 - rcu_check_callbacks(user_tick); 1635 + rcu_sched_clock_irq(user_tick); 1636 1636 #ifdef CONFIG_IRQ_WORK 1637 1637 if (in_irq()) 1638 1638 irq_work_tick();
+8 -17
kernel/torture.c
··· 1 + // SPDX-License-Identifier: GPL-2.0+ 1 2 /* 2 3 * Common functions for in-kernel torture tests. 3 4 * 4 - * This program is free software; you can redistribute it and/or modify 5 - * it under the terms of the GNU General Public License as published by 6 - * the Free Software Foundation; either version 2 of the License, or 7 - * (at your option) any later version. 8 - * 9 - * This program is distributed in the hope that it will be useful, 10 - * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 - * GNU General Public License for more details. 13 - * 14 - * You should have received a copy of the GNU General Public License 15 - * along with this program; if not, you can access it online at 16 - * http://www.gnu.org/licenses/gpl-2.0.html. 17 - * 18 5 * Copyright (C) IBM Corporation, 2014 19 6 * 20 - * Author: Paul E. McKenney <paulmck@us.ibm.com> 7 + * Author: Paul E. McKenney <paulmck@linux.ibm.com> 21 8 * Based on kernel/rcu/torture.c. 22 9 */ 23 10 ··· 40 53 #include "rcu/rcu.h" 41 54 42 55 MODULE_LICENSE("GPL"); 43 - MODULE_AUTHOR("Paul E. McKenney <paulmck@us.ibm.com>"); 56 + MODULE_AUTHOR("Paul E. McKenney <paulmck@linux.ibm.com>"); 44 57 45 58 static char *torture_type; 46 59 static int verbose; ··· 62 75 static struct task_struct *onoff_task; 63 76 static long onoff_holdoff; 64 77 static long onoff_interval; 78 + static torture_ofl_func *onoff_f; 65 79 static long n_offline_attempts; 66 80 static long n_offline_successes; 67 81 static unsigned long sum_offline; ··· 106 118 pr_alert("%s" TORTURE_FLAG 107 119 "torture_onoff task: offlined %d\n", 108 120 torture_type, cpu); 121 + if (onoff_f) 122 + onoff_f(); 109 123 (*n_offl_successes)++; 110 124 delta = jiffies - starttime; 111 125 *sum_offl += delta; ··· 233 243 /* 234 244 * Initiate online-offline handling. 235 245 */ 236 - int torture_onoff_init(long ooholdoff, long oointerval) 246 + int torture_onoff_init(long ooholdoff, long oointerval, torture_ofl_func *f) 237 247 { 238 248 #ifdef CONFIG_HOTPLUG_CPU 239 249 onoff_holdoff = ooholdoff; 240 250 onoff_interval = oointerval; 251 + onoff_f = f; 241 252 if (onoff_interval <= 0) 242 253 return 0; 243 254 return torture_create_kthread(torture_onoff, NULL, onoff_task);
+1
tools/memory-model/.gitignore
··· 1 + litmus
+2
tools/memory-model/README
··· 156 156 README 157 157 This file. 158 158 159 + scripts Various scripts, see scripts/README. 160 + 159 161 160 162 =========== 161 163 LIMITATIONS
+2 -1
tools/memory-model/linux-kernel.bell
··· 29 29 'sync-rcu (*synchronize_rcu*) || 30 30 'before-atomic (*smp_mb__before_atomic*) || 31 31 'after-atomic (*smp_mb__after_atomic*) || 32 - 'after-spinlock (*smp_mb__after_spinlock*) 32 + 'after-spinlock (*smp_mb__after_spinlock*) || 33 + 'after-unlock-lock (*smp_mb__after_unlock_lock*) 33 34 instructions F[Barriers] 34 35 35 36 (* Compute matching pairs of nested Rcu-lock and Rcu-unlock *)
+3 -1
tools/memory-model/linux-kernel.cat
··· 30 30 let mb = ([M] ; fencerel(Mb) ; [M]) | 31 31 ([M] ; fencerel(Before-atomic) ; [RMW] ; po? ; [M]) | 32 32 ([M] ; po? ; [RMW] ; fencerel(After-atomic) ; [M]) | 33 - ([M] ; po? ; [LKW] ; fencerel(After-spinlock) ; [M]) 33 + ([M] ; po? ; [LKW] ; fencerel(After-spinlock) ; [M]) | 34 + ([M] ; po ; [UL] ; (co | po) ; [LKW] ; 35 + fencerel(After-unlock-lock) ; [M]) 34 36 let gp = po ; [Sync-rcu] ; po? 35 37 36 38 let strong-fence = mb | gp
+1
tools/memory-model/linux-kernel.def
··· 23 23 smp_mb__before_atomic() { __fence{before-atomic}; } 24 24 smp_mb__after_atomic() { __fence{after-atomic}; } 25 25 smp_mb__after_spinlock() { __fence{after-spinlock}; } 26 + smp_mb__after_unlock_lock() { __fence{after-unlock-lock}; } 26 27 27 28 // Exchange 28 29 xchg(X,V) __xchg{mb}(X,V)
+70
tools/memory-model/scripts/README
··· 1 + ============ 2 + LKMM SCRIPTS 3 + ============ 4 + 5 + 6 + These scripts are run from the tools/memory-model directory. 7 + 8 + checkalllitmus.sh 9 + 10 + Run all litmus tests in the litmus-tests directory, checking 11 + the results against the expected results recorded in the 12 + "Result:" comment lines. 13 + 14 + checkghlitmus.sh 15 + 16 + Run all litmus tests in the https://github.com/paulmckrcu/litmus 17 + archive that are C-language and that have "Result:" comment lines 18 + documenting expected results, comparing the actual results to 19 + those expected. 20 + 21 + checklitmushist.sh 22 + 23 + Run all litmus tests having .litmus.out files from previous 24 + initlitmushist.sh or newlitmushist.sh runs, comparing the 25 + herd output to that of the original runs. 26 + 27 + checklitmus.sh 28 + 29 + Check a single litmus test against its "Result:" expected result. 30 + 31 + cmplitmushist.sh 32 + 33 + Compare output from two different runs of the same litmus tests, 34 + with the absolute pathnames of the tests to run provided one 35 + name per line on standard input. Not normally run manually, 36 + provided instead for use by other scripts. 37 + 38 + initlitmushist.sh 39 + 40 + Run all litmus tests having no more than the specified number 41 + of processes given a specified timeout, recording the results 42 + in .litmus.out files. 43 + 44 + judgelitmus.sh 45 + 46 + Given a .litmus file and its .litmus.out herd output, check the 47 + .litmus.out file against the .litmus file's "Result:" comment to 48 + judge whether the test ran correctly. Not normally run manually, 49 + provided instead for use by other scripts. 50 + 51 + newlitmushist.sh 52 + 53 + For all new or updated litmus tests having no more than the 54 + specified number of processes given a specified timeout, run 55 + and record the results in .litmus.out files. 56 + 57 + parseargs.sh 58 + 59 + Parse command-line arguments. Not normally run manually, 60 + provided instead for use by other scripts. 61 + 62 + runlitmushist.sh 63 + 64 + Run the litmus tests whose absolute pathnames are provided one 65 + name per line on standard input. Not normally run manually, 66 + provided instead for use by other scripts. 67 + 68 + README 69 + 70 + This file
+23 -30
tools/memory-model/scripts/checkalllitmus.sh
··· 1 1 #!/bin/sh 2 + # SPDX-License-Identifier: GPL-2.0+ 2 3 # 3 - # Run herd tests on all .litmus files in the specified directory (which 4 - # defaults to litmus-tests) and check each file's result against a "Result:" 5 - # comment within that litmus test. If the verification result does not 6 - # match that specified in the litmus test, this script prints an error 7 - # message prefixed with "^^^". It also outputs verification results to 8 - # a file whose name is that of the specified litmus test, but with ".out" 9 - # appended. 4 + # Run herd tests on all .litmus files in the litmus-tests directory 5 + # and check each file's result against a "Result:" comment within that 6 + # litmus test. If the verification result does not match that specified 7 + # in the litmus test, this script prints an error message prefixed with 8 + # "^^^". It also outputs verification results to a file whose name is 9 + # that of the specified litmus test, but with ".out" appended. 10 10 # 11 11 # Usage: 12 - # checkalllitmus.sh [ directory ] 12 + # checkalllitmus.sh 13 13 # 14 - # The LINUX_HERD_OPTIONS environment variable may be used to specify 15 - # arguments to herd, whose default is defined by the checklitmus.sh script. 16 - # Thus, one would normally run this in the directory containing the memory 17 - # model, specifying the pathname of the litmus test to check. 14 + # Run this in the directory containing the memory model. 18 15 # 19 16 # This script makes no attempt to run the litmus tests concurrently. 20 - # 21 - # This program is free software; you can redistribute it and/or modify 22 - # it under the terms of the GNU General Public License as published by 23 - # the Free Software Foundation; either version 2 of the License, or 24 - # (at your option) any later version. 25 - # 26 - # This program is distributed in the hope that it will be useful, 27 - # but WITHOUT ANY WARRANTY; without even the implied warranty of 28 - # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 29 - # GNU General Public License for more details. 30 - # 31 - # You should have received a copy of the GNU General Public License 32 - # along with this program; if not, you can access it online at 33 - # http://www.gnu.org/licenses/gpl-2.0.html. 34 17 # 35 18 # Copyright IBM Corporation, 2018 36 19 # 37 20 # Author: Paul E. McKenney <paulmck@linux.vnet.ibm.com> 38 21 39 - litmusdir=${1-litmus-tests} 22 + . scripts/parseargs.sh 23 + 24 + litmusdir=litmus-tests 40 25 if test -d "$litmusdir" -a -r "$litmusdir" -a -x "$litmusdir" 41 26 then 42 27 : 43 28 else 44 29 echo ' --- ' error: $litmusdir is not an accessible directory 45 30 exit 255 31 + fi 32 + 33 + # Create any new directories that have appeared in the github litmus 34 + # repo since the last run. 35 + if test "$LKMM_DESTDIR" != "." 36 + then 37 + find $litmusdir -type d -print | 38 + ( cd "$LKMM_DESTDIR"; sed -e 's/^/mkdir -p /' | sh ) 46 39 fi 47 40 48 41 # Find the checklitmus script. If it is not where we expect it, then ··· 50 57 51 58 # Run the script on all the litmus tests in the specified directory 52 59 ret=0 53 - for i in litmus-tests/*.litmus 60 + for i in $litmusdir/*.litmus 54 61 do 55 62 if ! $clscript $i 56 63 then ··· 59 66 done 60 67 if test "$ret" -ne 0 61 68 then 62 - echo " ^^^ VERIFICATION MISMATCHES" 69 + echo " ^^^ VERIFICATION MISMATCHES" 1>&2 63 70 else 64 - echo All litmus tests verified as was expected. 71 + echo All litmus tests verified as was expected. 1>&2 65 72 fi 66 73 exit $ret
+65
tools/memory-model/scripts/checkghlitmus.sh
··· 1 + #!/bin/sh 2 + # SPDX-License-Identifier: GPL-2.0+ 3 + # 4 + # Runs the C-language litmus tests having a maximum number of processes 5 + # to run, defaults to 6. 6 + # 7 + # sh checkghlitmus.sh 8 + # 9 + # Run from the Linux kernel tools/memory-model directory. See the 10 + # parseargs.sh scripts for arguments. 11 + 12 + . scripts/parseargs.sh 13 + 14 + T=/tmp/checkghlitmus.sh.$$ 15 + trap 'rm -rf $T' 0 16 + mkdir $T 17 + 18 + # Clone the repository if it is not already present. 19 + if test -d litmus 20 + then 21 + : 22 + else 23 + git clone https://github.com/paulmckrcu/litmus 24 + ( cd litmus; git checkout origin/master ) 25 + fi 26 + 27 + # Create any new directories that have appeared in the github litmus 28 + # repo since the last run. 29 + if test "$LKMM_DESTDIR" != "." 30 + then 31 + find litmus -type d -print | 32 + ( cd "$LKMM_DESTDIR"; sed -e 's/^/mkdir -p /' | sh ) 33 + fi 34 + 35 + # Create a list of the C-language litmus tests previously run. 36 + ( cd $LKMM_DESTDIR; find litmus -name '*.litmus.out' -print ) | 37 + sed -e 's/\.out$//' | 38 + xargs -r egrep -l '^ \* Result: (Never|Sometimes|Always|DEADLOCK)' | 39 + xargs -r grep -L "^P${LKMM_PROCS}"> $T/list-C-already 40 + 41 + # Create a list of C-language litmus tests with "Result:" commands and 42 + # no more than the specified number of processes. 43 + find litmus -name '*.litmus' -exec grep -l -m 1 "^C " {} \; > $T/list-C 44 + xargs < $T/list-C -r egrep -l '^ \* Result: (Never|Sometimes|Always|DEADLOCK)' > $T/list-C-result 45 + xargs < $T/list-C-result -r grep -L "^P${LKMM_PROCS}" > $T/list-C-result-short 46 + 47 + # Form list of tests without corresponding .litmus.out files 48 + sort $T/list-C-already $T/list-C-result-short | uniq -u > $T/list-C-needed 49 + 50 + # Run any needed tests. 51 + if scripts/runlitmushist.sh < $T/list-C-needed > $T/run.stdout 2> $T/run.stderr 52 + then 53 + errs= 54 + else 55 + errs=1 56 + fi 57 + 58 + sed < $T/list-C-result-short -e 's,^,scripts/judgelitmus.sh ,' | 59 + sh > $T/judge.stdout 2> $T/judge.stderr 60 + 61 + if test -n "$errs" 62 + then 63 + cat $T/run.stderr 1>&2 64 + fi 65 + grep '!!!' $T/judge.stdout
+11 -63
tools/memory-model/scripts/checklitmus.sh
··· 1 1 #!/bin/sh 2 + # SPDX-License-Identifier: GPL-2.0+ 2 3 # 3 - # Run a herd test and check the result against a "Result:" comment within 4 - # the litmus test. If the verification result does not match that specified 5 - # in the litmus test, this script prints an error message prefixed with 6 - # "^^^" and exits with a non-zero status. It also outputs verification 4 + # Run a herd test and invokes judgelitmus.sh to check the result against 5 + # a "Result:" comment within the litmus test. It also outputs verification 7 6 # results to a file whose name is that of the specified litmus test, but 8 7 # with ".out" appended. 9 8 # 10 9 # Usage: 11 10 # checklitmus.sh file.litmus 12 11 # 13 - # The LINUX_HERD_OPTIONS environment variable may be used to specify 14 - # arguments to herd, which default to "-conf linux-kernel.cfg". Thus, 15 - # one would normally run this in the directory containing the memory model, 16 - # specifying the pathname of the litmus test to check. 17 - # 18 - # This program is free software; you can redistribute it and/or modify 19 - # it under the terms of the GNU General Public License as published by 20 - # the Free Software Foundation; either version 2 of the License, or 21 - # (at your option) any later version. 22 - # 23 - # This program is distributed in the hope that it will be useful, 24 - # but WITHOUT ANY WARRANTY; without even the implied warranty of 25 - # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 26 - # GNU General Public License for more details. 27 - # 28 - # You should have received a copy of the GNU General Public License 29 - # along with this program; if not, you can access it online at 30 - # http://www.gnu.org/licenses/gpl-2.0.html. 12 + # Run this in the directory containing the memory model, specifying the 13 + # pathname of the litmus test to check. The caller is expected to have 14 + # properly set up the LKMM environment variables. 31 15 # 32 16 # Copyright IBM Corporation, 2018 33 17 # 34 18 # Author: Paul E. McKenney <paulmck@linux.vnet.ibm.com> 35 19 36 20 litmus=$1 37 - herdoptions=${LINUX_HERD_OPTIONS--conf linux-kernel.cfg} 21 + herdoptions=${LKMM_HERD_OPTIONS--conf linux-kernel.cfg} 38 22 39 23 if test -f "$litmus" -a -r "$litmus" 40 24 then ··· 27 43 echo ' --- ' error: \"$litmus\" is not a readable file 28 44 exit 255 29 45 fi 30 - if grep -q '^ \* Result: ' $litmus 31 - then 32 - outcome=`grep -m 1 '^ \* Result: ' $litmus | awk '{ print $3 }'` 33 - else 34 - outcome=specified 35 - fi 36 46 37 - echo Herd options: $herdoptions > $litmus.out 38 - /usr/bin/time herd7 -o ~/tmp $herdoptions $litmus >> $litmus.out 2>&1 39 - grep "Herd options:" $litmus.out 40 - grep '^Observation' $litmus.out 41 - if grep -q '^Observation' $litmus.out 42 - then 43 - : 44 - else 45 - cat $litmus.out 46 - echo ' ^^^ Verification error' 47 - echo ' ^^^ Verification error' >> $litmus.out 2>&1 48 - exit 255 49 - fi 50 - if test "$outcome" = DEADLOCK 51 - then 52 - echo grep 3 and 4 53 - if grep '^Observation' $litmus.out | grep -q 'Never 0 0$' 54 - then 55 - ret=0 56 - else 57 - echo " ^^^ Unexpected non-$outcome verification" 58 - echo " ^^^ Unexpected non-$outcome verification" >> $litmus.out 2>&1 59 - ret=1 60 - fi 61 - elif grep '^Observation' $litmus.out | grep -q $outcome || test "$outcome" = Maybe 62 - then 63 - ret=0 64 - else 65 - echo " ^^^ Unexpected non-$outcome verification" 66 - echo " ^^^ Unexpected non-$outcome verification" >> $litmus.out 2>&1 67 - ret=1 68 - fi 69 - tail -2 $litmus.out | head -1 70 - exit $ret 47 + echo Herd options: $herdoptions > $LKMM_DESTDIR/$litmus.out 48 + /usr/bin/time $LKMM_TIMEOUT_CMD herd7 $herdoptions $litmus >> $LKMM_DESTDIR/$litmus.out 2>&1 49 + 50 + scripts/judgelitmus.sh $litmus
+60
tools/memory-model/scripts/checklitmushist.sh
··· 1 + #!/bin/sh 2 + # SPDX-License-Identifier: GPL-2.0+ 3 + # 4 + # Reruns the C-language litmus tests previously run that match the 5 + # specified criteria, and compares the result to that of the previous 6 + # runs from initlitmushist.sh and/or newlitmushist.sh. 7 + # 8 + # sh checklitmushist.sh 9 + # 10 + # Run from the Linux kernel tools/memory-model directory. 11 + # See scripts/parseargs.sh for list of arguments. 12 + # 13 + # Copyright IBM Corporation, 2018 14 + # 15 + # Author: Paul E. McKenney <paulmck@linux.vnet.ibm.com> 16 + 17 + . scripts/parseargs.sh 18 + 19 + T=/tmp/checklitmushist.sh.$$ 20 + trap 'rm -rf $T' 0 21 + mkdir $T 22 + 23 + if test -d litmus 24 + then 25 + : 26 + else 27 + echo Run scripts/initlitmushist.sh first, need litmus repo. 28 + exit 1 29 + fi 30 + 31 + # Create the results directory and populate it with subdirectories. 32 + # The initial output is created here to avoid clobbering the output 33 + # generated earlier. 34 + mkdir $T/results 35 + find litmus -type d -print | ( cd $T/results; sed -e 's/^/mkdir -p /' | sh ) 36 + 37 + # Create the list of litmus tests already run, then remove those that 38 + # are excluded by this run's --procs argument. 39 + ( cd $LKMM_DESTDIR; find litmus -name '*.litmus.out' -print ) | 40 + sed -e 's/\.out$//' | 41 + xargs -r grep -L "^P${LKMM_PROCS}"> $T/list-C-already 42 + xargs < $T/list-C-already -r grep -L "^P${LKMM_PROCS}" > $T/list-C-short 43 + 44 + # Redirect output, run tests, then restore destination directory. 45 + destdir="$LKMM_DESTDIR" 46 + LKMM_DESTDIR=$T/results; export LKMM_DESTDIR 47 + scripts/runlitmushist.sh < $T/list-C-short > $T/runlitmushist.sh.out 2>&1 48 + LKMM_DESTDIR="$destdir"; export LKMM_DESTDIR 49 + 50 + # Move the newly generated .litmus.out files to .litmus.out.new files 51 + # in the destination directory. 52 + cdir=`pwd` 53 + ddir=`awk -v c="$cdir" -v d="$LKMM_DESTDIR" \ 54 + 'END { if (d ~ /^\//) print d; else print c "/" d; }' < /dev/null` 55 + ( cd $T/results; find litmus -type f -name '*.litmus.out' -print | 56 + sed -e 's,^.*$,cp & '"$ddir"'/&.new,' | sh ) 57 + 58 + sed < $T/list-C-short -e 's,^,'"$LKMM_DESTDIR/"',' | 59 + sh scripts/cmplitmushist.sh 60 + exit $?
+87
tools/memory-model/scripts/cmplitmushist.sh
··· 1 + #!/bin/sh 2 + # SPDX-License-Identifier: GPL-2.0+ 3 + # 4 + # Compares .out and .out.new files for each name on standard input, 5 + # one full pathname per line. Outputs comparison results followed by 6 + # a summary. 7 + # 8 + # sh cmplitmushist.sh 9 + 10 + T=/tmp/cmplitmushist.sh.$$ 11 + trap 'rm -rf $T' 0 12 + mkdir $T 13 + 14 + # comparetest oldpath newpath 15 + perfect=0 16 + obsline=0 17 + noobsline=0 18 + obsresult=0 19 + badcompare=0 20 + comparetest () { 21 + grep -v 'maxresident)k\|minor)pagefaults\|^Time' $1 > $T/oldout 22 + grep -v 'maxresident)k\|minor)pagefaults\|^Time' $2 > $T/newout 23 + if cmp -s $T/oldout $T/newout && grep -q '^Observation' $1 24 + then 25 + echo Exact output match: $2 26 + perfect=`expr "$perfect" + 1` 27 + return 0 28 + fi 29 + 30 + grep '^Observation' $1 > $T/oldout 31 + grep '^Observation' $2 > $T/newout 32 + if test -s $T/oldout -o -s $T/newout 33 + then 34 + if cmp -s $T/oldout $T/newout 35 + then 36 + echo Matching Observation result and counts: $2 37 + obsline=`expr "$obsline" + 1` 38 + return 0 39 + fi 40 + else 41 + echo Missing Observation line "(e.g., herd7 timeout)": $2 42 + noobsline=`expr "$noobsline" + 1` 43 + return 0 44 + fi 45 + 46 + grep '^Observation' $1 | awk '{ print $3 }' > $T/oldout 47 + grep '^Observation' $2 | awk '{ print $3 }' > $T/newout 48 + if cmp -s $T/oldout $T/newout 49 + then 50 + echo Matching Observation Always/Sometimes/Never result: $2 51 + obsresult=`expr "$obsresult" + 1` 52 + return 0 53 + fi 54 + echo ' !!!' Result changed: $2 55 + badcompare=`expr "$badcompare" + 1` 56 + return 1 57 + } 58 + 59 + sed -e 's/^.*$/comparetest &.out &.out.new/' > $T/cmpscript 60 + . $T/cmpscript > $T/cmpscript.out 61 + cat $T/cmpscript.out 62 + 63 + echo ' ---' Summary: 1>&2 64 + grep '!!!' $T/cmpscript.out 1>&2 65 + if test "$perfect" -ne 0 66 + then 67 + echo Exact output matches: $perfect 1>&2 68 + fi 69 + if test "$obsline" -ne 0 70 + then 71 + echo Matching Observation result and counts: $obsline 1>&2 72 + fi 73 + if test "$noobsline" -ne 0 74 + then 75 + echo Missing Observation line "(e.g., herd7 timeout)": $noobsline 1>&2 76 + fi 77 + if test "$obsresult" -ne 0 78 + then 79 + echo Matching Observation Always/Sometimes/Never result: $obsresult 1>&2 80 + fi 81 + if test "$badcompare" -ne 0 82 + then 83 + echo "!!!" Result changed: $badcompare 1>&2 84 + exit 1 85 + fi 86 + 87 + exit 0
+68
tools/memory-model/scripts/initlitmushist.sh
··· 1 + #!/bin/sh 2 + # SPDX-License-Identifier: GPL-2.0+ 3 + # 4 + # Runs the C-language litmus tests matching the specified criteria. 5 + # Generates the output for each .litmus file into a corresponding 6 + # .litmus.out file, and does not judge the result. 7 + # 8 + # sh initlitmushist.sh 9 + # 10 + # Run from the Linux kernel tools/memory-model directory. 11 + # See scripts/parseargs.sh for list of arguments. 12 + # 13 + # This script can consume significant wallclock time and CPU, especially as 14 + # the value of --procs rises. On a four-core (eight hardware threads) 15 + # 2.5GHz x86 with a one-minute per-run timeout: 16 + # 17 + # --procs wallclock CPU timeouts tests 18 + # 1 0m11.241s 0m1.086s 0 19 19 + # 2 1m12.598s 2m8.459s 2 393 20 + # 3 1m30.007s 6m2.479s 4 2291 21 + # 4 3m26.042s 18m5.139s 9 3217 22 + # 5 4m26.661s 23m54.128s 13 3784 23 + # 6 4m41.900s 26m4.721s 13 4352 24 + # 7 5m51.463s 35m50.868s 13 4626 25 + # 8 10m5.235s 68m43.672s 34 5117 26 + # 9 15m57.80s 105m58.101s 69 5156 27 + # 10 16m14.13s 103m35.009s 69 5165 28 + # 20 27m48.55s 198m3.286s 156 5269 29 + # 30 + # Increasing the timeout on the 20-process run to five minutes increases 31 + # the runtime to about 90 minutes with the CPU time rising to about 32 + # 10 hours. On the other hand, it decreases the number of timeouts to 101. 33 + # 34 + # Note that there are historical tests for which herd7 will fail 35 + # completely, for example, litmus/manual/atomic/C-unlock-wait-00.litmus 36 + # contains a call to spin_unlock_wait(), which no longer exists in either 37 + # the kernel or LKMM. 38 + 39 + . scripts/parseargs.sh 40 + 41 + T=/tmp/initlitmushist.sh.$$ 42 + trap 'rm -rf $T' 0 43 + mkdir $T 44 + 45 + if test -d litmus 46 + then 47 + : 48 + else 49 + git clone https://github.com/paulmckrcu/litmus 50 + ( cd litmus; git checkout origin/master ) 51 + fi 52 + 53 + # Create any new directories that have appeared in the github litmus 54 + # repo since the last run. 55 + if test "$LKMM_DESTDIR" != "." 56 + then 57 + find litmus -type d -print | 58 + ( cd "$LKMM_DESTDIR"; sed -e 's/^/mkdir -p /' | sh ) 59 + fi 60 + 61 + # Create a list of the C-language litmus tests with no more than the 62 + # specified number of processes (per the --procs argument). 63 + find litmus -name '*.litmus' -exec grep -l -m 1 "^C " {} \; > $T/list-C 64 + xargs < $T/list-C -r grep -L "^P${LKMM_PROCS}" > $T/list-C-short 65 + 66 + scripts/runlitmushist.sh < $T/list-C-short 67 + 68 + exit 0
+78
tools/memory-model/scripts/judgelitmus.sh
··· 1 + #!/bin/sh 2 + # SPDX-License-Identifier: GPL-2.0+ 3 + # 4 + # Given a .litmus test and the corresponding .litmus.out file, check 5 + # the .litmus.out file against the "Result:" comment to judge whether 6 + # the test ran correctly. 7 + # 8 + # Usage: 9 + # judgelitmus.sh file.litmus 10 + # 11 + # Run this in the directory containing the memory model, specifying the 12 + # pathname of the litmus test to check. 13 + # 14 + # Copyright IBM Corporation, 2018 15 + # 16 + # Author: Paul E. McKenney <paulmck@linux.vnet.ibm.com> 17 + 18 + litmus=$1 19 + 20 + if test -f "$litmus" -a -r "$litmus" 21 + then 22 + : 23 + else 24 + echo ' --- ' error: \"$litmus\" is not a readable file 25 + exit 255 26 + fi 27 + if test -f "$LKMM_DESTDIR/$litmus".out -a -r "$LKMM_DESTDIR/$litmus".out 28 + then 29 + : 30 + else 31 + echo ' --- ' error: \"$LKMM_DESTDIR/$litmus\".out is not a readable file 32 + exit 255 33 + fi 34 + if grep -q '^ \* Result: ' $litmus 35 + then 36 + outcome=`grep -m 1 '^ \* Result: ' $litmus | awk '{ print $3 }'` 37 + else 38 + outcome=specified 39 + fi 40 + 41 + grep '^Observation' $LKMM_DESTDIR/$litmus.out 42 + if grep -q '^Observation' $LKMM_DESTDIR/$litmus.out 43 + then 44 + : 45 + else 46 + echo ' !!! Verification error' $litmus 47 + if ! grep -q '!!!' $LKMM_DESTDIR/$litmus.out 48 + then 49 + echo ' !!! Verification error' >> $LKMM_DESTDIR/$litmus.out 2>&1 50 + fi 51 + exit 255 52 + fi 53 + if test "$outcome" = DEADLOCK 54 + then 55 + if grep '^Observation' $LKMM_DESTDIR/$litmus.out | grep -q 'Never 0 0$' 56 + then 57 + ret=0 58 + else 59 + echo " !!! Unexpected non-$outcome verification" $litmus 60 + if ! grep -q '!!!' $LKMM_DESTDIR/$litmus.out 61 + then 62 + echo " !!! Unexpected non-$outcome verification" >> $LKMM_DESTDIR/$litmus.out 2>&1 63 + fi 64 + ret=1 65 + fi 66 + elif grep '^Observation' $LKMM_DESTDIR/$litmus.out | grep -q $outcome || test "$outcome" = Maybe 67 + then 68 + ret=0 69 + else 70 + echo " !!! Unexpected non-$outcome verification" $litmus 71 + if ! grep -q '!!!' $LKMM_DESTDIR/$litmus.out 72 + then 73 + echo " !!! Unexpected non-$outcome verification" >> $LKMM_DESTDIR/$litmus.out 2>&1 74 + fi 75 + ret=1 76 + fi 77 + tail -2 $LKMM_DESTDIR/$litmus.out | head -1 78 + exit $ret
+61
tools/memory-model/scripts/newlitmushist.sh
··· 1 + #!/bin/sh 2 + # SPDX-License-Identifier: GPL-2.0+ 3 + # 4 + # Runs the C-language litmus tests matching the specified criteria 5 + # that do not already have a corresponding .litmus.out file, and does 6 + # not judge the result. 7 + # 8 + # sh newlitmushist.sh 9 + # 10 + # Run from the Linux kernel tools/memory-model directory. 11 + # See scripts/parseargs.sh for list of arguments. 12 + # 13 + # Copyright IBM Corporation, 2018 14 + # 15 + # Author: Paul E. McKenney <paulmck@linux.vnet.ibm.com> 16 + 17 + . scripts/parseargs.sh 18 + 19 + T=/tmp/newlitmushist.sh.$$ 20 + trap 'rm -rf $T' 0 21 + mkdir $T 22 + 23 + if test -d litmus 24 + then 25 + : 26 + else 27 + echo Run scripts/initlitmushist.sh first, need litmus repo. 28 + exit 1 29 + fi 30 + 31 + # Create any new directories that have appeared in the github litmus 32 + # repo since the last run. 33 + if test "$LKMM_DESTDIR" != "." 34 + then 35 + find litmus -type d -print | 36 + ( cd "$LKMM_DESTDIR"; sed -e 's/^/mkdir -p /' | sh ) 37 + fi 38 + 39 + # Create a list of the C-language litmus tests previously run. 40 + ( cd $LKMM_DESTDIR; find litmus -name '*.litmus.out' -print ) | 41 + sed -e 's/\.out$//' | 42 + xargs -r grep -L "^P${LKMM_PROCS}"> $T/list-C-already 43 + 44 + # Form full list of litmus tests with no more than the specified 45 + # number of processes (per the --procs argument). 46 + find litmus -name '*.litmus' -exec grep -l -m 1 "^C " {} \; > $T/list-C-all 47 + xargs < $T/list-C-all -r grep -L "^P${LKMM_PROCS}" > $T/list-C-short 48 + 49 + # Form list of new tests. Note: This does not handle litmus-test deletion! 50 + sort $T/list-C-already $T/list-C-short | uniq -u > $T/list-C-new 51 + 52 + # Form list of litmus tests that have changed since the last run. 53 + sed < $T/list-C-short -e 's,^.*$,if test & -nt '"$LKMM_DESTDIR"'/&.out; then echo &; fi,' > $T/list-C-script 54 + sh $T/list-C-script > $T/list-C-newer 55 + 56 + # Merge the list of new and of updated litmus tests: These must be (re)run. 57 + sort -u $T/list-C-new $T/list-C-newer > $T/list-C-needed 58 + 59 + scripts/runlitmushist.sh < $T/list-C-needed 60 + 61 + exit 0
+136
tools/memory-model/scripts/parseargs.sh
··· 1 + #!/bin/sh 2 + # SPDX-License-Identifier: GPL-2.0+ 3 + # 4 + # the corresponding .litmus.out file, and does not judge the result. 5 + # 6 + # . scripts/parseargs.sh 7 + # 8 + # Include into other Linux kernel tools/memory-model scripts. 9 + # 10 + # Copyright IBM Corporation, 2018 11 + # 12 + # Author: Paul E. McKenney <paulmck@linux.vnet.ibm.com> 13 + 14 + T=/tmp/parseargs.sh.$$ 15 + mkdir $T 16 + 17 + # Initialize one parameter: initparam name default 18 + initparam () { 19 + echo if test -z '"$'$1'"' > $T/s 20 + echo then >> $T/s 21 + echo $1='"'$2'"' >> $T/s 22 + echo export $1 >> $T/s 23 + echo fi >> $T/s 24 + echo $1_DEF='$'$1 >> $T/s 25 + . $T/s 26 + } 27 + 28 + initparam LKMM_DESTDIR "." 29 + initparam LKMM_HERD_OPTIONS "-conf linux-kernel.cfg" 30 + initparam LKMM_JOBS `getconf _NPROCESSORS_ONLN` 31 + initparam LKMM_PROCS "3" 32 + initparam LKMM_TIMEOUT "1m" 33 + 34 + scriptname=$0 35 + 36 + usagehelp () { 37 + echo "Usage $scriptname [ arguments ]" 38 + echo " --destdir path (place for .litmus.out, default by .litmus)" 39 + echo " --herdopts -conf linux-kernel.cfg ..." 40 + echo " --jobs N (number of jobs, default one per CPU)" 41 + echo " --procs N (litmus tests with at most this many processes)" 42 + echo " --timeout N (herd7 timeout (e.g., 10s, 1m, 2hr, 1d, '')" 43 + echo "Defaults: --destdir '$LKMM_DESTDIR_DEF' --herdopts '$LKMM_HERD_OPTIONS_DEF' --jobs '$LKMM_JOBS_DEF' --procs '$LKMM_PROCS_DEF' --timeout '$LKMM_TIMEOUT_DEF'" 44 + exit 1 45 + } 46 + 47 + usage () { 48 + usagehelp 1>&2 49 + } 50 + 51 + # checkarg --argname argtype $# arg mustmatch cannotmatch 52 + checkarg () { 53 + if test $3 -le 1 54 + then 55 + echo $1 needs argument $2 matching \"$5\" 56 + usage 57 + fi 58 + if echo "$4" | grep -q -e "$5" 59 + then 60 + : 61 + else 62 + echo $1 $2 \"$4\" must match \"$5\" 63 + usage 64 + fi 65 + if echo "$4" | grep -q -e "$6" 66 + then 67 + echo $1 $2 \"$4\" must not match \"$6\" 68 + usage 69 + fi 70 + } 71 + 72 + while test $# -gt 0 73 + do 74 + case "$1" in 75 + --destdir) 76 + checkarg --destdir "(path to directory)" "$#" "$2" '.\+' '^--' 77 + LKMM_DESTDIR="$2" 78 + mkdir $LKMM_DESTDIR > /dev/null 2>&1 79 + if ! test -e "$LKMM_DESTDIR" 80 + then 81 + echo "Cannot create directory --destdir '$LKMM_DESTDIR'" 82 + usage 83 + fi 84 + if test -d "$LKMM_DESTDIR" -a -w "$LKMM_DESTDIR" -a -x "$LKMM_DESTDIR" 85 + then 86 + : 87 + else 88 + echo "Directory --destdir '$LKMM_DESTDIR' insufficient permissions to create files" 89 + usage 90 + fi 91 + shift 92 + ;; 93 + --herdopts|--herdopt) 94 + checkarg --destdir "(herd options)" "$#" "$2" '.*' '^--' 95 + LKMM_HERD_OPTIONS="$2" 96 + shift 97 + ;; 98 + -j[1-9]*) 99 + njobs="`echo $1 | sed -e 's/^-j//'`" 100 + trailchars="`echo $njobs | sed -e 's/[0-9]\+\(.*\)$/\1/'`" 101 + if test -n "$trailchars" 102 + then 103 + echo $1 trailing characters "'$trailchars'" 104 + usagehelp 105 + fi 106 + LKMM_JOBS="`echo $njobs | sed -e 's/^\([0-9]\+\).*$/\1/'`" 107 + ;; 108 + --jobs|--job|-j) 109 + checkarg --jobs "(number)" "$#" "$2" '^[1-9][0-9]\+$' '^--' 110 + LKMM_JOBS="$2" 111 + shift 112 + ;; 113 + --procs|--proc) 114 + checkarg --procs "(number)" "$#" "$2" '^[0-9]\+$' '^--' 115 + LKMM_PROCS="$2" 116 + shift 117 + ;; 118 + --timeout) 119 + checkarg --timeout "(timeout spec)" "$#" "$2" '^\([0-9]\+[smhd]\?\|\)$' '^--' 120 + LKMM_TIMEOUT="$2" 121 + shift 122 + ;; 123 + *) 124 + echo Unknown argument $1 125 + usage 126 + ;; 127 + esac 128 + shift 129 + done 130 + if test -z "$LKMM_TIMEOUT" 131 + then 132 + LKMM_TIMEOUT_CMD=""; export LKMM_TIMEOUT_CMD 133 + else 134 + LKMM_TIMEOUT_CMD="timeout $LKMM_TIMEOUT"; export LKMM_TIMEOUT_CMD 135 + fi 136 + rm -rf $T
+87
tools/memory-model/scripts/runlitmushist.sh
··· 1 + #!/bin/bash 2 + # SPDX-License-Identifier: GPL-2.0+ 3 + # 4 + # Runs the C-language litmus tests specified on standard input, using up 5 + # to the specified number of CPUs (defaulting to all of them) and placing 6 + # the results in the specified directory (defaulting to the same place 7 + # the litmus test came from). 8 + # 9 + # sh runlitmushist.sh 10 + # 11 + # Run from the Linux kernel tools/memory-model directory. 12 + # This script uses environment variables produced by parseargs.sh. 13 + # 14 + # Copyright IBM Corporation, 2018 15 + # 16 + # Author: Paul E. McKenney <paulmck@linux.vnet.ibm.com> 17 + 18 + T=/tmp/runlitmushist.sh.$$ 19 + trap 'rm -rf $T' 0 20 + mkdir $T 21 + 22 + if test -d litmus 23 + then 24 + : 25 + else 26 + echo Directory \"litmus\" missing, aborting run. 27 + exit 1 28 + fi 29 + 30 + # Prefixes for per-CPU scripts 31 + for ((i=0;i<$LKMM_JOBS;i++)) 32 + do 33 + echo dir="$LKMM_DESTDIR" > $T/$i.sh 34 + echo T=$T >> $T/$i.sh 35 + echo herdoptions=\"$LKMM_HERD_OPTIONS\" >> $T/$i.sh 36 + cat << '___EOF___' >> $T/$i.sh 37 + runtest () { 38 + echo ' ... ' /usr/bin/time $LKMM_TIMEOUT_CMD herd7 $herdoptions $1 '>' $dir/$1.out '2>&1' 39 + if /usr/bin/time $LKMM_TIMEOUT_CMD herd7 $herdoptions $1 > $dir/$1.out 2>&1 40 + then 41 + if ! grep -q '^Observation ' $dir/$1.out 42 + then 43 + echo ' !!! Herd failed, no Observation:' $1 44 + fi 45 + else 46 + exitcode=$? 47 + if test "$exitcode" -eq 124 48 + then 49 + exitmsg="timed out" 50 + else 51 + exitmsg="failed, exit code $exitcode" 52 + fi 53 + echo ' !!! Herd' ${exitmsg}: $1 54 + fi 55 + } 56 + ___EOF___ 57 + done 58 + 59 + awk -v q="'" -v b='\\' ' 60 + { 61 + 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 62 + }' | bash | 63 + sort -k1n | 64 + awk -v ncpu=$LKMM_JOBS -v t=$T ' 65 + { 66 + print "runtest " $2 >> t "/" NR % ncpu ".sh"; 67 + } 68 + 69 + END { 70 + for (i = 0; i < ncpu; i++) { 71 + print "sh " t "/" i ".sh > " t "/" i ".sh.out 2>&1 &"; 72 + close(t "/" i ".sh"); 73 + } 74 + print "wait"; 75 + }' | sh 76 + cat $T/*.sh.out 77 + if grep -q '!!!' $T/*.sh.out 78 + then 79 + echo ' ---' Summary: 1>&2 80 + grep '!!!' $T/*.sh.out 1>&2 81 + nfail="`grep '!!!' $T/*.sh.out | wc -l`" 82 + echo 'Number of failed herd runs (e.g., timeout): ' $nfail 1>&2 83 + exit 1 84 + else 85 + echo All runs completed successfully. 1>&2 86 + exit 0 87 + fi
+17 -10
tools/testing/selftests/rcutorture/bin/mkinitrd.sh
··· 40 40 cat > $T/init << '__EOF___' 41 41 #!/bin/sh 42 42 # Run in userspace a few milliseconds every second. This helps to 43 - # exercise the NO_HZ_FULL portions of RCU. 43 + # exercise the NO_HZ_FULL portions of RCU. The 192 instances of "a" was 44 + # empirically shown to give a nice multi-millisecond burst of user-mode 45 + # execution on a 2GHz CPU, as desired. Modern CPUs will vary from a 46 + # couple of milliseconds up to perhaps 100 milliseconds, which is an 47 + # acceptable range. 48 + # 49 + # Why not calibrate an exact delay? Because within this initrd, we 50 + # are restricted to Bourne-shell builtins, which as far as I know do not 51 + # provide any means of obtaining a fine-grained timestamp. 52 + 53 + a4="a a a a" 54 + a16="$a4 $a4 $a4 $a4" 55 + a64="$a16 $a16 $a16 $a16" 56 + a192="$a64 $a64 $a64" 44 57 while : 45 58 do 46 59 q= 47 - for i in \ 48 - 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 \ 49 - 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 \ 50 - 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 \ 51 - 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 \ 52 - 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 \ 53 - 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 60 + for i in $a192 54 61 do 55 62 q="$q $i" 56 63 done ··· 131 124 | grep -q '^yes'; then 132 125 # architecture supported by nolibc 133 126 ${CROSS_COMPILE}gcc -fno-asynchronous-unwind-tables -fno-ident \ 134 - -nostdlib -include ../bin/nolibc.h -lgcc -s -static -Os \ 135 - -o init init.c 127 + -nostdlib -include ../../../../include/nolibc/nolibc.h \ 128 + -lgcc -s -static -Os -o init init.c 136 129 else 137 130 ${CROSS_COMPILE}gcc -s -static -Os -o init init.c 138 131 fi
+92 -26
tools/testing/selftests/rcutorture/bin/nolibc.h tools/include/nolibc/nolibc.h
··· 3 3 * Copyright (C) 2017-2018 Willy Tarreau <w@1wt.eu> 4 4 */ 5 5 6 - /* some archs (at least aarch64) don't expose the regular syscalls anymore by 6 + /* 7 + * This file is designed to be used as a libc alternative for minimal programs 8 + * with very limited requirements. It consists of a small number of syscall and 9 + * type definitions, and the minimal startup code needed to call main(). 10 + * All syscalls are declared as static functions so that they can be optimized 11 + * away by the compiler when not used. 12 + * 13 + * Syscalls are split into 3 levels: 14 + * - The lower level is the arch-specific syscall() definition, consisting in 15 + * assembly code in compound expressions. These are called my_syscall0() to 16 + * my_syscall6() depending on the number of arguments. The MIPS 17 + * implementation is limited to 5 arguments. All input arguments are cast 18 + * to a long stored in a register. These expressions always return the 19 + * syscall's return value as a signed long value which is often either a 20 + * pointer or the negated errno value. 21 + * 22 + * - The second level is mostly architecture-independent. It is made of 23 + * static functions called sys_<name>() which rely on my_syscallN() 24 + * depending on the syscall definition. These functions are responsible 25 + * for exposing the appropriate types for the syscall arguments (int, 26 + * pointers, etc) and for setting the appropriate return type (often int). 27 + * A few of them are architecture-specific because the syscalls are not all 28 + * mapped exactly the same among architectures. For example, some archs do 29 + * not implement select() and need pselect6() instead, so the sys_select() 30 + * function will have to abstract this. 31 + * 32 + * - The third level is the libc call definition. It exposes the lower raw 33 + * sys_<name>() calls in a way that looks like what a libc usually does, 34 + * takes care of specific input values, and of setting errno upon error. 35 + * There can be minor variations compared to standard libc calls. For 36 + * example the open() call always takes 3 args here. 37 + * 38 + * The errno variable is declared static and unused. This way it can be 39 + * optimized away if not used. However this means that a program made of 40 + * multiple C files may observe different errno values (one per C file). For 41 + * the type of programs this project targets it usually is not a problem. The 42 + * resulting program may even be reduced by defining the NOLIBC_IGNORE_ERRNO 43 + * macro, in which case the errno value will never be assigned. 44 + * 45 + * Some stdint-like integer types are defined. These are valid on all currently 46 + * supported architectures, because signs are enforced, ints are assumed to be 47 + * 32 bits, longs the size of a pointer and long long 64 bits. If more 48 + * architectures have to be supported, this may need to be adapted. 49 + * 50 + * Some macro definitions like the O_* values passed to open(), and some 51 + * structures like the sys_stat struct depend on the architecture. 52 + * 53 + * The definitions start with the architecture-specific parts, which are picked 54 + * based on what the compiler knows about the target architecture, and are 55 + * completed with the generic code. Since it is the compiler which sets the 56 + * target architecture, cross-compiling normally works out of the box without 57 + * having to specify anything. 58 + * 59 + * Finally some very common libc-level functions are provided. It is the case 60 + * for a few functions usually found in string.h, ctype.h, or stdlib.h. Nothing 61 + * is currently provided regarding stdio emulation. 62 + * 63 + * The macro NOLIBC is always defined, so that it is possible for a program to 64 + * check this macro to know if it is being built against and decide to disable 65 + * some features or simply not to include some standard libc files. 66 + * 67 + * Ideally this file should be split in multiple files for easier long term 68 + * maintenance, but provided as a single file as it is now, it's quite 69 + * convenient to use. Maybe some variations involving a set of includes at the 70 + * top could work. 71 + * 72 + * A simple static executable may be built this way : 73 + * $ gcc -fno-asynchronous-unwind-tables -fno-ident -s -Os -nostdlib \ 74 + * -static -include nolibc.h -lgcc -o hello hello.c 75 + * 76 + * A very useful calling convention table may be found here : 77 + * http://man7.org/linux/man-pages/man2/syscall.2.html 78 + * 79 + * This doc is quite convenient though not necessarily up to date : 80 + * https://w3challs.com/syscalls/ 81 + * 82 + */ 83 + 84 + /* Some archs (at least aarch64) don't expose the regular syscalls anymore by 7 85 * default, either because they have an "_at" replacement, or because there are 8 86 * more modern alternatives. For now we'd rather still use them. 9 87 */ ··· 96 18 #include <linux/loop.h> 97 19 98 20 #define NOLIBC 99 - 100 - /* Build a static executable this way : 101 - * $ gcc -fno-asynchronous-unwind-tables -fno-ident -s -Os -nostdlib \ 102 - * -static -include nolibc.h -lgcc -o hello hello.c 103 - * 104 - * Useful calling convention table found here : 105 - * http://man7.org/linux/man-pages/man2/syscall.2.html 106 - * 107 - * This doc is even better : 108 - * https://w3challs.com/syscalls/ 109 - */ 110 - 111 21 112 22 /* this way it will be removed if unused */ 113 23 static int errno; ··· 147 81 148 82 /* for poll() */ 149 83 struct pollfd { 150 - int fd; 151 - short int events; 152 - short int revents; 84 + int fd; 85 + short int events; 86 + short int revents; 153 87 }; 154 88 155 89 /* for select() */ ··· 305 239 "syscall\n" \ 306 240 : "=a" (_ret) \ 307 241 : "0"(_num) \ 308 - : "rcx", "r8", "r9", "r10", "r11", "memory", "cc" \ 242 + : "rcx", "r8", "r9", "r10", "r11", "memory", "cc" \ 309 243 ); \ 310 244 _ret; \ 311 245 }) ··· 321 255 : "=a" (_ret) \ 322 256 : "r"(_arg1), \ 323 257 "0"(_num) \ 324 - : "rcx", "r8", "r9", "r10", "r11", "memory", "cc" \ 258 + : "rcx", "r8", "r9", "r10", "r11", "memory", "cc" \ 325 259 ); \ 326 260 _ret; \ 327 261 }) ··· 338 272 : "=a" (_ret) \ 339 273 : "r"(_arg1), "r"(_arg2), \ 340 274 "0"(_num) \ 341 - : "rcx", "r8", "r9", "r10", "r11", "memory", "cc" \ 275 + : "rcx", "r8", "r9", "r10", "r11", "memory", "cc" \ 342 276 ); \ 343 277 _ret; \ 344 278 }) ··· 356 290 : "=a" (_ret) \ 357 291 : "r"(_arg1), "r"(_arg2), "r"(_arg3), \ 358 292 "0"(_num) \ 359 - : "rcx", "r8", "r9", "r10", "r11", "memory", "cc" \ 293 + : "rcx", "r8", "r9", "r10", "r11", "memory", "cc" \ 360 294 ); \ 361 295 _ret; \ 362 296 }) ··· 1072 1006 : "=r"(_num), "=r"(_arg4) \ 1073 1007 : "r"(_num) \ 1074 1008 : "memory", "cc", "at", "v1", "hi", "lo", \ 1075 - \ 1009 + "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9" \ 1076 1010 ); \ 1077 1011 _arg4 ? -_num : _num; \ 1078 1012 }) ··· 1091 1025 : "0"(_num), \ 1092 1026 "r"(_arg1) \ 1093 1027 : "memory", "cc", "at", "v1", "hi", "lo", \ 1094 - \ 1028 + "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9" \ 1095 1029 ); \ 1096 1030 _arg4 ? -_num : _num; \ 1097 1031 }) ··· 1111 1045 : "0"(_num), \ 1112 1046 "r"(_arg1), "r"(_arg2) \ 1113 1047 : "memory", "cc", "at", "v1", "hi", "lo", \ 1114 - \ 1048 + "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9" \ 1115 1049 ); \ 1116 1050 _arg4 ? -_num : _num; \ 1117 1051 }) ··· 1132 1066 : "0"(_num), \ 1133 1067 "r"(_arg1), "r"(_arg2), "r"(_arg3) \ 1134 1068 : "memory", "cc", "at", "v1", "hi", "lo", \ 1135 - \ 1069 + "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9" \ 1136 1070 ); \ 1137 1071 _arg4 ? -_num : _num; \ 1138 1072 }) ··· 1153 1087 : "0"(_num), \ 1154 1088 "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4) \ 1155 1089 : "memory", "cc", "at", "v1", "hi", "lo", \ 1156 - \ 1090 + "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9" \ 1157 1091 ); \ 1158 1092 _arg4 ? -_num : _num; \ 1159 1093 }) ··· 1176 1110 : "0"(_num), \ 1177 1111 "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5) \ 1178 1112 : "memory", "cc", "at", "v1", "hi", "lo", \ 1179 - \ 1113 + "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9" \ 1180 1114 ); \ 1181 1115 _arg4 ? -_num : _num; \ 1182 1116 })
+1 -1
virt/kvm/kvm_main.c
··· 4084 4084 static void kvm_resume(void) 4085 4085 { 4086 4086 if (kvm_usage_count) { 4087 - WARN_ON(raw_spin_is_locked(&kvm_count_lock)); 4087 + lockdep_assert_held(&kvm_count_lock); 4088 4088 hardware_enable_nolock(NULL); 4089 4089 } 4090 4090 }