Preview of RCU patches for 2.6.40
Subsystems (27)
cover Preview of RCU patches for 2.6.40
Hello!
This patchset introduces RCU_TREE priority boosting, a new "fire and forget" kfree_rcu() API, numerous uses of kfree_rcu(), plus a number of other fixes and improvements. The patches are as follows:
1. Remove conditional compilation for RCU CPU stall warnings, which
are now controlled only by the boot command line and sysfs.
2. Reworks RCU dyntick-idle interface to better tolerate theoretical
races introduced by expedited grace periods.
3-9. Introduce RCU priority boosting for TREE_RCU.
10-19. Upgrace TREE_RCU tracing to accommodate RCU priority boosting
and update documentation.
20-23. Make DEBUG_OBJECTS_RCU_HEAD work from !PREEMPT (thanks to
Mathieu Desnoyers).
24. Switch to this_cpu() primitives (thanks to Christoph Lameter).
25-27. Apply TREE_RCU priority-boosting lessons learned to TINY_RCU.
28. Avoid spurious diagnostics by moving from rcu_read_unlock() to
__rcu_read_unlock() in exit() patch (thanks to Lai Jiangshan).
29. Settle on "preemptible" spelling vs. "preemptable".
30. Introduce kfree_rcu() (thanks to Lai Jiangshan).
31. "Nice" down processes in rcu_yield(), which is called by RCU's
per-CPU kthreads to avoid monopolizing the CPU.
32. Improve latency by having call_rcu() avoid diving into the
RCU core code when called with irqs disabled.
33. Further reduce TINY_RCU's memory footprint (thanks to Eric
Dumazet).
34-70. Use kfree_rcu() throughout the kernel. This set of patches has
Acked-by's, so will go up -tip.
71-86. Ditto, but lacking Acked-by's.
For a testing-only version of this patchset from git, please see the following subject-to-rebase branch:
git://git.kernel.org/pub/scm/linux/kernel/git/paulmck/linux-2.6-rcu.git rcu/testing
Thanx, Paul
PATCH 1/86 rcu: Remove conditional compilation for RCU CPU stall warnings
The RCU CPU stall warnings can now be controlled using the rcu_cpu_stall_suppress boot-time parameter or via the same parameter from sysfs. There is therefore no longer any reason to have kernel config parameters for this feature. This commit therefore removes the RCU_CPU_STALL_DETECTOR and RCU_CPU_STALL_DETECTOR_RUNNABLE kernel config parameters. The RCU_CPU_STALL_TIMEOUT parameter remains to allow the timeout to be tuned and the RCU_CPU_STALL_VERBOSE parameter remains to allow task-stall information to be suppressed if desired.
--- Documentation/RCU/00-INDEX | 2 +- Documentation/RCU/stallwarn.txt | 23 +++++++++++++---------- kernel/rcutree.c | 26 +------------------------- kernel/rcutree.h | 12 ------------ kernel/rcutree_plugin.h | 12 ------------ lib/Kconfig.debug | 30 ++---------------------------- 6 files changed, 17 insertions(+), 88 deletions(-)
Documentation/RCU/00-INDEX +1 -1
@@ -21,7 +21,7 @@ rcu.txt RTFP.txt - List of RCU papers (bibliography) going back to 1980. stallwarn.txt - - RCU CPU stall warnings (CONFIG_RCU_CPU_STALL_DETECTOR) + - RCU CPU stall warnings (module parameter rcu_cpu_stall_suppress) torture.txt - RCU Torture Test Operation (CONFIG_RCU_TORTURE_TEST) trace.txt
Documentation/RCU/stallwarn.txt +13 -10
@@ -1,22 +1,25 @@ Using RCU's CPU Stall Detector -The CONFIG_RCU_CPU_STALL_DETECTOR kernel config parameter enables -RCU's CPU stall detector, which detects conditions that unduly delay -RCU grace periods. The stall detector's idea of what constitutes -"unduly delayed" is controlled by a set of C preprocessor macros: +The rcu_cpu_stall_suppress module parameter enables RCU's CPU stall +detector, which detects conditions that unduly delay RCU grace periods. +This module parameter enables CPU stall detection by default, but +may be overridden via boot-time parameter or at runtime via sysfs. +The stall detector's idea of what constitutes "unduly delayed" is +controlled by a set of kernel configuration variables and cpp macros: -RCU_SECONDS_TILL_STALL_CHECK +CONFIG_RCU_CPU_STALL_TIMEOUT - This macro defines the period of time that RCU will wait from - the beginning of a grace period until it issues an RCU CPU - stall warning. This time period is normally ten seconds. + This kernel configuration parameter defines the period of time + that RCU will wait from the beginning of a grace period until it + issues an RCU CPU stall warning. This time period is normally + ten seconds. RCU_SECONDS_TILL_STALL_RECHECK This macro defines the period of time that RCU will wait after issuing a stall warning until it issues another stall warning - for the same stall. This time period is normally set to thirty - seconds. + for the same stall. This time period is normally set to three + times the check interval plus thirty seconds. RCU_STALL_RAT_DELAY
kernel/rcutree.c +1 -25
@@ -140,10 +140,8 @@ module_param(blimit, int, 0);module_param (qhimark, int,0 );module_param (qlowmark, int,0 ); -#ifdef CONFIG_RCU_CPU_STALL_DETECTOR -int rcu_cpu_stall_suppress__read_mostly =RCU_CPU_STALL_SUPPRESS_INIT ; +int rcu_cpu_stall_suppress__read_mostly ;module_param (rcu_cpu_stall_suppress, int,0644 ); -#endif /* #ifdef CONFIG_RCU_CPU_STALL_DETECTOR */ static void force_quiescent_state (struct rcu_state *rsp,int relaxed);static int rcu_pending (int cpu);
@@ -450,8 +448,6 @@ static int rcu_implicit_dynticks_qs(struct rcu_data *rdp)#endif /* #else #ifdef CONFIG_NO_HZ */ -#ifdef CONFIG_RCU_CPU_STALL_DETECTOR -int rcu_cpu_stall_suppress__read_mostly ;static void record_gp_stall_check_time (struct rcu_state *rsp)
@@ -587,26 +583,6 @@ static void __init check_cpu_stall_init(void)atomic_notifier_chain_register (&panic_notifier_list, &rcu_panic_block); } -#else /* #ifdef CONFIG_RCU_CPU_STALL_DETECTOR */ - -static void record_gp_stall_check_time (struct rcu_state *rsp) -{ -} - -static void check_cpu_stall (struct rcu_state *rsp,struct rcu_data *rdp) -{ -} - -void rcu_cpu_stall_reset (void ) -{ -} - -static void __init check_cpu_stall_init (void ) -{ -} - -#endif /* #else #ifdef CONFIG_RCU_CPU_STALL_DETECTOR */ -/* * Update CPU-local rcu_data state to record the newly noticed grace period. * This is used both when we started the grace period and when we notice
kernel/rcutree.h +0 -12
@@ -254,7 +254,6 @@ struct rcu_data {#endif /* #else #ifdef CONFIG_NO_HZ */ #define RCU_JIFFIES_TILL_FORCE_QS 3/* for rsp->jiffies_force_qs */ -#ifdef CONFIG_RCU_CPU_STALL_DETECTOR #ifdef CONFIG_PROVE_RCU #define RCU_STALL_DELAY_DELTA (5 * HZ)
@@ -272,13 +271,6 @@ struct rcu_data {/* scheduling clock irq */ /* before ratting on them. */ -#ifdef CONFIG_RCU_CPU_STALL_DETECTOR_RUNNABLE -#define RCU_CPU_STALL_SUPPRESS_INIT 0 -#else -#define RCU_CPU_STALL_SUPPRESS_INIT 1 -#endif - -#endif /* #ifdef CONFIG_RCU_CPU_STALL_DETECTOR */ /* * RCU global state, including node hierarchy. This hierarchy is
@@ -325,12 +317,10 @@ struct rcu_state {/* due to lock unavailable. */ unsigned long n_force_qs_ngp;/* Number of calls leaving */ /* due to no GP active. */ -#ifdef CONFIG_RCU_CPU_STALL_DETECTOR unsigned long gp_start;/* Time at which GP started, */ /* but in jiffies. */ unsigned long jiffies_stall;/* Time at which to check */ /* for CPU stalls. */ -#endif /* #ifdef CONFIG_RCU_CPU_STALL_DETECTOR */ char *name;/* Name of structure. */ };
@@ -366,11 +356,9 @@ static int rcu_preempted_readers(struct rcu_node *rnp);static void rcu_report_unblock_qs_rnp (struct rcu_node *rnp,unsigned long flags);#endif /* #ifdef CONFIG_HOTPLUG_CPU */ -#ifdef CONFIG_RCU_CPU_STALL_DETECTOR static void rcu_print_detail_task_stall (struct rcu_state *rsp);static void rcu_print_task_stall (struct rcu_node *rnp);static void rcu_preempt_stall_reset (void ); -#endif /* #ifdef CONFIG_RCU_CPU_STALL_DETECTOR */ static void rcu_preempt_check_blocked_tasks (struct rcu_node *rnp);#ifdef CONFIG_HOTPLUG_CPU static int rcu_preempt_offline_tasks(struct rcu_state *rsp,
kernel/rcutree_plugin.h +0 -12
@@ -54,10 +54,6 @@ static void __init rcu_bootup_announce_oddness(void)#ifdef CONFIG_RCU_TORTURE_TEST_RUNNABLE printk (KERN_INFO "\tRCU torture testing starts during boot.\n" );#endif -#ifndef CONFIG_RCU_CPU_STALL_DETECTOR -printk (KERN_INFO -"\tRCU-based detection of stalled CPUs is disabled.\n" ); -#endif #if defined(CONFIG_TREE_PREEMPT_RCU ) && !defined(CONFIG_RCU_CPU_STALL_VERBOSE )printk (KERN_INFO "\tVerbose stalled-CPUs detection is disabled.\n" );#endif
@@ -356,8 +352,6 @@ void __rcu_read_unlock(void) }EXPORT_SYMBOL_GPL (__rcu_read_unlock); -#ifdef CONFIG_RCU_CPU_STALL_DETECTOR -#ifdef CONFIG_RCU_CPU_STALL_VERBOSE /*
@@ -430,8 +424,6 @@ static void rcu_preempt_stall_reset(void) rcu_preempt_state.jiffies_stall = jiffies +ULONG_MAX /2 ; } -#endif /* #ifdef CONFIG_RCU_CPU_STALL_DETECTOR */ -/* * Check that the list of blocked tasks for the newly completed grace * period is in fact empty. It is a serious bug to complete a grace
@@ -862,8 +854,6 @@ static void rcu_report_unblock_qs_rnp(struct rcu_node *rnp, unsigned long flags)#endif /* #ifdef CONFIG_HOTPLUG_CPU */ -#ifdef CONFIG_RCU_CPU_STALL_DETECTOR -/* * Because preemptable RCU does not exist, we never have to check for * tasks blocked within RCU read-side critical sections.
@@ -888,8 +878,6 @@ static void rcu_preempt_stall_reset(void) { } -#endif /* #ifdef CONFIG_RCU_CPU_STALL_DETECTOR */ -/* * Because there is no preemptable RCU, there can be no readers blocked, * so there is no need to check for blocked tasks. So check only for
lib/Kconfig.debug +2 -28
@@ -875,22 +875,9 @@ config RCU_TORTURE_TEST_RUNNABLE Say N here if you want the RCU torture tests to start only after being manually enabled via /proc. -config RCU_CPU_STALL_DETECTOR - bool "Check for stalled CPUs delaying RCU grace periods" - depends on TREE_RCU || TREE_PREEMPT_RCU - default y - help - This option causes RCU to printk information on which - CPUs are delaying the current grace period, but only when - the grace period extends for excessive time periods. - - Say N if you want to disable such checks. - - Say Y if you are unsure. - config RCU_CPU_STALL_TIMEOUT int "RCU CPU stall timeout in seconds" - depends on RCU_CPU_STALL_DETECTOR + depends on TREE_RCU || TREE_PREEMPT_RCU range 3 300 default 60 help
@@ -899,22 +886,9 @@ config RCU_CPU_STALL_TIMEOUT RCU grace period persists, additional CPU stall warnings are printed at more widely spaced intervals. -config RCU_CPU_STALL_DETECTOR_RUNNABLE - bool "RCU CPU stall checking starts automatically at boot" - depends on RCU_CPU_STALL_DETECTOR - default y - help - If set, start checking for RCU CPU stalls immediately on - boot. Otherwise, RCU CPU stall checking must be manually - enabled. - - Say Y if you are unsure. - - Say N if you wish to suppress RCU CPU stall checking during boot. - config RCU_CPU_STALL_VERBOSE bool "Print additional per-task information for RCU_CPU_STALL_DETECTOR" - depends on RCU_CPU_STALL_DETECTOR && TREE_PREEMPT_RCU + depends on TREE_PREEMPT_RCU default y help This option causes RCU to printk detailed per-task information
Signature · 1 line
1.7.3.2
PATCH 2/86 rcu: Decrease memory-barrier usage based on semi-formal proof
In reply to Paul E. McKenneyCommit d09b62d fixed grace-period synchronization, but left some smp_mb() invocations in rcu_process_callbacks() that are no longer needed, but sheer paranoia prevented them from being removed. This commit removes them and provides a proof of correctness in their absence. It also adds a memory barrier to rcu_report_qs_rsp() immediately before the update to rsp->completed in order to handle the theoretical possibility that the compiler or CPU might move massive quantities of code into a lock-based critical section. This also proves that the sheer paranoia was not entirely unjustified, at least from a theoretical point of view.
In addition, the old dyntick-idle synchronization depended on the fact that grace periods were many milliseconds in duration, so that it could be assumed that no dyntick-idle CPU could reorder a memory reference across an entire grace period. Unfortunately for this design, the addition of expedited grace periods breaks this assumption, which has the unfortunate side-effect of requiring atomic operations in the functions that track dyntick-idle state for RCU. (There is some hope that the algorithms used in user-level RCU might be applied here, but some work is required to handle the NMIs that user-space applications can happily ignore. For the short term, better safe than sorry.)
This proof assumes that neither compiler nor CPU will allow a lock acquisition and release to be reordered, as doing so can result in deadlock. The proof is as follows:
1. A given CPU declares a quiescent state under the protection of
its leaf rcu_node's lock.
2. If there is more than one level of rcu_node hierarchy, the
last CPU to declare a quiescent state will also acquire the ->lock of the next rcu_node up in the hierarchy, but only after releasing the lower level's lock. The acquisition of this lock clearly cannot occur prior to the acquisition of the leaf node's lock.
3. Step 2 repeats until we reach the root rcu_node structure.
Please note again that only one lock is held at a time through this process. The acquisition of the root rcu_node's ->lock must occur after the release of that of the leaf rcu_node.
4. At this point, we set the ->completed field in the rcu_state
structure in rcu_report_qs_rsp(). However, if the rcu_node hierarchy contains only one rcu_node, then in theory the code preceding the quiescent state could leak into the critical section. We therefore precede the update of ->completed with a memory barrier. All CPUs will therefore agree that any updates preceding any report of a quiescent state will have happened before the update of ->completed.
5. Regardless of whether a new grace period is needed, rcu_start_gp()
will propagate the new value of ->completed to all of the leaf rcu_node structures, under the protection of each rcu_node's ->lock. If a new grace period is needed immediately, this propagation will occur in the same critical section that ->completed was set in, but courtesy of the memory barrier in #4 above, is still seen to follow any pre-quiescent-state activity.
6. When a given CPU invokes __rcu_process_gp_end(), it becomes
aware of the end of the old grace period and therefore makes any RCU callbacks that were waiting on that grace period eligible for invocation.
If this CPU is the same one that detected the end of the grace period, and if there is but a single rcu_node in the hierarchy, we will still be in the single critical section. In this case, the memory barrier in step #4 guarantees that all callbacks will be seen to execute after each CPU's quiescent state.
On the other hand, if this is a different CPU, it will acquire the leaf rcu_node's ->lock, and will again be serialized after each CPU's quiescent state for the old grace period.
On the strength of this proof, this commit therefore removes the memory barriers from rcu_process_callbacks() and adds one to rcu_report_qs_rsp(). The effect is to reduce the number of memory barriers by one and to reduce the frequency of execution from about once per scheduling tick per CPU to once per grace period.
--- Documentation/RCU/trace.txt | 48 +++++++--------- kernel/rcutree.c | 130 ++++++++++++++++++------------------------ kernel/rcutree.h | 9 +-- kernel/rcutree_plugin.h | 7 +- kernel/rcutree_trace.c | 12 ++-- 5 files changed, 88 insertions(+), 118 deletions(-)
Documentation/RCU/trace.txt +20 -28
@@ -21,23 +21,23 @@ rcu_pending() function decided that there was core RCU work to do). The output of "cat rcu/rcudata" looks as follows: rcu_sched: - 0 c=17829 g=17829 pq=1 pqc=17829 qp=0 dt=10951/1 dn=0 df=1101 of=0 ri=36 ql=0 b=10 - 1 c=17829 g=17829 pq=1 pqc=17829 qp=0 dt=16117/1 dn=0 df=1015 of=0 ri=0 ql=0 b=10 - 2 c=17829 g=17829 pq=1 pqc=17829 qp=0 dt=1445/1 dn=0 df=1839 of=0 ri=0 ql=0 b=10 - 3 c=17829 g=17829 pq=1 pqc=17829 qp=0 dt=6681/1 dn=0 df=1545 of=0 ri=0 ql=0 b=10 - 4 c=17829 g=17829 pq=1 pqc=17829 qp=0 dt=1003/1 dn=0 df=1992 of=0 ri=0 ql=0 b=10 - 5 c=17829 g=17830 pq=1 pqc=17829 qp=1 dt=3887/1 dn=0 df=3331 of=0 ri=4 ql=2 b=10 - 6 c=17829 g=17829 pq=1 pqc=17829 qp=0 dt=859/1 dn=0 df=3224 of=0 ri=0 ql=0 b=10 - 7 c=17829 g=17830 pq=0 pqc=17829 qp=1 dt=3761/1 dn=0 df=1818 of=0 ri=0 ql=2 b=10 + 0 c=17829 g=17829 pq=1 pqc=17829 qp=0 dt=10951/1/0 df=1101 of=0 ri=36 ql=0 b=10 + 1 c=17829 g=17829 pq=1 pqc=17829 qp=0 dt=16117/1/0 df=1015 of=0 ri=0 ql=0 b=10 + 2 c=17829 g=17829 pq=1 pqc=17829 qp=0 dt=1445/1/0 df=1839 of=0 ri=0 ql=0 b=10 + 3 c=17829 g=17829 pq=1 pqc=17829 qp=0 dt=6681/1/0 df=1545 of=0 ri=0 ql=0 b=10 + 4 c=17829 g=17829 pq=1 pqc=17829 qp=0 dt=1003/1/0 df=1992 of=0 ri=0 ql=0 b=10 + 5 c=17829 g=17830 pq=1 pqc=17829 qp=1 dt=3887/1/0 df=3331 of=0 ri=4 ql=2 b=10 + 6 c=17829 g=17829 pq=1 pqc=17829 qp=0 dt=859/1/0 df=3224 of=0 ri=0 ql=0 b=10 + 7 c=17829 g=17830 pq=0 pqc=17829 qp=1 dt=3761/1/0 df=1818 of=0 ri=0 ql=2 b=10 rcu_bh: - 0 c=-275 g=-275 pq=1 pqc=-275 qp=0 dt=10951/1 dn=0 df=0 of=0 ri=0 ql=0 b=10 - 1 c=-275 g=-275 pq=1 pqc=-275 qp=0 dt=16117/1 dn=0 df=13 of=0 ri=0 ql=0 b=10 - 2 c=-275 g=-275 pq=1 pqc=-275 qp=0 dt=1445/1 dn=0 df=15 of=0 ri=0 ql=0 b=10 - 3 c=-275 g=-275 pq=1 pqc=-275 qp=0 dt=6681/1 dn=0 df=9 of=0 ri=0 ql=0 b=10 - 4 c=-275 g=-275 pq=1 pqc=-275 qp=0 dt=1003/1 dn=0 df=15 of=0 ri=0 ql=0 b=10 - 5 c=-275 g=-275 pq=1 pqc=-275 qp=0 dt=3887/1 dn=0 df=15 of=0 ri=0 ql=0 b=10 - 6 c=-275 g=-275 pq=1 pqc=-275 qp=0 dt=859/1 dn=0 df=15 of=0 ri=0 ql=0 b=10 - 7 c=-275 g=-275 pq=1 pqc=-275 qp=0 dt=3761/1 dn=0 df=15 of=0 ri=0 ql=0 b=10 + 0 c=-275 g=-275 pq=1 pqc=-275 qp=0 dt=10951/1/0 df=0 of=0 ri=0 ql=0 b=10 + 1 c=-275 g=-275 pq=1 pqc=-275 qp=0 dt=16117/1/0 df=13 of=0 ri=0 ql=0 b=10 + 2 c=-275 g=-275 pq=1 pqc=-275 qp=0 dt=1445/1/0 df=15 of=0 ri=0 ql=0 b=10 + 3 c=-275 g=-275 pq=1 pqc=-275 qp=0 dt=6681/1/0 df=9 of=0 ri=0 ql=0 b=10 + 4 c=-275 g=-275 pq=1 pqc=-275 qp=0 dt=1003/1/0 df=15 of=0 ri=0 ql=0 b=10 + 5 c=-275 g=-275 pq=1 pqc=-275 qp=0 dt=3887/1/0 df=15 of=0 ri=0 ql=0 b=10 + 6 c=-275 g=-275 pq=1 pqc=-275 qp=0 dt=859/1/0 df=15 of=0 ri=0 ql=0 b=10 + 7 c=-275 g=-275 pq=1 pqc=-275 qp=0 dt=3761/1/0 df=15 of=0 ri=0 ql=0 b=10 The first section lists the rcu_data structures for rcu_sched, the second for rcu_bh. Note that CONFIG_TREE_PREEMPT_RCU kernels will have an
@@ -85,18 +85,10 @@ o "qp" indicates that RCU still expects a quiescent state from o "dt" is the current value of the dyntick counter that is incremented when entering or leaving dynticks idle state, either by the - scheduler or by irq. The number after the "/" is the interrupt - nesting depth when in dyntick-idle state, or one greater than - the interrupt-nesting depth otherwise. - - This field is displayed only for CONFIG_NO_HZ kernels. - -o "dn" is the current value of the dyntick counter that is incremented - when entering or leaving dynticks idle state via NMI. If both - the "dt" and "dn" values are even, then this CPU is in dynticks - idle mode and may be ignored by RCU. If either of these two - counters is odd, then RCU must be alert to the possibility of - an RCU read-side critical section running on this CPU. + scheduler or by irq. The number after the first "/" is the + interrupt nesting depth when in dyntick-idle state, or one + greater than the interrupt-nesting depth otherwise. The number + after the second "/" is the NMI nesting depth. This field is displayed only for CONFIG_NO_HZ kernels.
kernel/rcutree.c +56 -74
214 lines not on this page · raw message
kernel/rcutree.h +3 -6
@@ -84,11 +84,9 @@* Dynticks per-CPU state. */ struct rcu_dynticks { -int dynticks_nesting;/* Track nesting level, sort of. */ -int dynticks;/* Even value for dynticks-idle, else odd. */ -int dynticks_nmi;/* Even value for either dynticks-idle or */ -/* not in nmi handler, else odd. So this */ -/* remains even for nmi from irq handler. */ +int dynticks_nesting;/* Track irq/process nesting level. */ +int dynticks_nmi_nesting;/* Track NMI nesting level. */ +atomic_t dynticks;/* Even value for dynticks-idle, else odd. */ };/*
@@ -218,7 +216,6 @@ struct rcu_data {/* 3) dynticks interface. */ struct rcu_dynticks *dynticks;/* Shared per-CPU dynticks state. */ int dynticks_snap;/* Per-GP tracking for dynticks. */ -int dynticks_nmi_snap;/* Per-GP tracking for dynticks_nmi. */ #endif /* #ifdef CONFIG_NO_HZ */ /* 4) reasons this CPU needed to be kicked by force_quiescent_state */
kernel/rcutree_plugin.h +3 -4
@@ -1182,7 +1182,6 @@ int rcu_needs_cpu(int cpu) {int c =0 ;int snap; -int snap_nmi;int thatcpu;/* Check for being in the holdoff period. */
@@ -1193,10 +1192,10 @@ int rcu_needs_cpu(int cpu)for_each_online_cpu (thatcpu) {if (thatcpu == cpu)continue ; - snap =per_cpu (rcu_dynticks, thatcpu).dynticks; - snap_nmi =per_cpu (rcu_dynticks, thatcpu).dynticks_nmi; + snap =atomic_add_return (0 , &per_cpu (rcu_dynticks, + thatcpu).dynticks);smp_mb ();/* Order sampling of snap with end of grace period. */ -if (((snap &0x1 ) !=0 ) || ((snap_nmi &0x1 ) !=0 )) { +if ((snap &0x1 ) !=0 ) {per_cpu (rcu_dyntick_drain, cpu) =0 ;per_cpu (rcu_dyntick_holdoff, cpu) = jiffies -1 ;return rcu_needs_cpu_quick_check (cpu);
kernel/rcutree_trace.c +6 -6
@@ -57,10 +57,10 @@ static void print_one_rcu_data(struct seq_file *m, struct rcu_data *rdp) rdp->passed_quiesc, rdp->passed_quiesc_completed, rdp->qs_pending);#ifdef CONFIG_NO_HZ -seq_printf (m," dt=%d/%d dn=%d df=%lu" , - rdp->dynticks->dynticks, +seq_printf (m," dt=%d/%d/%d df=%lu" , +atomic_read (&rdp->dynticks->dynticks), rdp->dynticks->dynticks_nesting, - rdp->dynticks->dynticks_nmi, + rdp->dynticks->dynticks_nmi_nesting, rdp->dynticks_fqs);#endif /* #ifdef CONFIG_NO_HZ */ seq_printf (m," of=%lu ri=%lu" , rdp->offline_fqs, rdp->resched_ipi);
@@ -115,9 +115,9 @@ static void print_one_rcu_data_csv(struct seq_file *m, struct rcu_data *rdp) rdp->qs_pending);#ifdef CONFIG_NO_HZ seq_printf (m,",%d,%d,%d,%lu" , - rdp->dynticks->dynticks, +atomic_read (&rdp->dynticks->dynticks), rdp->dynticks->dynticks_nesting, - rdp->dynticks->dynticks_nmi, + rdp->dynticks->dynticks_nmi_nesting, rdp->dynticks_fqs);#endif /* #ifdef CONFIG_NO_HZ */ seq_printf (m,",%lu,%lu" , rdp->offline_fqs, rdp->resched_ipi);
@@ -130,7 +130,7 @@ static int show_rcudata_csv(struct seq_file *m, void *unused) {seq_puts (m,"\"CPU\",\"Online?\",\"c\",\"g\",\"pq\",\"pqc\",\"pq\"," );#ifdef CONFIG_NO_HZ -seq_puts (m,"\"dt\",\"dt nesting\",\"dn\",\"df\"," ); +seq_puts (m,"\"dt\",\"dt nesting\",\"dt NMI nesting\",\"df\"," );#endif /* #ifdef CONFIG_NO_HZ */ seq_puts (m,"\"of\",\"ri\",\"ql\",\"b\",\"ci\",\"co\",\"ca\"\n" );#ifdef CONFIG_TREE_PREEMPT_RCU
Signature · 1 line
1.7.3.2
PATCH 3/86 rcu: merge TREE_PREEPT_RCU blocked_tasks[] lists
In reply to Paul E. McKenneyFrom: Paul E. McKenney <[email protected]>
Combine the current TREE_PREEMPT_RCU ->blocked_tasks[] lists in the rcu_node structure into a single ->blkd_tasks list with ->gp_tasks and ->exp_tasks tail pointers. This is in preparation for RCU priority boosting, which will add a third dimension to the combinatorial explosion in the ->blocked_tasks[] case, but simply a third pointer in the new ->blkd_tasks case.
--- kernel/rcutree.c | 5 +- kernel/rcutree.h | 21 ++++-- kernel/rcutree_plugin.h | 163 ++++++++++++++++++++++++++++------------------- kernel/rcutree_trace.c | 11 +-- 4 files changed, 117 insertions(+), 83 deletions(-)
kernel/rcutree.c +1 -4
@@ -1901,10 +1901,7 @@ static void __init rcu_init_one(struct rcu_state *rsp, j / rsp->levelspread[i -1 ]; } rnp->level = i; -INIT_LIST_HEAD (&rnp->blocked_tasks[0 ]); -INIT_LIST_HEAD (&rnp->blocked_tasks[1 ]); -INIT_LIST_HEAD (&rnp->blocked_tasks[2 ]); -INIT_LIST_HEAD (&rnp->blocked_tasks[3 ]); +INIT_LIST_HEAD (&rnp->blkd_tasks); } }
kernel/rcutree.h +15 -6
@@ -107,7 +107,7 @@ struct rcu_node {/* an rcu_data structure, otherwise, each */ /* bit corresponds to a child rcu_node */ /* structure. */ -unsigned long expmask;/* Groups that have ->blocked_tasks[] */ +unsigned long expmask;/* Groups that have ->blkd_tasks */ /* elements that need to drain to allow the */ /* current expedited grace period to */ /* complete (only for TREE_PREEMPT_RCU). */
@@ -120,11 +120,20 @@ struct rcu_node {u8 grpnum;/* CPU/group number for next level up. */ u8 level;/* root is at level 0. */ struct rcu_node *parent; -struct list_head blocked_tasks[4 ]; -/* Tasks blocked in RCU read-side critsect. */ -/* Grace period number (->gpnum) x blocked */ -/* by tasks on the (x & 0x1) element of the */ -/* blocked_tasks[] array. */ +struct list_head blkd_tasks; +/* Tasks blocked in RCU read-side critical */ +/* section. Tasks are placed at the head */ +/* of this list and age towards the tail. */ +struct list_head *gp_tasks; +/* Pointer to the first task blocking the */ +/* current grace period, or NULL if there */ +/* is no such task. */ +struct list_head *exp_tasks; +/* Pointer to the first task blocking the */ +/* current expedited grace period, or NULL */ +/* if there is no such task. If there */ +/* is no current expedited grace period, */ +/* then there can cannot be any such task. */ }____cacheline_internodealigned_in_smp ;/*
kernel/rcutree_plugin.h +97 -66
299 lines not on this page · raw message
kernel/rcutree_trace.c +4 -7
@@ -161,7 +161,6 @@ static void print_one_rcu_state(struct seq_file *m, struct rcu_state *rsp) {unsigned long gpnum;int level =0 ; -int phase;struct rcu_node *rnp; gpnum = rsp->gpnum;
@@ -178,13 +177,11 @@ static void print_one_rcu_state(struct seq_file *m, struct rcu_state *rsp)seq_puts (m,"\n" ); level = rnp->level; } - phase = gpnum &0x1 ; -seq_printf (m,"%lx/%lx %c%c>%c%c %d:%d ^%d " , +seq_printf (m,"%lx/%lx %c%c>%c %d:%d ^%d " , rnp->qsmask, rnp->qsmaskinit, -"T." [list_empty (&rnp->blocked_tasks[phase])], -"E." [list_empty (&rnp->blocked_tasks[phase +2 ])], -"T." [list_empty (&rnp->blocked_tasks[!phase])], -"E." [list_empty (&rnp->blocked_tasks[!phase +2 ])], +".G" [rnp->gp_tasks !=NULL ], +".E" [rnp->exp_tasks !=NULL ], +".T" [!list_empty (&rnp->blkd_tasks)], rnp->grplo, rnp->grphi, rnp->grpnum); }seq_puts (m,"\n" );
Signature · 1 line
1.7.3.2
PATCH 4/86 rcu: Update documentation to reflect blocked_tasks[] merge
In reply to Paul E. McKenneyFrom: Paul E. McKenney <[email protected]>
--- Documentation/RCU/trace.txt | 29 ++++++++++++++++++----------- 1 files changed, 18 insertions(+), 11 deletions(-)
Documentation/RCU/trace.txt +18 -11
@@ -166,14 +166,14 @@ o "gpnum" is the number of grace periods that have started. It is The output of "cat rcu/rcuhier" looks as follows, with very long lines: c=6902 g=6903 s=2 jfq=3 j=72c7 nfqs=13142/nfqsng=0(13142) fqlh=6 -1/1 .>. 0:127 ^0 -3/3 .>. 0:35 ^0 0/0 .>. 36:71 ^1 0/0 .>. 72:107 ^2 0/0 .>. 108:127 ^3 -3/3f .>. 0:5 ^0 2/3 .>. 6:11 ^1 0/0 .>. 12:17 ^2 0/0 .>. 18:23 ^3 0/0 .>. 24:29 ^4 0/0 .>. 30:35 ^5 0/0 .>. 36:41 ^0 0/0 .>. 42:47 ^1 0/0 .>. 48:53 ^2 0/0 .>. 54:59 ^3 0/0 .>. 60:65 ^4 0/0 .>. 66:71 ^5 0/0 .>. 72:77 ^0 0/0 .>. 78:83 ^1 0/0 .>. 84:89 ^2 0/0 .>. 90:95 ^3 0/0 .>. 96:101 ^4 0/0 .>. 102:107 ^5 0/0 .>. 108:113 ^0 0/0 .>. 114:119 ^1 0/0 .>. 120:125 ^2 0/0 .>. 126:127 ^3 +1/1 ..>. 0:127 ^0 +3/3 ..>. 0:35 ^0 0/0 ..>. 36:71 ^1 0/0 ..>. 72:107 ^2 0/0 ..>. 108:127 ^3 +3/3f ..>. 0:5 ^0 2/3 ..>. 6:11 ^1 0/0 ..>. 12:17 ^2 0/0 ..>. 18:23 ^3 0/0 ..>. 24:29 ^4 0/0 ..>. 30:35 ^5 0/0 ..>. 36:41 ^0 0/0 ..>. 42:47 ^1 0/0 ..>. 48:53 ^2 0/0 ..>. 54:59 ^3 0/0 ..>. 60:65 ^4 0/0 ..>. 66:71 ^5 0/0 ..>. 72:77 ^0 0/0 ..>. 78:83 ^1 0/0 ..>. 84:89 ^2 0/0 ..>. 90:95 ^3 0/0 ..>. 96:101 ^4 0/0 ..>. 102:107 ^5 0/0 ..>. 108:113 ^0 0/0 ..>. 114:119 ^1 0/0 ..>. 120:125 ^2 0/0 ..>. 126:127 ^3 rcu_bh: c=-226 g=-226 s=1 jfq=-5701 j=72c7 nfqs=88/nfqsng=0(88) fqlh=0 -0/1 .>. 0:127 ^0 -0/3 .>. 0:35 ^0 0/0 .>. 36:71 ^1 0/0 .>. 72:107 ^2 0/0 .>. 108:127 ^3 -0/3f .>. 0:5 ^0 0/3 .>. 6:11 ^1 0/0 .>. 12:17 ^2 0/0 .>. 18:23 ^3 0/0 .>. 24:29 ^4 0/0 .>. 30:35 ^5 0/0 .>. 36:41 ^0 0/0 .>. 42:47 ^1 0/0 .>. 48:53 ^2 0/0 .>. 54:59 ^3 0/0 .>. 60:65 ^4 0/0 .>. 66:71 ^5 0/0 .>. 72:77 ^0 0/0 .>. 78:83 ^1 0/0 .>. 84:89 ^2 0/0 .>. 90:95 ^3 0/0 .>. 96:101 ^4 0/0 .>. 102:107 ^5 0/0 .>. 108:113 ^0 0/0 .>. 114:119 ^1 0/0 .>. 120:125 ^2 0/0 .>. 126:127 ^3 +0/1 ..>. 0:127 ^0 +0/3 ..>. 0:35 ^0 0/0 ..>. 36:71 ^1 0/0 ..>. 72:107 ^2 0/0 ..>. 108:127 ^3 +0/3f ..>. 0:5 ^0 0/3 ..>. 6:11 ^1 0/0 ..>. 12:17 ^2 0/0 ..>. 18:23 ^3 0/0 ..>. 24:29 ^4 0/0 ..>. 30:35 ^5 0/0 ..>. 36:41 ^0 0/0 ..>. 42:47 ^1 0/0 ..>. 48:53 ^2 0/0 ..>. 54:59 ^3 0/0 ..>. 60:65 ^4 0/0 ..>. 66:71 ^5 0/0 ..>. 72:77 ^0 0/0 ..>. 78:83 ^1 0/0 ..>. 84:89 ^2 0/0 ..>. 90:95 ^3 0/0 ..>. 96:101 ^4 0/0 ..>. 102:107 ^5 0/0 ..>. 108:113 ^0 0/0 ..>. 114:119 ^1 0/0 ..>. 120:125 ^2 0/0 ..>. 126:127 ^3 This is once again split into "rcu_sched" and "rcu_bh" portions, and CONFIG_TREE_PREEMPT_RCU kernels will again have an additional
@@ -232,13 +232,20 @@ o Each element of the form "1/1 0:127 ^0" represents one struct current grace period. o The characters separated by the ">" indicate the state - of the blocked-tasks lists. A "T" preceding the ">" + of the blocked-tasks lists. A "G" preceding the ">" indicates that at least one task blocked in an RCU read-side critical section blocks the current grace - period, while a "." preceding the ">" indicates otherwise. - The character following the ">" indicates similarly for - the next grace period. A "T" should appear in this - field only for rcu-preempt. + period, while a "E" preceding the ">" indicates that + at least one task blocked in an RCU read-side critical + section blocks the current expedited grace period. + A "T" character following the ">" indicates that at + least one task is blocked within an RCU read-side + critical section, regardless of whether any current + grace period (expedited or normal) is inconvenienced. + A "." character appears if the corresponding condition + does not hold, so that "..>." indicates that no tasks + are blocked. In contrast, "GE>T" indicates maximal + inconvenience from blocked tasks. o The numbers separated by the ":" are the range of CPUs served by this struct rcu_node. This can be helpful
Signature · 1 line
1.7.3.2
PATCH 5/86 rcu: move TREE_RCU from softirq to kthread
In reply to Paul E. McKenneyFrom: Paul E. McKenney <[email protected]>
If RCU priority boosting is to be meaningful, callback invocation must be boosted in addition to preempted RCU readers. Otherwise, in presence of CPU real-time threads, the grace period ends, but the callbacks don't get invoked. If the callbacks don't get invoked, the associated memory doesn't get freed, so the system is still subject to OOM.
But it is not reasonable to priority-boost RCU_SOFTIRQ, so this commit moves the callback invocations to a kthread, which can be boosted easily.
Also add comments and properly synchronized all accesses to rcu_cpu_kthread_task, as suggested by Lai Jiangshan.
--- Documentation/filesystems/proc.txt | 1 - include/linux/interrupt.h | 1 - include/trace/events/irq.h | 3 +- kernel/rcutree.c | 340 ++++++++++++++++++++++++++++++++++- kernel/rcutree.h | 8 + kernel/rcutree_plugin.h | 4 +- kernel/softirq.c | 2 +- tools/perf/util/trace-event-parse.c | 1 - 8 files changed, 348 insertions(+), 12 deletions(-)
Documentation/filesystems/proc.txt +0 -1
@@ -836,7 +836,6 @@ Provides counts of softirq handlers serviced since boot time, for each cpu. TASKLET: 0 0 0 290 SCHED: 27035 26983 26971 26746 HRTIMER: 0 0 0 0 - RCU: 1678 1769 2178 2250 1.3 IDE devices in /proc/ide
include/linux/interrupt.h +0 -1
@@ -414,7 +414,6 @@ enumTASKLET_SOFTIRQ ,SCHED_SOFTIRQ ,HRTIMER_SOFTIRQ , -RCU_SOFTIRQ ,/* Preferable RCU should always be the last softirq */ NR_SOFTIRQS };
include/trace/events/irq.h +1 -2
@@ -20,8 +20,7 @@ struct softirq_action;softirq_name (BLOCK_IOPOLL ), \softirq_name (TASKLET ), \softirq_name (SCHED ), \ -softirq_name (HRTIMER ), \ - softirq_name(RCU)) + softirq_name(HRTIMER))/** * irq_handler_entry - called immediately before the irq action handler
kernel/rcutree.c +336 -4
417 lines not on this page · raw message
kernel/rcutree.h +8 -0
@@ -111,6 +111,7 @@ struct rcu_node {/* elements that need to drain to allow the */ /* current expedited grace period to */ /* complete (only for TREE_PREEMPT_RCU). */ +unsigned long wakemask;/* CPUs whose kthread needs to be awakened. */ unsigned long qsmaskinit;/* Per-GP initial value for qsmask & expmask. */ unsigned long grpmask;/* Mask to apply to parent qsmask. */
@@ -134,6 +135,13 @@ struct rcu_node {/* if there is no such task. If there */ /* is no current expedited grace period, */ /* then there can cannot be any such task. */ +struct task_struct *node_kthread_task; +/* kthread that takes care of this rcu_node */ +/* structure, for example, awakening the */ +/* per-CPU kthreads as needed. */ +wait_queue_head_t node_wq; +/* Wait queue on which to park the per-node */ +/* kthread. */ }____cacheline_internodealigned_in_smp ;/*
kernel/rcutree_plugin.h +2 -2
@@ -1206,7 +1206,7 @@ static DEFINE_PER_CPU(unsigned long, rcu_dyntick_holdoff);* * Because it is not legal to invoke rcu_process_callbacks() with irqs * disabled, we do one pass of force_quiescent_state(), then do a -* raise_softirq() to cause rcu_process_callbacks() to be invoked later. +* invoke_rcu_kthread() to cause rcu_process_callbacks() to be invoked later. * The per-cpu rcu_dyntick_drain variable controls the sequencing. */ int rcu_needs_cpu (int cpu)
@@ -1257,7 +1257,7 @@ int rcu_needs_cpu(int cpu)/* If RCU callbacks are still pending, RCU still needs this CPU. */ if (c) -raise_softirq (RCU_SOFTIRQ ); +invoke_rcu_kthread ();return c; }
kernel/softirq.c +1 -1
@@ -58,7 +58,7 @@ DEFINE_PER_CPU(struct task_struct *, ksoftirqd);char *softirq_to_name[NR_SOFTIRQS ] = {"HI" ,"TIMER" ,"NET_TX" ,"NET_RX" ,"BLOCK" ,"BLOCK_IOPOLL" , -"TASKLET" ,"SCHED" ,"HRTIMER" ,"RCU" +"TASKLET" ,"SCHED" ,"HRTIMER" };/*
tools/perf/util/trace-event-parse.c +0 -1
@@ -2187,7 +2187,6 @@ static const struct flag flags[] = { { "TASKLET_SOFTIRQ", 6 }, { "SCHED_SOFTIRQ", 7 }, { "HRTIMER_SOFTIRQ", 8 }, - { "RCU_SOFTIRQ", 9 }, { "HRTIMER_NORESTART", 0 }, { "HRTIMER_RESTART", 1 },
Signature · 1 line
1.7.3.2
Re: [PATCH tip/core/rcu 05/86] rcu: move TREE_RCU from softirq to kthread
Quoted 17 lines · Paul E. McKenney
From: Paul E. McKenney <[email protected]>
If RCU priority boosting is to be meaningful, callback invocation must be boosted in addition to preempted RCU readers. Otherwise, in presence of CPU real-time threads, the grace period ends, but the callbacks don't get invoked. If the callbacks don't get invoked, the associated memory doesn't get freed, so the system is still subject to OOM.
But it is not reasonable to priority-boost
RCU_SOFTIRQ, so this commit moves the callback invocations to a kthread, which can be boosted easily.Also add comments and properly synchronized all accesses to
rcu_cpu_kthread_task, as suggested by Lai Jiangshan.Signed-off-by Paul E. McKenney <[email protected]>Signed-off-by Paul E. McKenney <[email protected]>---
[snip]
kernel/rcutree.c static void rcu_process_callbacks(struct softirq_action *unused) · line 1472
Quoted 12 lines
+ * Drop to non-real-time priority and yield, but only after posting a
+ * timer that will cause us to regain our real-time priority if we
+ * remain preempted. Either way, we restore our real-time priority
+ * before returning.
+ */kernel/rcutree.c +7
-0+static void rcu_yield (int cpu) +{ + struct rcu_data *rdp = per_cpu_ptr(rcu_sched_state.rda, cpu); + struct sched_param sp; + struct timer_list yield_timer; + + setup_timer(&yield_timer, rcu_cpu_kthread_timer, (unsigned long)rdp);
setup_timer_on_stack() should be used here :)
Thanks,
Yong
Signature · 1 line
Only stand for myself
Re: [PATCH tip/core/rcu 05/86] rcu: move TREE_RCU from softirq to kthread
Quoted 20 lines · Yong Zhang
Quoted 17 lines · Paul E. McKenney
From: Paul E. McKenney <[email protected]>
If RCU priority boosting is to be meaningful, callback invocation must be boosted in addition to preempted RCU readers. Otherwise, in presence of CPU real-time threads, the grace period ends, but the callbacks don't get invoked. If the callbacks don't get invoked, the associated memory doesn't get freed, so the system is still subject to OOM.
But it is not reasonable to priority-boost
RCU_SOFTIRQ, so this commit moves the callback invocations to a kthread, which can be boosted easily.Also add comments and properly synchronized all accesses to
rcu_cpu_kthread_task, as suggested by Lai Jiangshan.Signed-off-by Paul E. McKenney <[email protected]>Signed-off-by Paul E. McKenney <[email protected]>---
[snip]
Quoted 14 lines
kernel/rcutree.c static void rcu_process_callbacks(struct softirq_action *unused) · line 1472
Quoted 12 lines
+ * Drop to non-real-time priority and yield, but only after posting a
+ * timer that will cause us to regain our real-time priority if we
+ * remain preempted. Either way, we restore our real-time priority
+ * before returning.
+ */kernel/rcutree.c +7
-0+static void rcu_yield (int cpu) +{ + struct rcu_data *rdp = per_cpu_ptr(rcu_sched_state.rda, cpu); + struct sched_param sp; + struct timer_list yield_timer; + + setup_timer(&yield_timer, rcu_cpu_kthread_timer, (unsigned long)rdp);
setup_timer_on_stack()should be used here :)
Good eyes!!! Fixed, will update the -rcu git tree.
Thanx, Paul
PATCH 6/86 rcu: priority boosting for TREE_PREEMPT_RCU
In reply to Paul E. McKenneyFrom: Paul E. McKenney <[email protected]>
Add priority boosting for TREE_PREEMPT_RCU, similar to that for TINY_PREEMPT_RCU. This is enabled by the default-off RCU_BOOST kernel parameter. The priority to which to boost preempted RCU readers is controlled by the RCU_BOOST_PRIO kernel parameter (defaulting to real-time priority 1) and the time to wait before boosting the readers who are blocking a given grace period is controlled by the RCU_BOOST_DELAY kernel parameter (defaulting to 500 milliseconds).
--- init/Kconfig | 2 +- kernel/rcutree.c | 115 ++++++++++++------ kernel/rcutree.h | 31 +++++- kernel/rcutree_plugin.h | 314 +++++++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 411 insertions(+), 51 deletions(-)
init/Kconfig +1 -1
@@ -485,7 +485,7 @@ config TREE_RCU_TRACE config RCU_BOOST bool "Enable RCU priority boosting" - depends on RT_MUTEXES && TINY_PREEMPT_RCU + depends on RT_MUTEXES && PREEMPT_RCU default n help This option boosts the priority of preempted RCU readers that
kernel/rcutree.c +77 -38
283 lines not on this page · raw message
kernel/rcutree.h +30 -1
@@ -135,6 +135,24 @@ struct rcu_node {/* if there is no such task. If there */ /* is no current expedited grace period, */ /* then there can cannot be any such task. */ +#ifdef CONFIG_RCU_BOOST +struct list_head *boost_tasks; +/* Pointer to first task that needs to be */ +/* priority boosted, or NULL if no priority */ +/* boosting is needed for this rcu_node */ +/* structure. If there are no tasks */ +/* queued on this rcu_node structure that */ +/* are blocking the current grace period, */ +/* there can be no such task. */ +unsigned long boost_time; +/* When to start boosting (jiffies). */ +struct task_struct *boost_kthread_task; +/* kthread that takes care of priority */ +/* boosting for this rcu_node structure. */ +wait_queue_head_t boost_wq; +/* Wait queue on which to park the boost */ +/* kthread. */ +#endif /* #ifdef CONFIG_RCU_BOOST */ struct task_struct *node_kthread_task;/* kthread that takes care of this rcu_node */ /* structure, for example, awakening the */
@@ -365,7 +383,7 @@ DECLARE_PER_CPU(struct rcu_data, rcu_preempt_data);static void rcu_bootup_announce (void );long rcu_batches_completed (void );static void rcu_preempt_note_context_switch (int cpu); -static int rcu_preempted_readers (struct rcu_node *rnp); +static int rcu_preempt_blocked_readers_cgp (struct rcu_node *rnp);#ifdef CONFIG_HOTPLUG_CPU static void rcu_report_unblock_qs_rnp (struct rcu_node *rnp,unsigned long flags);
@@ -392,5 +410,16 @@ static void __cpuinit rcu_preempt_init_percpu_data(int cpu);static void rcu_preempt_send_cbs_to_online (void );static void __init __rcu_init_preempt (void );static void rcu_needs_cpu_flush (void ); +static void __init rcu_init_boost_waitqueue (struct rcu_node *rnp); +static void rcu_initiate_boost (struct rcu_node *rnp); +static void rcu_boost_kthread_setaffinity (struct rcu_node *rnp, +cpumask_var_t cm); +static void rcu_preempt_boost_start_gp (struct rcu_node *rnp); +static int __cpuinit rcu_spawn_one_boost_kthread (struct rcu_state *rsp, +struct rcu_node *rnp, +int rnp_index); +#ifdef CONFIG_HOTPLUG_CPU +static void rcu_stop_boost_kthread (struct rcu_node *rnp); +#endif /* #ifdef CONFIG_HOTPLUG_CPU */ #endif /* #ifndef RCU_TREE_NONCORE */
kernel/rcutree_plugin.h +303 -11
424 lines not on this page · raw message
Signature · 1 line
1.7.3.2
PATCH 7/86 rcu: Force per-rcu_node kthreads off of the outgoing CPU
In reply to Paul E. McKenneyFrom: Paul E. McKenney <[email protected]>
The scheduler has had some heartburn in the past when too many real-time kthreads were affinitied to the outgoing CPU. So, this commit lightens the load by forcing the per-rcu_node and the boost kthreads off of the outgoing CPU. Note that RCU's per-CPU kthread remains on the outgoing CPU until the bitter end, as it must in order to preserve correctness.
Also avoid disabling hardirqs across calls to set_cpus_allowed_ptr(), given that this function can block.
--- kernel/rcutree.c | 24 +++++++++++++++++++----- kernel/rcutree_plugin.h | 8 +++++--- 2 files changed, 24 insertions(+), 8 deletions(-)
kernel/rcutree.c +19 -5
@@ -95,7 +95,7 @@ static DEFINE_PER_CPU(wait_queue_head_t, rcu_cpu_wq); static DEFINE_PER_CPU(char, rcu_cpu_has_work);static char rcu_kthreads_spawnable; -static void rcu_node_kthread_setaffinity (struct rcu_node *rnp); +static void rcu_node_kthread_setaffinity (struct rcu_node *rnp,int outgoingcpu);static void invoke_rcu_cpu_kthread (void );#define RCU_KTHREAD_PRIO 1/* RT priority for per-CPU kthreads. */
@@ -1099,7 +1099,7 @@ static void __rcu_offline_cpu(int cpu, struct rcu_state *rsp)kthread_stop (t);rcu_stop_boost_kthread (rnp); }else -rcu_node_kthread_setaffinity (rnp); +rcu_node_kthread_setaffinity (rnp,-1 ); }/*
@@ -1644,8 +1644,12 @@ static int rcu_node_kthread(void *arg)* Set the per-rcu_node kthread's affinity to cover all CPUs that are * served by the rcu_node in question. The CPU hotplug lock is still * held, so the value of rnp->qsmaskinit will be stable. +* +* We don't include outgoingcpu in the affinity set, use -1 if there is +* no outgoing CPU. If there are no CPUs left in the affinity set, +* this function allows the kthread to execute on any CPU. */ -static void rcu_node_kthread_setaffinity (struct rcu_node *rnp) +static void rcu_node_kthread_setaffinity (struct rcu_node *rnp,int outgoingcpu) {cpumask_var_t cm;int cpu;
@@ -1657,8 +1661,14 @@ static void rcu_node_kthread_setaffinity(struct rcu_node *rnp)return ;cpumask_clear (cm);for (cpu = rnp->grplo; cpu <= rnp->grphi; cpu++, mask >>=1 ) -if (mask &0x1 ) +if ((mask &0x1 ) && cpu != outgoingcpu)cpumask_set_cpu (cpu, cm); +if (cpumask_weight (cm) ==0 ) { +cpumask_setall (cm); +for (cpu = rnp->grplo; cpu <= rnp->grphi; cpu++) +cpumask_clear_cpu (cpu, cm); +WARN_ON_ONCE (cpumask_weight (cm) ==0 ); + }set_cpus_allowed_ptr (rnp->node_kthread_task, cm);rcu_boost_kthread_setaffinity (rnp, cm);free_cpumask_var (cm);
@@ -2154,7 +2164,11 @@ static int __cpuinit rcu_cpu_notify(struct notifier_block *self,rcu_online_kthreads (cpu);break ;case CPU_ONLINE : -rcu_node_kthread_setaffinity (rnp); +case CPU_DOWN_FAILED : +rcu_node_kthread_setaffinity (rnp,-1 ); +break ; +case CPU_DOWN_PREPARE : +rcu_node_kthread_setaffinity (rnp, cpu);break ;case CPU_DYING :case CPU_DYING_FROZEN :
kernel/rcutree_plugin.h +5 -3
@@ -1212,17 +1212,19 @@ static void rcu_initiate_boost(struct rcu_node *rnp) } } +/* +* Set the affinity of the boost kthread. The CPU-hotplug locks are +* held, so no one should be messing with the existence of the boost +* kthread. +*/ static void rcu_boost_kthread_setaffinity (struct rcu_node *rnp,cpumask_var_t cm) { -unsigned long flags;struct task_struct *t; -raw_spin_lock_irqsave (&rnp->lock, flags); t = rnp->boost_kthread_task;if (t !=NULL )set_cpus_allowed_ptr (rnp->boost_kthread_task, cm); -raw_spin_unlock_irqrestore (&rnp->lock, flags); }#define RCU_BOOST_DELAY_JIFFIES DIV_ROUND_UP(CONFIG_RCU_BOOST_DELAY * HZ, 1000)
Signature · 1 line
1.7.3.2
Josh Triplett
maintainerRe: [PATCH tip/core/rcu 07/86] rcu: Force per-rcu_node kthreads off of the outgoing CPU
Quoted 10 lines · Paul E. McKenney
From: Paul E. McKenney <[email protected]>
The scheduler has had some heartburn in the past when too many real-time kthreads were affinitied to the outgoing CPU. So, this commit lightens the load by forcing the per-rcu_node and the boost kthreads off of the outgoing CPU. Note that RCU's per-CPU kthread remains on the outgoing CPU until the bitter end, as it must in order to preserve correctness.
Also avoid disabling hardirqs across calls to
set_cpus_allowed_ptr(), given that this function can block.
This seems like two separate changes in one patch. The change to kernel/rcutree_plugin.h seems entirely separable from the change to kernel/rcutree.c here.
Quoted 2 lines
Signed-off-by Paul E. McKenney <[email protected]>Signed-off-by Paul E. McKenney <[email protected]>
Heh, amusingly this actually seems meaningful, if you intend it as a "role" approval.
- Josh Triplett
Re: [PATCH tip/core/rcu 07/86] rcu: Force per-rcu_node kthreads off of the outgoing CPU
Quoted 16 lines · Josh Triplett
Quoted 10 lines · Paul E. McKenney
From: Paul E. McKenney <[email protected]>
The scheduler has had some heartburn in the past when too many real-time kthreads were affinitied to the outgoing CPU. So, this commit lightens the load by forcing the per-rcu_node and the boost kthreads off of the outgoing CPU. Note that RCU's per-CPU kthread remains on the outgoing CPU until the bitter end, as it must in order to preserve correctness.
Also avoid disabling hardirqs across calls to
set_cpus_allowed_ptr(), given that this function can block.This seems like two separate changes in one patch. The change to
kernel/rcutree_plugin.hseems entirely separable from the change tokernel/rcutree.chere.
Quoted 5 lines
Quoted 2 lines
Signed-off-by Paul E. McKenney <[email protected]>Signed-off-by Paul E. McKenney <[email protected]>Heh, amusingly this actually seems meaningful, if you intend it as a "role" approval.
Yep, that is the intent! ;-)
Thanx, Paul
PATCH 8/86 rcu: put per-CPU kthread at non-RT priority during CPU hotplug operations
In reply to Paul E. McKenneyFrom: Paul E. McKenney <[email protected]>
If you are doing CPU hotplug operations, it is best not to have CPU-bound realtime tasks running CPU-bound on the outgoing CPU. So this commit makes per-CPU kthreads run at non-realtime priority during that time.
--- kernel/rcutree.c | 26 ++++++++++++++++++++++++++ 1 files changed, 26 insertions(+), 0 deletions(-)
kernel/rcutree.c +26 -0
@@ -1464,6 +1464,30 @@ static void invoke_rcu_node_kthread(struct rcu_node *rnp) }/* +* Set the specified CPU's kthread to run RT or not, as specified by +* the to_rt argument. The CPU-hotplug locks are held, so the task +* is not going away. +*/ +static void rcu_cpu_kthread_setrt (int cpu,int to_rt) +{ +int policy; +struct sched_param sp; +struct task_struct *t; + + t =per_cpu (rcu_cpu_kthread_task, cpu); +if (t ==NULL ) +return ; +if (to_rt) { + policy =SCHED_FIFO ; + sp.sched_priority =RCU_KTHREAD_PRIO ; + }else { + policy =SCHED_NORMAL ; + sp.sched_priority =0 ; + } +sched_setscheduler_nocheck (t, policy, &sp); +} + +/* * Timer handler to initiate the waking up of per-CPU kthreads that * have yielded the CPU due to excess numbers of RCU callbacks. * We wake up the per-rcu_node kthread, which in turn will wake up
@@ -2166,9 +2190,11 @@ static int __cpuinit rcu_cpu_notify(struct notifier_block *self,case CPU_ONLINE :case CPU_DOWN_FAILED :rcu_node_kthread_setaffinity (rnp,-1 ); +rcu_cpu_kthread_setrt (cpu,1 );break ;case CPU_DOWN_PREPARE :rcu_node_kthread_setaffinity (rnp, cpu); +rcu_cpu_kthread_setrt (cpu,0 );break ;case CPU_DYING :case CPU_DYING_FROZEN :
Signature · 1 line
1.7.3.2
PATCH 9/86 rcu: avoid hammering sched with yet another bound RT kthread
In reply to Paul E. McKenneyFrom: Paul E. McKenney <[email protected]>
The scheduler does not appear to take kindly to having multiple real-time threads bound to a CPU that is going offline. So this commit is a temporary hack-around to avoid that happening.
--- kernel/rcutorture.c | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-)
kernel/rcutorture.c +3 -3
@@ -163,11 +163,11 @@ static int stutter_pause_test;#endif int rcutorture_runnable =RCUTORTURE_RUNNABLE_INIT ; -#ifdef CONFIG_RCU_BOOST +#if defined(CONFIG_RCU_BOOST ) && !defined(CONFIG_HOTPLUG_CPU )#define rcu_can_boost () 1 -#else /* #ifdef CONFIG_RCU_BOOST */ +#else /* #if defined(CONFIG_RCU_BOOST) && !defined(CONFIG_HOTPLUG_CPU) */ #define rcu_can_boost () 0 -#endif /* #else #ifdef CONFIG_RCU_BOOST */ +#endif /* #else #if defined(CONFIG_RCU_BOOST) && !defined(CONFIG_HOTPLUG_CPU) */ static unsigned long boost_starttime;/* jiffies of next boost test start. */ DEFINE_MUTEX (boost_mutex);/* protect setting boost_starttime */
Signature · 1 line
1.7.3.2
Josh Triplett
maintainerRe: [PATCH tip/core/rcu 09/86] rcu: avoid hammering sched with yet another bound RT kthread
Quoted 18 lines · Paul E. McKenney
From: Paul E. McKenney <[email protected]>
The scheduler does not appear to take kindly to having multiple real-time threads bound to a CPU that is going offline. So this commit is a temporary hack-around to avoid that happening.
Signed-off-by Paul E. McKenney <[email protected]>Signed-off-by Paul E. McKenney <[email protected]>--- kernel/rcutorture.c | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-)kernel/rcutorture.c +0
-0@@ -163,11 +163,11 @@ static int stutter_pause_test;#endif
kernel/rcutorture.c static int stutter_pause_test; · line 170
Quoted 10 lines
kernel/rcutorture.c +3
-3int rcutorture_runnable =RCUTORTURE_RUNNABLE_INIT ; -#ifdef CONFIG_RCU_BOOST +#if defined(CONFIG_RCU_BOOST ) && !defined(CONFIG_HOTPLUG_CPU )#define rcu_can_boost () 1 -#else /* #ifdef CONFIG_RCU_BOOST */ +#else /* #if defined(CONFIG_RCU_BOOST) && !defined(CONFIG_HOTPLUG_CPU) */ #define rcu_can_boost () 0 -#endif /* #else #ifdef CONFIG_RCU_BOOST */ +#endif /* #else #if defined(CONFIG_RCU_BOOST) && !defined(CONFIG_HOTPLUG_CPU) */
So, this disables boosting entirely when CONFIG_HOTPLUG_CPU=y? Other patches in this series take various steps to un-bound or un-realtime the RCU threads on a CPU when it goes offline; do those fix this problem? Which patch disables this hack-around?
Also, it seems like your patch series introduces boosting, and then disables it for CONFIG_HOTPLUG_CPU=y, which suggests that in the middle of this patch series you can have a broken kernel if you build with CONFIG_HOTPLUG_CPU=y and CONFIG_RCU_BOOST=y. Please consider reordering the patches (and possibly merging this patch into the original introduction of RCU boosting) to make sure that kernels in the middle of the patch series don't have this potential brokenness.
- Josh Triplett
Re: [PATCH tip/core/rcu 09/86] rcu: avoid hammering sched with yet another bound RT kthread
Quoted 21 lines · Josh Triplett
Quoted 20 lines · Paul E. McKenney
From: Paul E. McKenney <[email protected]>
The scheduler does not appear to take kindly to having multiple real-time threads bound to a CPU that is going offline. So this commit is a temporary hack-around to avoid that happening.
Signed-off-by Paul E. McKenney <[email protected]>Signed-off-by Paul E. McKenney <[email protected]>--- kernel/rcutorture.c | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-)kernel/rcutorture.c +0
-0@@ -163,11 +163,11 @@ static int stutter_pause_test;#endif int rcutorture_runnable =RCUTORTURE_RUNNABLE_INIT ;
Quoted 13 lines
kernel/rcutorture.c static int stutter_pause_test; · line 170
Quoted 8 lines
kernel/rcutorture.c +3
-3-#ifdef CONFIG_RCU_BOOST +#if defined(CONFIG_RCU_BOOST ) && !defined(CONFIG_HOTPLUG_CPU )#define rcu_can_boost () 1 -#else /* #ifdef CONFIG_RCU_BOOST */ +#else /* #if defined(CONFIG_RCU_BOOST) && !defined(CONFIG_HOTPLUG_CPU) */ #define rcu_can_boost () 0 -#endif /* #else #ifdef CONFIG_RCU_BOOST */ +#endif /* #else #if defined(CONFIG_RCU_BOOST) && !defined(CONFIG_HOTPLUG_CPU) */ So, this disables boosting entirely when
CONFIG_HOTPLUG_CPU=y? Other patches in this series take various steps to un-bound or un-realtime the RCU threads on a CPU when it goes offline; do those fix this problem? Which patch disables this hack-around?
No, it just flips the default. You can still test boosting in this case by specifying test_boost=2 when loading rcutorture.
As near as I can tell, the sensitivity is a scheduler bug. Once this is fixed, I will revert this patch.
http://comments.gmane.org/gmane.linux.kernel/1131000
Quoted 7 lines
Also, it seems like your patch series introduces boosting, and then disables it for
CONFIG_HOTPLUG_CPU=y, which suggests that in the middle of this patch series you can have a broken kernel if you build withCONFIG_HOTPLUG_CPU=yandCONFIG_RCU_BOOST=y. Please consider reordering the patches (and possibly merging this patch into the original introduction of RCU boosting) to make sure that kernels in the middle of the patch series don't have this potential brokenness.
I need to have the patch separate so that I can revert it later, when the underlying problem is fixed. And if someone is bisecting based on running rcutorture with priority boosting, they are going to have to handle the introduction of priority boosting specially anyway -- otherwise, they get artifacts when testing before the introduction of RCU_TREE priority boosting.
So, while I definitely am a fan of bisectability, I don't believe that the location of this patch introduces any additional problems.
Thanx, Paul
PATCH 10/86 rcu: eliminate unused boosting statistics
In reply to Paul E. McKenneyFrom: Paul E. McKenney <[email protected]>
The n_rcu_torture_boost_allocerror and n_rcu_torture_boost_afferror statistics are not actually incremented anymore, so eliminate them.
--- kernel/rcutorture.c | 4 +--- 1 files changed, 1 insertions(+), 3 deletions(-)
kernel/rcutorture.c +1 -3
@@ -1067,7 +1067,7 @@ rcu_torture_printk(char *page) cnt +=sprintf (&page[cnt],"%s%s " , torture_type,TORTURE_FLAG ); cnt += sprintf(&page[cnt], "rtc: %p ver: %ld tfle: %d rta: %d rtaf: %d rtf: %d " - "rtmbe: %d rtbke: %ld rtbre: %ld rtbae: %ld rtbafe: %ld " + "rtmbe: %d rtbke: %ld rtbre: %ld " "rtbf: %ld rtb: %ld nt: %ld", rcu_torture_current, rcu_torture_current_version,
@@ -1078,8 +1078,6 @@ rcu_torture_printk(char *page)atomic_read (&n_rcu_torture_mberror), n_rcu_torture_boost_ktrerror, n_rcu_torture_boost_rterror, - n_rcu_torture_boost_allocerror, - n_rcu_torture_boost_afferror, n_rcu_torture_boost_failure, n_rcu_torture_boosts, n_rcu_torture_timers);
Signature · 1 line
1.7.3.2
Josh Triplett
maintainerRe: [PATCH tip/core/rcu 10/86] rcu: eliminate unused boosting statistics
Quoted 25 lines · Paul E. McKenney
From: Paul E. McKenney <[email protected]>
The
n_rcu_torture_boost_allocerrorandn_rcu_torture_boost_afferrorstatistics are not actually incremented anymore, so eliminate them.Signed-off-by Paul E. McKenney <[email protected]>Signed-off-by Paul E. McKenney <[email protected]>--- kernel/rcutorture.c | 4 +--- 1 files changed, 1 insertions(+), 3 deletions(-)kernel/rcutorture.c +1
-1@@ -1067,7 +1067,7 @@ rcu_torture_printk(char *page) cnt +=sprintf (&page[cnt],"%s%s " , torture_type,TORTURE_FLAG ); cnt += sprintf(&page[cnt], "rtc: %p ver: %ld tfle: %d rta: %d rtaf: %d rtf: %d " - "rtmbe: %d rtbke: %ld rtbre: %ld rtbae: %ld rtbafe: %ld " + "rtmbe: %d rtbke: %ld rtbre: %ld " "rtbf: %ld rtb: %ld nt: %ld", rcu_torture_current, rcu_torture_current_version,
kernel/rcutorture.c rcu_torture_printk(char *page) · line 1083
Quoted 8 lines
kernel/rcutorture.c +0
-2@@ -1078,8 +1078,6 @@ rcu_torture_printk(char *page)atomic_read (&n_rcu_torture_mberror), n_rcu_torture_boost_ktrerror, n_rcu_torture_boost_rterror, - n_rcu_torture_boost_allocerror, - n_rcu_torture_boost_afferror, n_rcu_torture_boost_failure, n_rcu_torture_boosts, n_rcu_torture_timers);
Shouldn't you eliminate the variables entirely, if they no longer track anything?
- Josh Triplett
Re: [PATCH tip/core/rcu 10/86] rcu: eliminate unused boosting statistics
Quoted 29 lines · Josh Triplett
Quoted 28 lines · Paul E. McKenney
From: Paul E. McKenney <[email protected]>
The
n_rcu_torture_boost_allocerrorandn_rcu_torture_boost_afferrorstatistics are not actually incremented anymore, so eliminate them.Signed-off-by Paul E. McKenney <[email protected]>Signed-off-by Paul E. McKenney <[email protected]>--- kernel/rcutorture.c | 4 +--- 1 files changed, 1 insertions(+), 3 deletions(-)kernel/rcutorture.c +1
-1@@ -1067,7 +1067,7 @@ rcu_torture_printk(char *page) cnt +=sprintf (&page[cnt],"%s%s " , torture_type,TORTURE_FLAG ); cnt += sprintf(&page[cnt], "rtc: %p ver: %ld tfle: %d rta: %d rtaf: %d rtf: %d " - "rtmbe: %d rtbke: %ld rtbre: %ld rtbae: %ld rtbafe: %ld " + "rtmbe: %d rtbke: %ld rtbre: %ld " "rtbf: %ld rtb: %ld nt: %ld", rcu_torture_current, rcu_torture_current_version,@@ -1078,8 +1078,6 @@ rcu_torture_printk(char *page)atomic_read (&n_rcu_torture_mberror), n_rcu_torture_boost_ktrerror, n_rcu_torture_boost_rterror,
Quoted 8 lines
kernel/rcutorture.c rcu_torture_printk(char *page) · line 1083
Quoted 5 lines
kernel/rcutorture.c +0
-2- n_rcu_torture_boost_allocerror, - n_rcu_torture_boost_afferror, n_rcu_torture_boost_failure, n_rcu_torture_boosts, n_rcu_torture_timers);Shouldn't you eliminate the variables entirely, if they no longer track anything?
I most certainly should!!! Good catch!!!
Thanx, Paul
Paul E. McKenney
Reviewed-by Josh TriplettRe: [PATCH tip/core/rcu 10/86] rcu: eliminate unused boosting statistics
Quoted 39 lines · Paul E. McKenney
Quoted 29 lines · Josh Triplett
Quoted 28 lines · Paul E. McKenney
From: Paul E. McKenney <[email protected]>
The
n_rcu_torture_boost_allocerrorandn_rcu_torture_boost_afferrorstatistics are not actually incremented anymore, so eliminate them.Signed-off-by Paul E. McKenney <[email protected]>Signed-off-by Paul E. McKenney <[email protected]>--- kernel/rcutorture.c | 4 +--- 1 files changed, 1 insertions(+), 3 deletions(-)kernel/rcutorture.c +1
-1@@ -1067,7 +1067,7 @@ rcu_torture_printk(char *page) cnt +=sprintf (&page[cnt],"%s%s " , torture_type,TORTURE_FLAG ); cnt += sprintf(&page[cnt], "rtc: %p ver: %ld tfle: %d rta: %d rtaf: %d rtf: %d " - "rtmbe: %d rtbke: %ld rtbre: %ld rtbae: %ld rtbafe: %ld " + "rtmbe: %d rtbke: %ld rtbre: %ld " "rtbf: %ld rtb: %ld nt: %ld", rcu_torture_current, rcu_torture_current_version,@@ -1078,8 +1078,6 @@ rcu_torture_printk(char *page)atomic_read (&n_rcu_torture_mberror), n_rcu_torture_boost_ktrerror, n_rcu_torture_boost_rterror,Quoted 8 lines
kernel/rcutorture.c rcu_torture_printk(char *page) · line 1083
Quoted 5 lines
kernel/rcutorture.c +0
-2- n_rcu_torture_boost_allocerror, - n_rcu_torture_boost_afferror, n_rcu_torture_boost_failure, n_rcu_torture_boosts, n_rcu_torture_timers);Shouldn't you eliminate the variables entirely, if they no longer track anything?
Quoted 1 line
I most certainly should!!! Good catch!!!
And here is the updated commit.
Thanx, Paul
------------------------------------------------------------------------
rcu: eliminate unused boosting statistics
The n_rcu_torture_boost_allocerror and n_rcu_torture_boost_afferror statistics are not actually incremented anymore, so eliminate them.
kernel/rcutorture.c +1 -9
@@ -146,8 +146,6 @@ static atomic_t n_rcu_torture_mberror;static atomic_t n_rcu_torture_error;static long n_rcu_torture_boost_ktrerror;static long n_rcu_torture_boost_rterror; -static long n_rcu_torture_boost_allocerror; -static long n_rcu_torture_boost_afferror;static long n_rcu_torture_boost_failure;static long n_rcu_torture_boosts;static long n_rcu_torture_timers;
@@ -1067,7 +1065,7 @@ rcu_torture_printk(char *page) cnt +=sprintf (&page[cnt],"%s%s " , torture_type,TORTURE_FLAG ); cnt += sprintf(&page[cnt], "rtc: %p ver: %ld tfle: %d rta: %d rtaf: %d rtf: %d " - "rtmbe: %d rtbke: %ld rtbre: %ld rtbae: %ld rtbafe: %ld " + "rtmbe: %d rtbke: %ld rtbre: %ld " "rtbf: %ld rtb: %ld nt: %ld", rcu_torture_current, rcu_torture_current_version,
@@ -1078,16 +1076,12 @@ rcu_torture_printk(char *page)atomic_read (&n_rcu_torture_mberror), n_rcu_torture_boost_ktrerror, n_rcu_torture_boost_rterror, - n_rcu_torture_boost_allocerror, - n_rcu_torture_boost_afferror, n_rcu_torture_boost_failure, n_rcu_torture_boosts, n_rcu_torture_timers);if (atomic_read (&n_rcu_torture_mberror) !=0 || n_rcu_torture_boost_ktrerror !=0 || n_rcu_torture_boost_rterror !=0 || - n_rcu_torture_boost_allocerror !=0 || - n_rcu_torture_boost_afferror !=0 || n_rcu_torture_boost_failure !=0 ) cnt +=sprintf (&page[cnt]," !!!" ); cnt +=sprintf (&page[cnt],"\n%s%s " , torture_type,TORTURE_FLAG );
@@ -1486,8 +1480,6 @@ rcu_torture_init(void)atomic_set (&n_rcu_torture_error,0 ); n_rcu_torture_boost_ktrerror =0 ; n_rcu_torture_boost_rterror =0 ; - n_rcu_torture_boost_allocerror =0 ; - n_rcu_torture_boost_afferror =0 ; n_rcu_torture_boost_failure =0 ; n_rcu_torture_boosts =0 ;for (i =0 ; i <RCU_TORTURE_PIPE_LEN +1 ; i++)
PATCH 11/86 rcu: Add boosting to TREE_PREEMPT_RCU tracing
In reply to Paul E. McKenneyFrom: Paul E. McKenney <[email protected]>
Includes total number of tasks boosted, number boosted on behalf of each of normal and expedited grace periods, and statistics on attempts to initiate boosting that failed for various reasons.
--- kernel/rcutree.h | 19 +++++++++++++ kernel/rcutree_plugin.h | 42 ++++++++++++++++++++++++++--- kernel/rcutree_trace.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 125 insertions(+), 4 deletions(-)
kernel/rcutree.h +19 -0
@@ -152,6 +152,25 @@ struct rcu_node {wait_queue_head_t boost_wq;/* Wait queue on which to park the boost */ /* kthread. */ +unsigned long n_tasks_boosted; +/* Total number of tasks boosted. */ +unsigned long n_exp_boosts; +/* Number of tasks boosted for expedited GP. */ +unsigned long n_normal_boosts; +/* Number of tasks boosted for normal GP. */ +unsigned long n_balk_blkd_tasks; +/* Refused to boost: no blocked tasks. */ +unsigned long n_balk_exp_gp_tasks; +/* Refused to boost: nothing blocking GP. */ +unsigned long n_balk_boost_tasks; +/* Refused to boost: already boosting. */ +unsigned long n_balk_notblocked; +/* Refused to boost: RCU RS CS still running. */ +unsigned long n_balk_notyet; +/* Refused to boost: not yet time. */ +unsigned long n_balk_nos; +/* Refused to boost: not sure why, though. */ +/* This can happen due to race conditions. */ #endif /* #ifdef CONFIG_RCU_BOOST */ struct task_struct *node_kthread_task;/* kthread that takes care of this rcu_node */
kernel/rcutree_plugin.h +38 -4
69 lines not on this page · raw message
kernel/rcutree_trace.c +68 -0
80 lines not on this page · raw message
Signature · 1 line
1.7.3.2
Josh Triplett
maintainerRe: [PATCH tip/core/rcu 11/86] rcu: Add boosting to TREE_PREEMPT_RCU tracing
Quoted 5 lines · Paul E. McKenney
From: Paul E. McKenney <[email protected]>
Includes total number of tasks boosted, number boosted on behalf of each of normal and expedited grace periods, and statistics on attempts to initiate boosting that failed for various reasons.
In this patch series, you have several cases where you improve the trace output in one patch, and then update the documentation in a subsequent patch. You might consider doing both in the same patch, so that at each step the documentation matches the kernel.
- Josh Triplett
Re: [PATCH tip/core/rcu 11/86] rcu: Add boosting to TREE_PREEMPT_RCU tracing
Quoted 11 lines · Josh Triplett
Quoted 5 lines · Paul E. McKenney
From: Paul E. McKenney <[email protected]>
Includes total number of tasks boosted, number boosted on behalf of each of normal and expedited grace periods, and statistics on attempts to initiate boosting that failed for various reasons.
In this patch series, you have several cases where you improve the trace output in one patch, and then update the documentation in a subsequent patch. You might consider doing both in the same patch, so that at each step the documentation matches the kernel.
The reason I do the documentation second is that it allows me to copy the exact output from a test run, which has the nice side-effect of making sure that I really am getting the documentation correct. Or at least of reducing the probability of getting it wrong... ;-)
Thanx, Paul
Josh Triplett
maintainerRe: [PATCH tip/core/rcu 11/86] rcu: Add boosting to TREE_PREEMPT_RCU tracing
Quoted 13 lines · Paul E. McKenney
Quoted 11 lines · Josh Triplett
Quoted 5 lines · Paul E. McKenney
From: Paul E. McKenney <[email protected]>
Includes total number of tasks boosted, number boosted on behalf of each of normal and expedited grace periods, and statistics on attempts to initiate boosting that failed for various reasons.
In this patch series, you have several cases where you improve the trace output in one patch, and then update the documentation in a subsequent patch. You might consider doing both in the same patch, so that at each step the documentation matches the kernel.
Quoted 4 lines
The reason I do the documentation second is that it allows me to copy the exact output from a test run, which has the nice side-effect of making sure that I really am getting the documentation correct. Or at least of reducing the probability of getting it wrong... ;-)
I definitely agree that you should copy the output from a test run to make the documentation accurate; I just mean that once you do so, you should put both the code changes and corresponding documentation into a single commit.
- Josh Triplett
Re: [PATCH tip/core/rcu 11/86] rcu: Add boosting to TREE_PREEMPT_RCU tracing
Quoted 19 lines · Josh Triplett
Quoted 13 lines · Paul E. McKenney
Quoted 11 lines · Josh Triplett
Quoted 5 lines · Paul E. McKenney
From: Paul E. McKenney <[email protected]>
Includes total number of tasks boosted, number boosted on behalf of each of normal and expedited grace periods, and statistics on attempts to initiate boosting that failed for various reasons.
In this patch series, you have several cases where you improve the trace output in one patch, and then update the documentation in a subsequent patch. You might consider doing both in the same patch, so that at each step the documentation matches the kernel.
Quoted 4 lines
The reason I do the documentation second is that it allows me to copy the exact output from a test run, which has the nice side-effect of making sure that I really am getting the documentation correct. Or at least of reducing the probability of getting it wrong... ;-)
Quoted 4 lines
I definitely agree that you should copy the output from a test run to make the documentation accurate; I just mean that once you do so, you should put both the code changes and corresponding documentation into a single commit.
Fair enough, I did some squashing.
Thanx, Paul
PATCH 12/86 rcu: Update RCU's trace.txt documentation for new format
In reply to Paul E. McKenneyFrom: Paul E. McKenney <[email protected]>
The trace.txt file had obsolete output for the debugfs rcu/rcudata file, so update it.
--- Documentation/RCU/trace.txt | 65 ++++++++++++++++++++++-------------------- 1 files changed, 34 insertions(+), 31 deletions(-)
Documentation/RCU/trace.txt +34 -31
@@ -21,23 +21,23 @@ rcu_pending() function decided that there was core RCU work to do). The output of "cat rcu/rcudata" looks as follows: rcu_sched: - 0 c=17829 g=17829 pq=1 pqc=17829 qp=0 dt=10951/1/0 df=1101 of=0 ri=36 ql=0 b=10 - 1 c=17829 g=17829 pq=1 pqc=17829 qp=0 dt=16117/1/0 df=1015 of=0 ri=0 ql=0 b=10 - 2 c=17829 g=17829 pq=1 pqc=17829 qp=0 dt=1445/1/0 df=1839 of=0 ri=0 ql=0 b=10 - 3 c=17829 g=17829 pq=1 pqc=17829 qp=0 dt=6681/1/0 df=1545 of=0 ri=0 ql=0 b=10 - 4 c=17829 g=17829 pq=1 pqc=17829 qp=0 dt=1003/1/0 df=1992 of=0 ri=0 ql=0 b=10 - 5 c=17829 g=17830 pq=1 pqc=17829 qp=1 dt=3887/1/0 df=3331 of=0 ri=4 ql=2 b=10 - 6 c=17829 g=17829 pq=1 pqc=17829 qp=0 dt=859/1/0 df=3224 of=0 ri=0 ql=0 b=10 - 7 c=17829 g=17830 pq=0 pqc=17829 qp=1 dt=3761/1/0 df=1818 of=0 ri=0 ql=2 b=10 + 0!c=423090 g=423091 pq=1 pqc=423090 qp=1 dt=86475/1/0 df=16319 of=163 ri=1519 ql=0 b=10 ci=1460693 co=1648 ca=6448 + 1!c=423329 g=423330 pq=1 pqc=423329 qp=1 dt=90875/1/0 df=16231 of=157 ri=1249 ql=0 b=10 ci=1459002 co=1614 ca=3310 + 2!c=423370 g=423371 pq=1 pqc=423370 qp=1 dt=69661/1/0 df=16125 of=163 ri=1469 ql=0 b=10 ci=1610701 co=2015 ca=2378 + 3!c=422967 g=422968 pq=1 pqc=422967 qp=1 dt=70349/1/0 df=12528 of=163 ri=1450 ql=0 b=10 ci=1427543 co=1430 ca=897 + 4!c=423196 g=423197 pq=1 pqc=423196 qp=0 dt=38935/1/0 df=10959 of=177 ri=1657 ql=0 b=10 ci=1562249 co=1896 ca=533 + 5!c=422950 g=422951 pq=1 pqc=422950 qp=0 dt=25127/1/0 df=5895 of=167 ri=1549 ql=0 b=10 ci=1777260 co=2137 ca=274 + 6!c=423396 g=423397 pq=1 pqc=423396 qp=1 dt=22639/1/0 df=4590 of=149 ri=1572 ql=0 b=10 ci=1471186 co=1530 ca=243 + 7 c=460203 g=460203 pq=1 pqc=460202 qp=0 dt=937087/1/0 df=3298 of=149 ri=1584 ql=6 b=10 ci=4026154 co=1948 ca=135 rcu_bh: - 0 c=-275 g=-275 pq=1 pqc=-275 qp=0 dt=10951/1/0 df=0 of=0 ri=0 ql=0 b=10 - 1 c=-275 g=-275 pq=1 pqc=-275 qp=0 dt=16117/1/0 df=13 of=0 ri=0 ql=0 b=10 - 2 c=-275 g=-275 pq=1 pqc=-275 qp=0 dt=1445/1/0 df=15 of=0 ri=0 ql=0 b=10 - 3 c=-275 g=-275 pq=1 pqc=-275 qp=0 dt=6681/1/0 df=9 of=0 ri=0 ql=0 b=10 - 4 c=-275 g=-275 pq=1 pqc=-275 qp=0 dt=1003/1/0 df=15 of=0 ri=0 ql=0 b=10 - 5 c=-275 g=-275 pq=1 pqc=-275 qp=0 dt=3887/1/0 df=15 of=0 ri=0 ql=0 b=10 - 6 c=-275 g=-275 pq=1 pqc=-275 qp=0 dt=859/1/0 df=15 of=0 ri=0 ql=0 b=10 - 7 c=-275 g=-275 pq=1 pqc=-275 qp=0 dt=3761/1/0 df=15 of=0 ri=0 ql=0 b=10 + 0!c=18446744073709551494 g=18446744073709551494 pq=0 pqc=18446744073709551493 qp=1 dt=86475/1/0 df=11 of=0 ri=0 ql=0 b=10 ci=112 co=0 ca=0 + 1!c=18446744073709551496 g=18446744073709551496 pq=1 pqc=18446744073709551495 qp=0 dt=90875/1/0 df=15 of=0 ri=0 ql=0 b=10 ci=143 co=0 ca=0 + 2!c=18446744073709551496 g=18446744073709551496 pq=1 pqc=18446744073709551495 qp=0 dt=69661/1/0 df=21 of=0 ri=1 ql=0 b=10 ci=88 co=0 ca=0 + 3!c=18446744073709551494 g=18446744073709551494 pq=1 pqc=18446744073709551493 qp=0 dt=70349/1/0 df=13 of=0 ri=0 ql=0 b=10 ci=100 co=0 ca=0 + 4!c=18446744073709551494 g=18446744073709551494 pq=0 pqc=18446744073709551493 qp=1 dt=38935/1/0 df=17 of=0 ri=0 ql=0 b=10 ci=36 co=0 ca=0 + 5!c=18446744073709551494 g=18446744073709551494 pq=0 pqc=18446744073709551493 qp=1 dt=25127/1/0 df=7 of=0 ri=0 ql=0 b=10 ci=32 co=0 ca=0 + 6!c=18446744073709551496 g=18446744073709551496 pq=1 pqc=18446744073709551495 qp=0 dt=22639/1/0 df=9 of=0 ri=0 ql=0 b=10 ci=44 co=0 ca=0 + 7 c=182 g=182 pq=1 pqc=181 qp=0 dt=937087/1/0 df=14 of=0 ri=1 ql=0 b=10 ci=627 co=0 ca=0 The first section lists the rcu_data structures for rcu_sched, the second for rcu_bh. Note that CONFIG_TREE_PREEMPT_RCU kernels will have an
@@ -52,17 +52,18 @@ o The number at the beginning of each line is the CPU number. substantially larger than the number of actual CPUs. o "c" is the count of grace periods that this CPU believes have - completed. CPUs in dynticks idle mode may lag quite a ways - behind, for example, CPU 4 under "rcu_sched" above, which has - slept through the past 25 RCU grace periods. It is not unusual - to see CPUs lagging by thousands of grace periods. + completed. Offlined CPUs and CPUs in dynticks idle mode may + lag quite a ways behind, for example, CPU 6 under "rcu_sched" + above, which has been offline through not quite 40,000 RCU grace + periods. It is not unusual to see CPUs lagging by thousands of + grace periods. o "g" is the count of grace periods that this CPU believes have - started. Again, CPUs in dynticks idle mode may lag behind. - If the "c" and "g" values are equal, this CPU has already - reported a quiescent state for the last RCU grace period that - it is aware of, otherwise, the CPU believes that it owes RCU a - quiescent state. + started. Again, offlined CPUs and CPUs in dynticks idle mode + may lag behind. If the "c" and "g" values are equal, this CPU + has already reported a quiescent state for the last RCU grace + period that it is aware of, otherwise, the CPU believes that it + owes RCU a quiescent state. o "pq" indicates that this CPU has passed through a quiescent state for the current grace period. It is possible for "pq" to be
@@ -81,14 +82,16 @@ o "pqc" indicates which grace period the last-observed quiescent the next grace period! o "qp" indicates that RCU still expects a quiescent state from - this CPU. + this CPU. Offlined CPUs and CPUs in dyntick idle mode might + well have qp=1, which is OK: RCU is still ignoring them. o "dt" is the current value of the dyntick counter that is incremented when entering or leaving dynticks idle state, either by the - scheduler or by irq. The number after the first "/" is the - interrupt nesting depth when in dyntick-idle state, or one - greater than the interrupt-nesting depth otherwise. The number - after the second "/" is the NMI nesting depth. + scheduler or by irq. This number is even if the CPU is in + dyntick idle mode and odd otherwise. The number after the first + "/" is the interrupt nesting depth when in dyntick-idle state, + or one greater than the interrupt-nesting depth otherwise. + The number after the second "/" is the NMI nesting depth. This field is displayed only for CONFIG_NO_HZ kernels.
@@ -100,7 +103,7 @@ o "df" is the number of times that some other CPU has forced a o "of" is the number of times that some other CPU has forced a quiescent state on behalf of this CPU due to this CPU being - offline. In a perfect world, this might neve happen, but it + offline. In a perfect world, this might never happen, but it turns out that offlining and onlining a CPU can take several grace periods, and so there is likely to be an extended period of time when RCU believes that the CPU is online when it really is not.
Signature · 1 line
1.7.3.2
PATCH 13/86 rcu: add callback-queue information to rcudata output
In reply to Paul E. McKenneyFrom: Paul E. McKenney <[email protected]>
This commit adds an indication of the state of the callback queue using a string of four characters following the "ql=" integer queue length. The first character is "N" if there are callbacks that have been queued that are not yet ready to be handled by the next grace period, or "." otherwise. The second character is "R" if there are callbacks queued that are ready to be handled by the next grace period, or "." otherwise. The third character is "W" if there are callbacks waiting for the current grace period, or "." otherwise. Finally, the fourth character is "D" if there are callbacks that have been handled by a prior grace period and are waiting to be invoked, or ".".
Note that callbacks that are in the process of being invoked are not shown. These callbacks would have been removed from the rcu_data structure's list by rcu_do_batch() prior to being executed. (These callbacks are also not reflected in the "ql=" total, FWIW.)
--- kernel/rcutree_trace.c | 21 +++++++++++++++++++-- 1 files changed, 19 insertions(+), 2 deletions(-)
kernel/rcutree_trace.c +19 -2
@@ -64,7 +64,16 @@ static void print_one_rcu_data(struct seq_file *m, struct rcu_data *rdp) rdp->dynticks_fqs);#endif /* #ifdef CONFIG_NO_HZ */ seq_printf (m," of=%lu ri=%lu" , rdp->offline_fqs, rdp->resched_ipi); -seq_printf (m," ql=%ld b=%ld" , rdp->qlen, rdp->blimit); +seq_printf (m," ql=%ld qs=%c%c%c%c b=%ld" , + rdp->qlen, +".N" [rdp->nxttail[RCU_NEXT_READY_TAIL ] != + rdp->nxttail[RCU_NEXT_TAIL ]], +".R" [rdp->nxttail[RCU_WAIT_TAIL ] != + rdp->nxttail[RCU_NEXT_READY_TAIL ]], +".W" [rdp->nxttail[RCU_DONE_TAIL ] != + rdp->nxttail[RCU_WAIT_TAIL ]], +".D" [&rdp->nxtlist != rdp->nxttail[RCU_DONE_TAIL ]], + rdp->blimit);seq_printf (m," ci=%lu co=%lu ca=%lu\n" , rdp->n_cbs_invoked, rdp->n_cbs_orphaned, rdp->n_cbs_adopted); }
@@ -121,7 +130,15 @@ static void print_one_rcu_data_csv(struct seq_file *m, struct rcu_data *rdp) rdp->dynticks_fqs);#endif /* #ifdef CONFIG_NO_HZ */ seq_printf (m,",%lu,%lu" , rdp->offline_fqs, rdp->resched_ipi); -seq_printf (m,",%ld,%ld" , rdp->qlen, rdp->blimit); +seq_printf (m,",%ld,\"%c%c%c%c\",%ld" , rdp->qlen, +".N" [rdp->nxttail[RCU_NEXT_READY_TAIL ] != + rdp->nxttail[RCU_NEXT_TAIL ]], +".R" [rdp->nxttail[RCU_WAIT_TAIL ] != + rdp->nxttail[RCU_NEXT_READY_TAIL ]], +".W" [rdp->nxttail[RCU_DONE_TAIL ] != + rdp->nxttail[RCU_WAIT_TAIL ]], +".D" [&rdp->nxtlist != rdp->nxttail[RCU_DONE_TAIL ]], + rdp->blimit);seq_printf (m,",%lu,%lu,%lu\n" , rdp->n_cbs_invoked, rdp->n_cbs_orphaned, rdp->n_cbs_adopted); }
Signature · 1 line
1.7.3.2
PATCH 14/86 rcu: document new callback-queue trace information
In reply to Paul E. McKenneyFrom: Paul E. McKenney <[email protected]>
--- Documentation/RCU/trace.txt | 58 +++++++++++++++++++++++++++++++------------ 1 files changed, 42 insertions(+), 16 deletions(-)
Documentation/RCU/trace.txt +42 -16
@@ -21,23 +21,23 @@ rcu_pending() function decided that there was core RCU work to do). The output of "cat rcu/rcudata" looks as follows: rcu_sched: - 0!c=423090 g=423091 pq=1 pqc=423090 qp=1 dt=86475/1/0 df=16319 of=163 ri=1519 ql=0 b=10 ci=1460693 co=1648 ca=6448 - 1!c=423329 g=423330 pq=1 pqc=423329 qp=1 dt=90875/1/0 df=16231 of=157 ri=1249 ql=0 b=10 ci=1459002 co=1614 ca=3310 - 2!c=423370 g=423371 pq=1 pqc=423370 qp=1 dt=69661/1/0 df=16125 of=163 ri=1469 ql=0 b=10 ci=1610701 co=2015 ca=2378 - 3!c=422967 g=422968 pq=1 pqc=422967 qp=1 dt=70349/1/0 df=12528 of=163 ri=1450 ql=0 b=10 ci=1427543 co=1430 ca=897 - 4!c=423196 g=423197 pq=1 pqc=423196 qp=0 dt=38935/1/0 df=10959 of=177 ri=1657 ql=0 b=10 ci=1562249 co=1896 ca=533 - 5!c=422950 g=422951 pq=1 pqc=422950 qp=0 dt=25127/1/0 df=5895 of=167 ri=1549 ql=0 b=10 ci=1777260 co=2137 ca=274 - 6!c=423396 g=423397 pq=1 pqc=423396 qp=1 dt=22639/1/0 df=4590 of=149 ri=1572 ql=0 b=10 ci=1471186 co=1530 ca=243 - 7 c=460203 g=460203 pq=1 pqc=460202 qp=0 dt=937087/1/0 df=3298 of=149 ri=1584 ql=6 b=10 ci=4026154 co=1948 ca=135 + 0!c=423090 g=423091 pq=1 pqc=423090 qp=1 dt=86475/1/0 df=16319 of=163 ri=1519 ql=0 qs=.... b=10 ci=1460693 co=1648 ca=6448 + 1!c=423329 g=423330 pq=1 pqc=423329 qp=1 dt=90875/1/0 df=16231 of=157 ri=1249 ql=0 qs=.... b=10 ci=1459002 co=1614 ca=3310 + 2!c=423370 g=423371 pq=1 pqc=423370 qp=1 dt=69661/1/0 df=16125 of=163 ri=1469 ql=0 qs=.... b=10 ci=1610701 co=2015 ca=2378 + 3!c=422967 g=422968 pq=1 pqc=422967 qp=1 dt=70349/1/0 df=12528 of=163 ri=1450 ql=0 qs=.... b=10 ci=1427543 co=1430 ca=897 + 4!c=423196 g=423197 pq=1 pqc=423196 qp=0 dt=38935/1/0 df=10959 of=177 ri=1657 ql=0 qs=.... b=10 ci=1562249 co=1896 ca=533 + 5!c=422950 g=422951 pq=1 pqc=422950 qp=0 dt=25127/1/0 df=5895 of=167 ri=1549 ql=0 qs=.... b=10 ci=1777260 co=2137 ca=274 + 6!c=423396 g=423397 pq=1 pqc=423396 qp=1 dt=22639/1/0 df=4590 of=149 ri=1572 ql=0 qs=.... b=10 ci=1471186 co=1530 ca=243 + 7 c=460203 g=460203 pq=1 pqc=460202 qp=0 dt=937087/1/0 df=3298 of=149 ri=1584 ql=6 qs=N.W. b=10 ci=4026154 co=1948 ca=135 rcu_bh: - 0!c=18446744073709551494 g=18446744073709551494 pq=0 pqc=18446744073709551493 qp=1 dt=86475/1/0 df=11 of=0 ri=0 ql=0 b=10 ci=112 co=0 ca=0 - 1!c=18446744073709551496 g=18446744073709551496 pq=1 pqc=18446744073709551495 qp=0 dt=90875/1/0 df=15 of=0 ri=0 ql=0 b=10 ci=143 co=0 ca=0 - 2!c=18446744073709551496 g=18446744073709551496 pq=1 pqc=18446744073709551495 qp=0 dt=69661/1/0 df=21 of=0 ri=1 ql=0 b=10 ci=88 co=0 ca=0 - 3!c=18446744073709551494 g=18446744073709551494 pq=1 pqc=18446744073709551493 qp=0 dt=70349/1/0 df=13 of=0 ri=0 ql=0 b=10 ci=100 co=0 ca=0 - 4!c=18446744073709551494 g=18446744073709551494 pq=0 pqc=18446744073709551493 qp=1 dt=38935/1/0 df=17 of=0 ri=0 ql=0 b=10 ci=36 co=0 ca=0 - 5!c=18446744073709551494 g=18446744073709551494 pq=0 pqc=18446744073709551493 qp=1 dt=25127/1/0 df=7 of=0 ri=0 ql=0 b=10 ci=32 co=0 ca=0 - 6!c=18446744073709551496 g=18446744073709551496 pq=1 pqc=18446744073709551495 qp=0 dt=22639/1/0 df=9 of=0 ri=0 ql=0 b=10 ci=44 co=0 ca=0 - 7 c=182 g=182 pq=1 pqc=181 qp=0 dt=937087/1/0 df=14 of=0 ri=1 ql=0 b=10 ci=627 co=0 ca=0 + 0!c=18446744073709551494 g=18446744073709551494 pq=0 pqc=18446744073709551493 qp=1 dt=86475/1/0 df=11 of=0 ri=0 ql=0 qs=.... b=10 ci=112 co=0 ca=0 + 1!c=18446744073709551496 g=18446744073709551496 pq=1 pqc=18446744073709551495 qp=0 dt=90875/1/0 df=15 of=0 ri=0 ql=0 qs=.... b=10 ci=143 co=0 ca=0 + 2!c=18446744073709551496 g=18446744073709551496 pq=1 pqc=18446744073709551495 qp=0 dt=69661/1/0 df=21 of=0 ri=1 ql=0 qs=.... b=10 ci=88 co=0 ca=0 + 3!c=18446744073709551494 g=18446744073709551494 pq=1 pqc=18446744073709551493 qp=0 dt=70349/1/0 df=13 of=0 ri=0 ql=0 qs=.... b=10 ci=100 co=0 ca=0 + 4!c=18446744073709551494 g=18446744073709551494 pq=0 pqc=18446744073709551493 qp=1 dt=38935/1/0 df=17 of=0 ri=0 ql=0 qs=.... b=10 ci=36 co=0 ca=0 + 5!c=18446744073709551494 g=18446744073709551494 pq=0 pqc=18446744073709551493 qp=1 dt=25127/1/0 df=7 of=0 ri=0 ql=0 qs=.... b=10 ci=32 co=0 ca=0 + 6!c=18446744073709551496 g=18446744073709551496 pq=1 pqc=18446744073709551495 qp=0 dt=22639/1/0 df=9 of=0 ri=0 ql=0 qs=.... b=10 ci=44 co=0 ca=0 + 7 c=182 g=182 pq=1 pqc=181 qp=0 dt=937087/1/0 df=14 of=0 ri=1 ql=0 qs=.... b=10 ci=627 co=0 ca=0 The first section lists the rcu_data structures for rcu_sched, the second for rcu_bh. Note that CONFIG_TREE_PREEMPT_RCU kernels will have an
@@ -120,6 +120,32 @@ o "ql" is the number of RCU callbacks currently residing on of what state they are in (new, waiting for grace period to start, waiting for grace period to end, ready to invoke). +o "qs" gives an indication of the state of the callback queue + with four characters: + + "N" Indicates that there are callbacks queued that are not + ready to be handled by the next grace period, and thus + will be handled by the grace period following the next + one. + + "R" Indicates that there are callbacks queued that are + ready to be handled by the next grace period. + + "W" Indicates that there are callbacks queued that are + waiting on the current grace period. + + "D" Indicates that there are callbacks queued that have + already been handled by a prior grace period, and are + thus waiting to be invoked. Note that callbacks in + the process of being invoked are not counted here. + Callbacks in the process of being invoked are those + that have been removed from the rcu_data structures + queues by rcu_do_batch(), but which have not yet been + invoked. + + If there are no callbacks in a given one of the above states, + the corresponding character is replaced by ".". + o "b" is the batch limit for this CPU. If more than this number of RCU callbacks is ready to invoke, then the remainder will be deferred.
Signature · 1 line
1.7.3.2
PATCH 15/86 rcu: add tracing for RCU's kthread run states.
In reply to Paul E. McKenneyFrom: Paul E. McKenney <[email protected]>
Add tracing to help debugging situations when RCU's kthreads are not running but are supposed to be.
--- kernel/rcutree.c | 11 ++++++++++- kernel/rcutree.h | 11 +++++++++++ kernel/rcutree_plugin.h | 3 +++ kernel/rcutree_trace.c | 23 ++++++++++++++++++++--- 4 files changed, 44 insertions(+), 4 deletions(-)
kernel/rcutree.c +10 -1
@@ -91,8 +91,9 @@ EXPORT_SYMBOL_GPL(rcu_scheduler_active);* handle all flavors of RCU. */ static DEFINE_PER_CPU(struct task_struct *, rcu_cpu_kthread_task); +DEFINE_PER_CPU (unsigned int , rcu_cpu_kthread_status); static DEFINE_PER_CPU(wait_queue_head_t, rcu_cpu_wq); -static DEFINE_PER_CPU(char, rcu_cpu_has_work); +DEFINE_PER_CPU (char , rcu_cpu_has_work);static char rcu_kthreads_spawnable;static void rcu_node_kthread_setaffinity (struct rcu_node *rnp,int outgoingcpu);
@@ -1563,11 +1564,13 @@ static int rcu_cpu_kthread(void *arg)int cpu = (int )(long )arg;unsigned long flags;int spincnt =0 ; +unsigned int *statusp = &per_cpu (rcu_cpu_kthread_status, cpu);wait_queue_head_t *wqp = &per_cpu (rcu_cpu_wq, cpu);char work;char *workp = &per_cpu (rcu_cpu_has_work, cpu);for (;;) { + *statusp =RCU_KTHREAD_WAITING ;wait_event_interruptible (*wqp, *workp !=0 ||kthread_should_stop ());local_bh_disable ();
@@ -1575,6 +1578,7 @@ static int rcu_cpu_kthread(void *arg)local_bh_enable ();break ; } + *statusp =RCU_KTHREAD_RUNNING ;local_irq_save (flags); work = *workp; *workp =0 ;
@@ -1587,10 +1591,12 @@ static int rcu_cpu_kthread(void *arg)else spincnt =0 ;if (spincnt >10 ) { + *statusp =RCU_KTHREAD_YIELDING ;rcu_yield (rcu_cpu_kthread_timer, (unsigned long )cpu); spincnt =0 ; } } + *statusp =RCU_KTHREAD_STOPPED ;return 0 ; }
@@ -1637,10 +1643,12 @@ static int rcu_node_kthread(void *arg)struct task_struct *t;for (;;) { + rnp->node_kthread_status =RCU_KTHREAD_WAITING ;wait_event_interruptible (rnp->node_wq, rnp->wakemask !=0 ||kthread_should_stop ());if (kthread_should_stop ())break ; + rnp->node_kthread_status =RCU_KTHREAD_RUNNING ;raw_spin_lock_irqsave (&rnp->lock, flags); mask = rnp->wakemask; rnp->wakemask =0 ;
@@ -1661,6 +1669,7 @@ static int rcu_node_kthread(void *arg)preempt_enable (); } } + rnp->node_kthread_status =RCU_KTHREAD_STOPPED ;return 0 ; }
kernel/rcutree.h +11 -0
@@ -89,6 +89,13 @@ struct rcu_dynticks {atomic_t dynticks;/* Even value for dynticks-idle, else odd. */ }; +/* RCU's kthread states for tracing. */ +#define RCU_KTHREAD_STOPPED 0 +#define RCU_KTHREAD_RUNNING 1 +#define RCU_KTHREAD_WAITING 2 +#define RCU_KTHREAD_YIELDING 3 +#define RCU_KTHREAD_MAX 3 +/* * Definition for node within the RCU grace-period-detection hierarchy. */
@@ -152,6 +159,8 @@ struct rcu_node {wait_queue_head_t boost_wq;/* Wait queue on which to park the boost */ /* kthread. */ +unsigned int boost_kthread_status; +/* State of boost_kthread_task for tracing. */ unsigned long n_tasks_boosted;/* Total number of tasks boosted. */ unsigned long n_exp_boosts;
@@ -179,6 +188,8 @@ struct rcu_node {wait_queue_head_t node_wq;/* Wait queue on which to park the per-node */ /* kthread. */ +unsigned int node_kthread_status; +/* State of node_kthread_task for tracing. */ }____cacheline_internodealigned_in_smp ;/*
kernel/rcutree_plugin.h +3 -0
@@ -1198,11 +1198,13 @@ static int rcu_boost_kthread(void *arg)int more2boost;for (;;) { + rnp->boost_kthread_status =RCU_KTHREAD_WAITING ;wait_event_interruptible (rnp->boost_wq, rnp->boost_tasks || rnp->exp_tasks ||kthread_should_stop ());if (kthread_should_stop ())break ; + rnp->boost_kthread_status =RCU_KTHREAD_RUNNING ; more2boost =rcu_boost (rnp);if (more2boost) spincnt++;
@@ -1213,6 +1215,7 @@ static int rcu_boost_kthread(void *arg) spincnt =0 ; } } + rnp->boost_kthread_status =RCU_KTHREAD_STOPPED ;return 0 ; }
kernel/rcutree_trace.c +20 -3
@@ -46,6 +46,16 @@#define RCU_TREE_NONCORE #include "rcutree.h" +DECLARE_PER_CPU(unsigned int, rcu_cpu_kthread_status); +DECLARE_PER_CPU (char, rcu_cpu_has_work); + +static char convert_kthread_status (unsigned int kthread_status) +{ +if (kthread_status >RCU_KTHREAD_MAX ) +return '?' ; +return "SRWY" [kthread_status]; +} +static void print_one_rcu_data (struct seq_file *m,struct rcu_data *rdp) {if (!rdp->beenonline)
@@ -64,7 +74,7 @@ static void print_one_rcu_data(struct seq_file *m, struct rcu_data *rdp) rdp->dynticks_fqs);#endif /* #ifdef CONFIG_NO_HZ */ seq_printf (m," of=%lu ri=%lu" , rdp->offline_fqs, rdp->resched_ipi); - seq_printf(m, " ql=%ld qs=%c%c%c%c b=%ld", + seq_printf(m, " ql=%ld qs=%c%c%c%c kt=%d/%c b=%ld", rdp->qlen, ".N"[rdp->nxttail[RCU_NEXT_READY_TAIL] != rdp->nxttail[RCU_NEXT_TAIL]],
@@ -73,6 +83,9 @@ static void print_one_rcu_data(struct seq_file *m, struct rcu_data *rdp)".W" [rdp->nxttail[RCU_DONE_TAIL ] != rdp->nxttail[RCU_WAIT_TAIL ]],".D" [&rdp->nxtlist != rdp->nxttail[RCU_DONE_TAIL ]], +per_cpu (rcu_cpu_has_work, rdp->cpu), +convert_kthread_status (per_cpu (rcu_cpu_kthread_status, + rdp->cpu)), rdp->blimit);seq_printf (m," ci=%lu co=%lu ca=%lu\n" , rdp->n_cbs_invoked, rdp->n_cbs_orphaned, rdp->n_cbs_adopted);
@@ -130,7 +143,7 @@ static void print_one_rcu_data_csv(struct seq_file *m, struct rcu_data *rdp) rdp->dynticks_fqs);#endif /* #ifdef CONFIG_NO_HZ */ seq_printf (m,",%lu,%lu" , rdp->offline_fqs, rdp->resched_ipi); - seq_printf(m, ",%ld,\"%c%c%c%c\",%ld", rdp->qlen, + seq_printf(m, ",%ld,\"%c%c%c%c\",%d,\"%c\",%ld", rdp->qlen, ".N"[rdp->nxttail[RCU_NEXT_READY_TAIL] != rdp->nxttail[RCU_NEXT_TAIL]], ".R"[rdp->nxttail[RCU_WAIT_TAIL] !=
@@ -138,6 +151,9 @@ static void print_one_rcu_data_csv(struct seq_file *m, struct rcu_data *rdp)".W" [rdp->nxttail[RCU_DONE_TAIL ] != rdp->nxttail[RCU_WAIT_TAIL ]],".D" [&rdp->nxtlist != rdp->nxttail[RCU_DONE_TAIL ]], +per_cpu (rcu_cpu_has_work, rdp->cpu), +convert_kthread_status (per_cpu (rcu_cpu_kthread_status, + rdp->cpu)), rdp->blimit);seq_printf (m,",%lu,%lu,%lu\n" , rdp->n_cbs_invoked, rdp->n_cbs_orphaned, rdp->n_cbs_adopted);
@@ -178,13 +194,14 @@ static const struct file_operations rcudata_csv_fops = {static void print_one_rcu_node_boost (struct seq_file *m,struct rcu_node *rnp) { - seq_printf(m, "%d:%d tasks=%c%c%c%c ntb=%lu neb=%lu nnb=%lu " + seq_printf(m, "%d:%d tasks=%c%c%c%c kt=%c ntb=%lu neb=%lu nnb=%lu " "j=%04x bt=%04x\n", rnp->grplo, rnp->grphi, "T."[list_empty(&rnp->blkd_tasks)], "N."[!rnp->gp_tasks], "E."[!rnp->exp_tasks], "B."[!rnp->boost_tasks], + convert_kthread_status(rnp->boost_kthread_status), rnp->n_tasks_boosted, rnp->n_exp_boosts, rnp->n_normal_boosts, (int)(jiffies & 0xffff),
Signature · 1 line
1.7.3.2
PATCH 16/86 rcu: make rcutorture version numbers available through debugfs
In reply to Paul E. McKenneyFrom: Paul E. McKenney <[email protected]>
It is not possible to accurately correlate rcutorture output with that of debugfs. This patch therefore adds a debugfs file that prints out the rcutorture version number, permitting easy correlation.
--- include/linux/rcupdate.h | 13 ++++++++++++- include/linux/rcutree.h | 3 +++ kernel/rcutorture.c | 8 +++++--- kernel/rcutree.c | 37 +++++++++++++++++++++++++++++++++++++ kernel/rcutree_trace.c | 28 ++++++++++++++++++++++++++++ 5 files changed, 85 insertions(+), 4 deletions(-)
include/linux/rcupdate.h +12 -1
@@ -47,6 +47,18 @@extern int rcutorture_runnable;/* for sysctl */ #endif /* #ifdef CONFIG_RCU_TORTURE_TEST */ +#if defined(CONFIG_TREE_RCU ) || defined(CONFIG_TREE_PREEMPT_RCU ) +extern void rcutorture_record_test_transition (void ); +extern void rcutorture_record_progress (unsigned long vernum); +#else +static inline void rcutorture_record_test_transition (void ) +{ +} +static inline void rcutorture_record_progress (unsigned long vernum) +{ +} +#endif +#define UINT_CMP_GE (a, b) (UINT_MAX / 2 >= (a) - (b))#define UINT_CMP_LT (a, b) (UINT_MAX / 2 < (a) - (b))#define ULONG_CMP_GE (a, b) (ULONG_MAX / 2 >= (a) - (b))
@@ -68,7 +80,6 @@ extern void call_rcu_sched(struct rcu_head *head,extern void synchronize_sched (void );extern void rcu_barrier_bh (void );extern void rcu_barrier_sched (void ); -extern int sched_expedited_torture_stats (char *page);static inline void __rcu_read_lock_bh (void ) {
include/linux/rcutree.h +3 -0
@@ -58,9 +58,12 @@ static inline void synchronize_rcu_bh_expedited(void)extern void rcu_barrier (void ); +extern unsigned long rcutorture_testseq; +extern unsigned long rcutorture_vernum;extern long rcu_batches_completed (void );extern long rcu_batches_completed_bh (void );extern long rcu_batches_completed_sched (void ); +extern void rcu_force_quiescent_state (void );extern void rcu_bh_force_quiescent_state (void );extern void rcu_sched_force_quiescent_state (void );
kernel/rcutorture.c +5 -3
@@ -131,7 +131,7 @@ struct rcu_torture {static LIST_HEAD (rcu_torture_freelist);static struct rcu_torture __rcu *rcu_torture_current; -static long rcu_torture_current_version; +static unsigned long rcu_torture_current_version;static struct rcu_torture rcu_tortures[10 *RCU_TORTURE_PIPE_LEN ];static DEFINE_SPINLOCK (rcu_torture_lock); static DEFINE_PER_CPU(long [RCU_TORTURE_PIPE_LEN + 1], rcu_torture_count) =
@@ -886,7 +886,7 @@ rcu_torture_writer(void *arg) old_rp->rtort_pipe_count++; cur_ops->deferred_free (old_rp); } - rcu_torture_current_version++; +rcutorture_record_progress (++rcu_torture_current_version); oldbatch = cur_ops->completed ();rcu_stutter_wait ("rcu_torture_writer" ); }while (!kthread_should_stop () && fullstop ==FULLSTOP_DONTSTOP );
@@ -1066,7 +1066,7 @@ rcu_torture_printk(char *page) } cnt +=sprintf (&page[cnt],"%s%s " , torture_type,TORTURE_FLAG ); cnt += sprintf(&page[cnt], - "rtc: %p ver: %ld tfle: %d rta: %d rtaf: %d rtf: %d " + "rtc: %p ver: %lu tfle: %d rta: %d rtaf: %d rtf: %d " "rtmbe: %d rtbke: %ld rtbre: %ld " "rtbf: %ld rtb: %ld nt: %ld", rcu_torture_current,
@@ -1329,6 +1329,7 @@ rcu_torture_cleanup(void)int i;mutex_lock (&fullstop_mutex); +rcutorture_record_test_transition ();if (fullstop ==FULLSTOP_SHUTDOWN ) {printk (KERN_WARNING /* but going down anyway, so... */ "Concurrent 'rmmod rcutorture' and shutdown illegal!\n" );
@@ -1622,6 +1623,7 @@ rcu_torture_init(void) } }register_reboot_notifier (&rcutorture_shutdown_nb); +rcutorture_record_test_transition ();mutex_unlock (&fullstop_mutex);return 0 ;
kernel/rcutree.c +37 -0
@@ -102,6 +102,18 @@ static void invoke_rcu_cpu_kthread(void);#define RCU_KTHREAD_PRIO 1/* RT priority for per-CPU kthreads. */ /* +* Track the rcutorture test sequence number and the update version +* number within a given test. The rcutorture_testseq is incremented +* on every rcutorture module load and unload, so has an odd value +* when a test is running. The rcutorture_vernum is set to zero +* when rcutorture starts and is incremented on each rcutorture update. +* These variables enable correlating rcutorture output with the +* RCU tracing information. +*/ +unsigned long rcutorture_testseq; +unsigned long rcutorture_vernum; + +/* * Return true if an RCU grace period is in progress. The ACCESS_ONCE()s * permit this function to be invoked without holding the root rcu_node * structure's ->lock, but of course results can be subject to change.
@@ -193,6 +205,31 @@ void rcu_bh_force_quiescent_state(void)EXPORT_SYMBOL_GPL (rcu_bh_force_quiescent_state);/* +* Record the number of times rcutorture tests have been initiated and +* terminated. This information allows the debugfs tracing stats to be +* correlated to the rcutorture messages, even when the rcutorture module +* is being repeatedly loaded and unloaded. In other words, we cannot +* store this state in rcutorture itself. +*/ +void rcutorture_record_test_transition (void ) +{ + rcutorture_testseq++; + rcutorture_vernum =0 ; +} +EXPORT_SYMBOL_GPL (rcutorture_record_test_transition); + +/* +* Record the number of writer passes through the current rcutorture test. +* This is also used to correlate debugfs tracing stats with the rcutorture +* messages. +*/ +void rcutorture_record_progress (unsigned long vernum) +{ + rcutorture_vernum++; +} +EXPORT_SYMBOL_GPL (rcutorture_record_progress); + +/* * Force a quiescent state for RCU-sched. */ void rcu_sched_force_quiescent_state (void )
kernel/rcutree_trace.c +28 -0
@@ -394,6 +394,29 @@ static const struct file_operations rcu_pending_fops = { .release = single_release, }; +static int show_rcutorture (struct seq_file *m,void *unused) +{ +seq_printf (m,"rcutorture test sequence: %lu %s\n" , + rcutorture_testseq >>1 , + (rcutorture_testseq &0x1 ) ?"(test in progress)" :"" ); +seq_printf (m,"rcutorture update version number: %lu\n" , + rcutorture_vernum); +return 0 ; +} + +static int rcutorture_open (struct inode *inode,struct file *file) +{ +return single_open (file, show_rcutorture,NULL ); +} + +static const struct file_operations rcutorture_fops = { + .owner =THIS_MODULE , + .open = rcutorture_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; +static struct dentry *rcudir;static int __init rcutree_trace_init (void )
@@ -430,6 +453,11 @@ static int __init rcutree_trace_init(void) NULL, &rcu_pending_fops);if (!retval) goto free_out; + + retval =debugfs_create_file ("rcutorture" ,0444 , rcudir, +NULL , &rcutorture_fops); +if (!retval) + goto free_out;return 0 ; free_out:debugfs_remove_recursive (rcudir);
Signature · 1 line
1.7.3.2
Josh Triplett
maintainerRe: [PATCH tip/core/rcu 16/86] rcu: make rcutorture version numbers available through debugfs
Quoted 5 lines · Paul E. McKenney
From: Paul E. McKenney <[email protected]>
It is not possible to accurately correlate rcutorture output with that of debugfs. This patch therefore adds a debugfs file that prints out the rcutorture version number, permitting easy correlation.
You can't accurately correlate debugfs values with each other, either, right? The rcutorture version number can change between accesses to different debugfs files.
- Josh Triplett
Re: [PATCH tip/core/rcu 16/86] rcu: make rcutorture version numbers available through debugfs
Quoted 10 lines · Josh Triplett
Quoted 5 lines · Paul E. McKenney
From: Paul E. McKenney <[email protected]>
It is not possible to accurately correlate rcutorture output with that of debugfs. This patch therefore adds a debugfs file that prints out the rcutorture version number, permitting easy correlation.
You can't accurately correlate debugfs values with each other, either, right? The rcutorture version number can change between accesses to different debugfs files.
True, but this is OK given the use case.
The problem that I used to have was that an automated test run would get a grace-period hang somewhere in the middle of a long run. Now, in a grace-period hang, most of the interesting debugfs output is static, so it is not necessary to line them up exactly. All that is needed is for the corellation to be good enough for me to ignore the debugfs output that came a long time before the hang started.
Also, if there is an RCU grace-period hang, the rcutorture version number will stop changing once it has the entire array waiting for a grace period, which normally happens in a few seconds.
Make sense, or am I missing your point?
Thanx, Paul
Josh Triplett
maintainerRe: [PATCH tip/core/rcu 16/86] rcu: make rcutorture version numbers available through debugfs
Quoted 21 lines · Paul E. McKenney
Quoted 10 lines · Josh Triplett
Quoted 5 lines · Paul E. McKenney
From: Paul E. McKenney <[email protected]>
It is not possible to accurately correlate rcutorture output with that of debugfs. This patch therefore adds a debugfs file that prints out the rcutorture version number, permitting easy correlation.
You can't accurately correlate debugfs values with each other, either, right? The rcutorture version number can change between accesses to different debugfs files.
True, but this is OK given the use case.
The problem that I used to have was that an automated test run would get a grace-period hang somewhere in the middle of a long run. Now, in a grace-period hang, most of the interesting debugfs output is static, so it is not necessary to line them up exactly. All that is needed is for the corellation to be good enough for me to ignore the debugfs output that came a long time before the hang started.
Quoted 5 lines
Also, if there is an RCU grace-period hang, the rcutorture version number will stop changing once it has the entire array waiting for a grace period, which normally happens in a few seconds.
Make sense, or am I missing your point?
Makes sense.
- Josh Triplett
PATCH 17/86 rcu: fix boost-tracing bug and update tracing documentation
In reply to Paul E. McKenneyFrom: Paul E. McKenney <[email protected]>
--- Documentation/RCU/trace.txt | 169 +++++++++++++++++++++++++++++++++++++------ kernel/rcutree_plugin.h | 2 +- 2 files changed, 149 insertions(+), 22 deletions(-)
Documentation/RCU/trace.txt +148 -21
@@ -10,34 +10,37 @@ for rcutree and next for rcutiny. CONFIG_TREE_RCU and CONFIG_TREE_PREEMPT_RCU debugfs Files and Formats -These implementations of RCU provides five debugfs files under the +These implementations of RCU provides seven debugfs files under the top-level directory RCU: rcu/rcudata (which displays fields in struct rcu_data), rcu/rcudata.csv (which is a .csv spreadsheet version of rcu/rcudata), rcu/rcugp (which displays grace-period counters), -rcu/rcuhier (which displays the struct rcu_node hierarchy), and +rcu/rcuhier (which displays the struct rcu_node hierarchy), rcu/rcu_pending (which displays counts of the reasons that the -rcu_pending() function decided that there was core RCU work to do). +rcu_pending() function decided that there was core RCU work to do), +rcu/rcutorture (which displays rcutorture test progress), and, if the +kernel is built with CONFIG_RCU_BOOST, rcu/rcuboost (which displays RCU +boosting statistics). The output of "cat rcu/rcudata" looks as follows: rcu_sched: - 0!c=423090 g=423091 pq=1 pqc=423090 qp=1 dt=86475/1/0 df=16319 of=163 ri=1519 ql=0 qs=.... b=10 ci=1460693 co=1648 ca=6448 - 1!c=423329 g=423330 pq=1 pqc=423329 qp=1 dt=90875/1/0 df=16231 of=157 ri=1249 ql=0 qs=.... b=10 ci=1459002 co=1614 ca=3310 - 2!c=423370 g=423371 pq=1 pqc=423370 qp=1 dt=69661/1/0 df=16125 of=163 ri=1469 ql=0 qs=.... b=10 ci=1610701 co=2015 ca=2378 - 3!c=422967 g=422968 pq=1 pqc=422967 qp=1 dt=70349/1/0 df=12528 of=163 ri=1450 ql=0 qs=.... b=10 ci=1427543 co=1430 ca=897 - 4!c=423196 g=423197 pq=1 pqc=423196 qp=0 dt=38935/1/0 df=10959 of=177 ri=1657 ql=0 qs=.... b=10 ci=1562249 co=1896 ca=533 - 5!c=422950 g=422951 pq=1 pqc=422950 qp=0 dt=25127/1/0 df=5895 of=167 ri=1549 ql=0 qs=.... b=10 ci=1777260 co=2137 ca=274 - 6!c=423396 g=423397 pq=1 pqc=423396 qp=1 dt=22639/1/0 df=4590 of=149 ri=1572 ql=0 qs=.... b=10 ci=1471186 co=1530 ca=243 - 7 c=460203 g=460203 pq=1 pqc=460202 qp=0 dt=937087/1/0 df=3298 of=149 ri=1584 ql=6 qs=N.W. b=10 ci=4026154 co=1948 ca=135 + 0!c=423090 g=423091 pq=1 pqc=423090 qp=1 dt=86475/1/0 df=16319 of=163 ri=1519 ql=0 qs=.... kt=0/W b=10 ci=1460693 co=1648 ca=6448 + 1!c=423329 g=423330 pq=1 pqc=423329 qp=1 dt=90875/1/0 df=16231 of=157 ri=1249 ql=0 qs=.... kt=0/W b=10 ci=1459002 co=1614 ca=3310 + 2!c=423370 g=423371 pq=1 pqc=423370 qp=1 dt=69661/1/0 df=16125 of=163 ri=1469 ql=0 qs=.... kt=0/W b=10 ci=1610701 co=2015 ca=2378 + 3!c=422967 g=422968 pq=1 pqc=422967 qp=1 dt=70349/1/0 df=12528 of=163 ri=1450 ql=0 qs=.... kt=0/W b=10 ci=1427543 co=1430 ca=897 + 4!c=423196 g=423197 pq=1 pqc=423196 qp=0 dt=38935/1/0 df=10959 of=177 ri=1657 ql=0 qs=.... kt=0/W b=10 ci=1562249 co=1896 ca=533 + 5!c=422950 g=422951 pq=1 pqc=422950 qp=0 dt=25127/1/0 df=5895 of=167 ri=1549 ql=0 qs=.... kt=0/W b=10 ci=1777260 co=2137 ca=274 + 6!c=423396 g=423397 pq=1 pqc=423396 qp=1 dt=22639/1/0 df=4590 of=149 ri=1572 ql=0 qs=.... kt=0/W b=10 ci=1471186 co=1530 ca=243 + 7 c=460203 g=460203 pq=1 pqc=460202 qp=0 dt=937087/1/0 df=3298 of=149 ri=1584 ql=6 qs=N.W. kt=0/W b=10 ci=4026154 co=1948 ca=135 rcu_bh: - 0!c=18446744073709551494 g=18446744073709551494 pq=0 pqc=18446744073709551493 qp=1 dt=86475/1/0 df=11 of=0 ri=0 ql=0 qs=.... b=10 ci=112 co=0 ca=0 - 1!c=18446744073709551496 g=18446744073709551496 pq=1 pqc=18446744073709551495 qp=0 dt=90875/1/0 df=15 of=0 ri=0 ql=0 qs=.... b=10 ci=143 co=0 ca=0 - 2!c=18446744073709551496 g=18446744073709551496 pq=1 pqc=18446744073709551495 qp=0 dt=69661/1/0 df=21 of=0 ri=1 ql=0 qs=.... b=10 ci=88 co=0 ca=0 - 3!c=18446744073709551494 g=18446744073709551494 pq=1 pqc=18446744073709551493 qp=0 dt=70349/1/0 df=13 of=0 ri=0 ql=0 qs=.... b=10 ci=100 co=0 ca=0 - 4!c=18446744073709551494 g=18446744073709551494 pq=0 pqc=18446744073709551493 qp=1 dt=38935/1/0 df=17 of=0 ri=0 ql=0 qs=.... b=10 ci=36 co=0 ca=0 - 5!c=18446744073709551494 g=18446744073709551494 pq=0 pqc=18446744073709551493 qp=1 dt=25127/1/0 df=7 of=0 ri=0 ql=0 qs=.... b=10 ci=32 co=0 ca=0 - 6!c=18446744073709551496 g=18446744073709551496 pq=1 pqc=18446744073709551495 qp=0 dt=22639/1/0 df=9 of=0 ri=0 ql=0 qs=.... b=10 ci=44 co=0 ca=0 - 7 c=182 g=182 pq=1 pqc=181 qp=0 dt=937087/1/0 df=14 of=0 ri=1 ql=0 qs=.... b=10 ci=627 co=0 ca=0 + 0!c=18446744073709551494 g=18446744073709551494 pq=0 pqc=18446744073709551493 qp=1 dt=86475/1/0 df=11 of=0 ri=0 ql=0 qs=.... kt=0/W b=10 ci=112 co=0 ca=0 + 1!c=18446744073709551496 g=18446744073709551496 pq=1 pqc=18446744073709551495 qp=0 dt=90875/1/0 df=15 of=0 ri=0 ql=0 qs=.... kt=0/W b=10 ci=143 co=0 ca=0 + 2!c=18446744073709551496 g=18446744073709551496 pq=1 pqc=18446744073709551495 qp=0 dt=69661/1/0 df=21 of=0 ri=1 ql=0 qs=.... kt=0/W b=10 ci=88 co=0 ca=0 + 3!c=18446744073709551494 g=18446744073709551494 pq=1 pqc=18446744073709551493 qp=0 dt=70349/1/0 df=13 of=0 ri=0 ql=0 qs=.... kt=0/W b=10 ci=100 co=0 ca=0 + 4!c=18446744073709551494 g=18446744073709551494 pq=0 pqc=18446744073709551493 qp=1 dt=38935/1/0 df=17 of=0 ri=0 ql=0 qs=.... kt=0/W b=10 ci=36 co=0 ca=0 + 5!c=18446744073709551494 g=18446744073709551494 pq=0 pqc=18446744073709551493 qp=1 dt=25127/1/0 df=7 of=0 ri=0 ql=0 qs=.... kt=0/W b=10 ci=32 co=0 ca=0 + 6!c=18446744073709551496 g=18446744073709551496 pq=1 pqc=18446744073709551495 qp=0 dt=22639/1/0 df=9 of=0 ri=0 ql=0 qs=.... kt=0/W b=10 ci=44 co=0 ca=0 + 7 c=182 g=182 pq=1 pqc=181 qp=0 dt=937087/1/0 df=14 of=0 ri=1 ql=0 qs=.... kt=0/W b=10 ci=627 co=0 ca=0 The first section lists the rcu_data structures for rcu_sched, the second for rcu_bh. Note that CONFIG_TREE_PREEMPT_RCU kernels will have an
@@ -146,6 +149,23 @@ o "qs" gives an indication of the state of the callback queue If there are no callbacks in a given one of the above states, the corresponding character is replaced by ".". +o "kt" is the per-CPU kernel-thread state. The digit preceding + the slash is zero if there is no work pending and 1 otherwise. + The character after the slash is as follows: + + "S" The kernel thread is stopped, in other words, all + CPUs corresponding to this rcu_node structure are + offline. + + "R" The kernel thread is running. + + "W" The kernel thread is waiting because there is no work + for it to do. + + "Y" The kernel thread is yielding to avoid hogging CPU. + + "?" Unknown value, indicates a bug. + o "b" is the batch limit for this CPU. If more than this number of RCU callbacks is ready to invoke, then the remainder will be deferred.
@@ -356,6 +376,113 @@ o "nn" is the number of times that this CPU needed nothing. Alert is due to short-circuit evaluation in rcu_pending(). +The output of "cat rcu/rcutorture" looks as follows: + +rcutorture test sequence: 0 (test in progress) +rcutorture update version number: 615 + +The first line shows the number of rcutorture tests that have completed +since boot. If a test is currently running, the "(test in progress)" +string will appear as shown above. The second line shows the number of +update cycles that the current test has started, or zero if there is +no test in progress. + + +The output of "cat rcu/rcuboost" looks as follows: + +0:5 tasks=.... kt=W ntb=0 neb=0 nnb=0 j=2f95 bt=300f + balk: nt=0 egt=989 bt=0 nb=0 ny=0 nos=16 +6:7 tasks=.... kt=W ntb=0 neb=0 nnb=0 j=2f95 bt=300f + balk: nt=0 egt=225 bt=0 nb=0 ny=0 nos=6 + +This information is output only for rcu_preempt. Each two-line entry +corresponds to a leaf rcu_node strcuture. The fields are as follows: + +o "n:m" is the CPU-number range for the corresponding two-line + entry. In the sample output above, the first entry covers + CPUs zero through five and the second entry covers CPUs 6 + and 7. + +o "tasks=TNEB" gives the state of the various segments of the + rnp->blocked_tasks list: + + "T" This indicates that there are some tasks that blocked + while running on one of the corresponding CPUs while + in an RCU read-side critical section. + + "N" This indicates that some of the blocked tasks are preventing + the current normal (non-expedited) grace period from + completing. + + "E" This indicates that some of the blocked tasks are preventing + the current expedited grace period from completing. + + "B" This indicates that some of the blocked tasks are in + need of RCU priority boosting. + + Each character is replaced with "." if the corresponding + condition does not hold. + +o "kt" is the state of the RCU priority-boosting kernel + thread associated with the corresponding rcu_node structure. + The state can be one of the following: + + "S" The kernel thread is stopped, in other words, all + CPUs corresponding to this rcu_node structure are + offline. + + "R" The kernel thread is running. + + "W" The kernel thread is waiting because there is no work + for it to do. + + "Y" The kernel thread is yielding to avoid hogging CPU. + + "?" Unknown value, indicates a bug. + +o "ntb" is the number of tasks boosted. + +o "neb" is the number of tasks boosted in order to complete an + expedited grace period. + +o "nnb" is the number of tasks boosted in order to complete a + normal (non-expedited) grace period. When boosting a task + that was blocking both an expedited and a normal grace period, + it is counted against the expedited total above. + +o "j" is the low-order 16 bits of the jiffies counter in + hexadecimal. + +o "bt" is the low-order 16 bits of the value that the jiffies + counter will have when we next start boosting, assuming that + the current grace period does not end beforehand. This is + also in hexadecimal. + +o "balk: nt" counts the number of times we didn't boost (in + other words, we balked) even though it was time to boost because + there were no blocked tasks to boost. This situation occurs + when there is one blocked task on one rcu_node structure and + none on some other rcu_node structure. + +o "egt" counts the number of times we balked because although + there were blocked tasks, none of them were blocking the + current grace period, whether expedited or otherwise. + +o "bt" counts the number of times we balked because boosting + had already been initiated for the current grace period. + +o "nb" counts the number of times we balked because there + was at least one task blocking the current non-expedited grace + period that never had blocked. If it is already running, it + just won't help to boost its priority! + +o "ny" counts the number of times we balked because it was + not yet time to start boosting. + +o "nos" counts the number of times we balked for other + reasons, e.g., the grace period ended first. + + CONFIG_TINY_RCU and CONFIG_TINY_PREEMPT_RCU debugfs Files and Formats These implementations of RCU provides a single debugfs file under the
@@ -422,9 +549,9 @@ o "neb" is the number of expedited grace periods that have had o "nnb" is the number of normal grace periods that have had to resort to RCU priority boosting since boot. -o "j" is the low-order 12 bits of the jiffies counter in hexadecimal. +o "j" is the low-order 16 bits of the jiffies counter in hexadecimal. -o "bt" is the low-order 12 bits of the value that the jiffies counter +o "bt" is the low-order 16 bits of the value that the jiffies counter will have at the next time that boosting is scheduled to begin. o In the line beginning with "normal balk", the fields are as follows:
kernel/rcutree_plugin.h +1 -1
@@ -1086,7 +1086,7 @@ static void rcu_initiate_boost_trace(struct rcu_node *rnp)else if (rnp->gp_tasks !=NULL && rnp->qsmask !=0 ) rnp->n_balk_notblocked++;else if (rnp->gp_tasks !=NULL && -ULONG_CMP_GE (jiffies, rnp->boost_time)) +ULONG_CMP_LT (jiffies, rnp->boost_time)) rnp->n_balk_notyet++;else rnp->n_balk_nos++;
Signature · 1 line
1.7.3.2
Josh Triplett
maintainerRe: [PATCH tip/core/rcu 17/86] rcu: fix boost-tracing bug and update tracing documentation
The bugfix here should really go in a separate commit from the updated documentation. Also:
Documentation/RCU/trace.txt for rcutree and next for rcutiny. · line 13
Quoted 8 lines · Paul E. McKenney
Documentation/RCU/trace.txt +1
-1@@ -10,34 +10,37 @@ for rcutree and next for rcutiny. CONFIG_TREE_RCU and CONFIG_TREE_PREEMPT_RCU debugfs Files and Formats -These implementations of RCU provides five debugfs files under the +These implementations of RCU provides seven debugfs files under the
s/seven/several/, so this doesn't continue to need updates as you add more tracing? It doesn't seem entirely accurate even now, given that the set of files available now depends on CONFIG_RCU_BOOST.
Documentation/RCU/trace.txt for rcutree and next for rcutiny. · line 14
Quoted 1 line
Documentation/RCU/trace.txt +0
-0top-level directory RCU: rcu/rcudata (which displays fields in struct
RCU or rcu?
Documentation/RCU/trace.txt for rcutree and next for rcutiny. · line 22
Quoted 10 lines
Documentation/RCU/trace.txt +5
-2rcu_data), rcu/rcudata.csv (which is a .csv spreadsheet version of rcu/rcudata), rcu/rcugp (which displays grace-period counters), -rcu/rcuhier (which displays the struct rcu_node hierarchy), and +rcu/rcuhier (which displays the struct rcu_node hierarchy), rcu/rcu_pending (which displays counts of the reasons that the -rcu_pending() function decided that there was core RCU work to do). +rcu_pending() function decided that there was core RCU work to do), +rcu/rcutorture (which displays rcutorture test progress), and, if the +kernel is built with CONFIG_RCU_BOOST, rcu/rcuboost (which displays RCU +boosting statistics).
I think this would work better as a list:
rcu/rcudata:
Displays fields in struct rcu_data.
rcu/rcudata.csv:
Comma-separated values spreadsheet version of rcudata.
rcu/rcugp:
Displays grace-period counters.
rcu/rcuhier
Displays the struct rcu_node hierarchy.
rcu/rcu_pending:
Displays counts of the reasons rcu_pending() decided that RCU had work to do.
rcu/rcutorture:
Displays rcutorture test progress.
rcu/rcuboost
Displays RCU boosting statistics. Only present if CONFIG_RCU_BOOST=y.
Feel free to put the descriptions on the same lines as the filenames if you prefer; however, I thought this style worked better for the descriptions longer than one line.
Also, does rcu/rcutorture appear with rcutorture not loaded? Hopefully not, since rcutorture shouldn't take up any additional resources when not loaded.
kernel/rcutree_plugin.h static void rcu_initiate_boost_trace(struct rcu_node *rnp) · line 1092
Quoted 11 lines
kernel/rcutree_plugin.h +1
-1@@ -1086,7 +1086,7 @@ static void rcu_initiate_boost_trace(struct rcu_node *rnp)else if (rnp->gp_tasks !=NULL && rnp->qsmask !=0 ) rnp->n_balk_notblocked++;else if (rnp->gp_tasks !=NULL && -ULONG_CMP_GE (jiffies, rnp->boost_time)) +ULONG_CMP_LT (jiffies, rnp->boost_time)) rnp->n_balk_notyet++;else rnp->n_balk_nos++;
This bugfix should go in a separate commit.
- Josh Triplett
Re: [PATCH tip/core/rcu 17/86] rcu: fix boost-tracing bug and update tracing documentation
Quoted 8 lines · Josh Triplett
The bugfix here should really go in a separate commit from the updated documentation. Also:
Quoted 4 lines · Paul E. McKenney
Documentation/RCU/trace.txt +0
-0@@ -10,34 +10,37 @@ for rcutree and next for rcutiny.
Quoted 8 lines
Documentation/RCU/trace.txt for rcutree and next for rcutiny. · line 13
Quoted 4 lines
Documentation/RCU/trace.txt +1
-1CONFIG_TREE_RCU and CONFIG_TREE_PREEMPT_RCU debugfs Files and Formats -These implementations of RCU provides five debugfs files under the +These implementations of RCU provides seven debugfs files under thes/seven/several/, so this doesn't continue to need updates as you add more tracing? It doesn't seem entirely accurate even now, given that the set of files available now depends on
CONFIG_RCU_BOOST.
Good point, will fix.
Quoted 3 lines
Documentation/RCU/trace.txt for rcutree and next for rcutiny. · line 14
Quoted 1 line
Documentation/RCU/trace.txt +0
-0top-level directory RCU: rcu/rcudata (which displays fields in structRCU or rcu?
Indeed, "rcu". Will fix.
Quoted 30 lines
Documentation/RCU/trace.txt for rcutree and next for rcutiny. · line 22
Quoted 10 lines
Documentation/RCU/trace.txt +5
-2rcu_data), rcu/rcudata.csv (which is a .csv spreadsheet version of rcu/rcudata), rcu/rcugp (which displays grace-period counters), -rcu/rcuhier (which displays the struct rcu_node hierarchy), and +rcu/rcuhier (which displays the struct rcu_node hierarchy), rcu/rcu_pending (which displays counts of the reasons that the -rcu_pending() function decided that there was core RCU work to do). +rcu_pending() function decided that there was core RCU work to do), +rcu/rcutorture (which displays rcutorture test progress), and, if the +kernel is built with CONFIG_RCU_BOOST, rcu/rcuboost (which displays RCU +boosting statistics).I think this would work better as a list:
rcu/rcudata:
Displays fields in structrcu_data.
rcu/rcudata.csv:
Comma-separated values spreadsheet version of rcudata.
rcu/rcugp:
Displays grace-period counters.
rcu/rcuhier
Displays the structrcu_nodehierarchy.
rcu/rcu_pending:
Displays counts of the reasonsrcu_pending()decided that RCU had work to do.
rcu/rcutorture:
Displays rcutorture test progress.
rcu/rcuboost
Displays RCU boosting statistics. Only present ifCONFIG_RCU_BOOST=y.
Quoted 3 lines
Feel free to put the descriptions on the same lines as the filenames if you prefer; however, I thought this style worked better for the descriptions longer than one line.
Makes sense, will do a list.
Quoted 3 lines
Also, does rcu/rcutorture appear with rcutorture not loaded? Hopefully not, since rcutorture shouldn't take up any additional resources when not loaded.
Not much choice, unfortunately. If I put the info into rcutorture, then I lose it when rcutorture is unloaded. This is problematic in automated tests that repeatedly load and unload rcutorture.
But the amount of data is small, and I set things up so that TINY_RCU can omit this. TREE_RCU is big enough that it doesn't really matter.
Quoted 5 lines
Quoted 5 lines
kernel/rcutree_plugin.h +0
-0@@ -1086,7 +1086,7 @@ static void rcu_initiate_boost_trace(struct rcu_node *rnp)else if (rnp->gp_tasks !=NULL && rnp->qsmask !=0 ) rnp->n_balk_notblocked++;
Quoted 8 lines
kernel/rcutree_plugin.h static void rcu_initiate_boost_trace(struct rcu_node *rnp) · line 1092
Quoted 6 lines
kernel/rcutree_plugin.h +1
-1else if (rnp->gp_tasks !=NULL && -ULONG_CMP_GE (jiffies, rnp->boost_time)) +ULONG_CMP_LT (jiffies, rnp->boost_time)) rnp->n_balk_notyet++;else rnp->n_balk_nos++;This bugfix should go in a separate commit.
Excellent point, will fix.
Thanx, Paul
Josh Triplett
maintainerRe: [PATCH tip/core/rcu 17/86] rcu: fix boost-tracing bug and update tracing documentation
Quoted 11 lines · Paul E. McKenney
Quoted 3 lines · Josh Triplett
Also, does rcu/rcutorture appear with rcutorture not loaded? Hopefully not, since rcutorture shouldn't take up any additional resources when not loaded.
Not much choice, unfortunately. If I put the info into rcutorture, then I lose it when rcutorture is unloaded. This is problematic in automated tests that repeatedly load and unload rcutorture.
But the amount of data is small, and I set things up so that
TINY_RCUcan omit this.TREE_RCUis big enough that it doesn't really matter.
You could omit it entirely if CONFIG_RCU_TORTURE_TEST=n (rather than =m).
- Josh Triplett
Re: [PATCH tip/core/rcu 17/86] rcu: fix boost-tracing bug and update tracing documentation
Quoted 10 lines · Josh Triplett
Quoted 9 lines · Paul E. McKenney
Quoted 3 lines · Josh Triplett
Also, does rcu/rcutorture appear with rcutorture not loaded? Hopefully not, since rcutorture shouldn't take up any additional resources when not loaded.
Not much choice, unfortunately. If I put the info into rcutorture, then I lose it when rcutorture is unloaded. This is problematic in automated tests that repeatedly load and unload rcutorture.
Quoted 5 lines
Quoted 2 lines
But the amount of data is small, and I set things up so that
TINY_RCUcan omit this.TREE_RCUis big enough that it doesn't really matter.You could omit it entirely if
CONFIG_RCU_TORTURE_TEST=n(rather than =m).
I could, but it doesn't seem worth it. Of course, it might be just the fact that I am writing this from the Toronto airport...
Thanx, Paul
Re: [PATCH tip/core/rcu 17/86] rcu: fix boost-tracing bug and update tracing documentation
In reply to Paul E. McKenneyQuoted 87 lines · Paul E. McKenney
Quoted 8 lines · Josh Triplett
The bugfix here should really go in a separate commit from the updated documentation. Also:
Quoted 4 lines · Paul E. McKenney
Documentation/RCU/trace.txt +0
-0@@ -10,34 +10,37 @@ for rcutree and next for rcutiny.Quoted 8 lines
Documentation/RCU/trace.txt for rcutree and next for rcutiny. · line 13
Quoted 4 lines
Documentation/RCU/trace.txt +1
-1CONFIG_TREE_RCU and CONFIG_TREE_PREEMPT_RCU debugfs Files and Formats -These implementations of RCU provides five debugfs files under the +These implementations of RCU provides seven debugfs files under thes/seven/several/, so this doesn't continue to need updates as you add more tracing? It doesn't seem entirely accurate even now, given that the set of files available now depends on
CONFIG_RCU_BOOST.Good point, will fix.
Quoted 3 lines
Documentation/RCU/trace.txt for rcutree and next for rcutiny. · line 14
Quoted 1 line
Documentation/RCU/trace.txt +0
-0top-level directory RCU: rcu/rcudata (which displays fields in structRCU or rcu?
Indeed, "rcu". Will fix.
Quoted 30 lines
Documentation/RCU/trace.txt for rcutree and next for rcutiny. · line 22
Quoted 10 lines
Documentation/RCU/trace.txt +5
-2rcu_data), rcu/rcudata.csv (which is a .csv spreadsheet version of rcu/rcudata), rcu/rcugp (which displays grace-period counters), -rcu/rcuhier (which displays the struct rcu_node hierarchy), and +rcu/rcuhier (which displays the struct rcu_node hierarchy), rcu/rcu_pending (which displays counts of the reasons that the -rcu_pending() function decided that there was core RCU work to do). +rcu_pending() function decided that there was core RCU work to do), +rcu/rcutorture (which displays rcutorture test progress), and, if the +kernel is built with CONFIG_RCU_BOOST, rcu/rcuboost (which displays RCU +boosting statistics).I think this would work better as a list:
rcu/rcudata:
Displays fields in structrcu_data.
rcu/rcudata.csv:
Comma-separated values spreadsheet version of rcudata.
rcu/rcugp:
Displays grace-period counters.
rcu/rcuhier
Displays the structrcu_nodehierarchy.
rcu/rcu_pending:
Displays counts of the reasonsrcu_pending()decided that RCU had work to do.
rcu/rcutorture:
Displays rcutorture test progress.
rcu/rcuboost
Displays RCU boosting statistics. Only present ifCONFIG_RCU_BOOST=y.Quoted 3 lines
Feel free to put the descriptions on the same lines as the filenames if you prefer; however, I thought this style worked better for the descriptions longer than one line.
Makes sense, will do a list.
Quoted 3 lines
Also, does rcu/rcutorture appear with rcutorture not loaded? Hopefully not, since rcutorture shouldn't take up any additional resources when not loaded.
Not much choice, unfortunately. If I put the info into rcutorture, then I lose it when rcutorture is unloaded. This is problematic in automated tests that repeatedly load and unload rcutorture.
But the amount of data is small, and I set things up so that
TINY_RCUcan omit this.TREE_RCUis big enough that it doesn't really matter.Quoted 5 lines
Quoted 5 lines
kernel/rcutree_plugin.h +0
-0@@ -1086,7 +1086,7 @@ static void rcu_initiate_boost_trace(struct rcu_node *rnp)else if (rnp->gp_tasks !=NULL && rnp->qsmask !=0 ) rnp->n_balk_notblocked++;Quoted 8 lines
kernel/rcutree_plugin.h static void rcu_initiate_boost_trace(struct rcu_node *rnp) · line 1092
Quoted 6 lines
kernel/rcutree_plugin.h +1
-1else if (rnp->gp_tasks !=NULL && -ULONG_CMP_GE (jiffies, rnp->boost_time)) +ULONG_CMP_LT (jiffies, rnp->boost_time)) rnp->n_balk_notyet++;else rnp->n_balk_nos++;This bugfix should go in a separate commit.
Quoted 1 line
Excellent point, will fix.
Here is the updated documentation update.
Thanx, Paul
------------------------------------------------------------------------
rcu: update tracing documentation for new rcutorture and rcuboost
This commit documents the new debugfs rcu/rcutorture and rcu/rcuboost trace files. The description has been updated as suggested by Josh Triplett.
Documentation/RCU/trace.txt +161 -25
@@ -10,34 +10,46 @@ for rcutree and next for rcutiny. CONFIG_TREE_RCU and CONFIG_TREE_PREEMPT_RCU debugfs Files and Formats -These implementations of RCU provides five debugfs files under the -top-level directory RCU: rcu/rcudata (which displays fields in struct -rcu_data), rcu/rcudata.csv (which is a .csv spreadsheet version of -rcu/rcudata), rcu/rcugp (which displays grace-period counters), -rcu/rcuhier (which displays the struct rcu_node hierarchy), and -rcu/rcu_pending (which displays counts of the reasons that the -rcu_pending() function decided that there was core RCU work to do). +These implementations of RCU provides several debugfs files under the +top-level directory "rcu": + +rcu/rcudata: + Displays fields in struct rcu_data. +rcu/rcudata.csv: + Comma-separated values spreadsheet version of rcudata. +rcu/rcugp: + Displays grace-period counters. +rcu/rcuhier: + Displays the struct rcu_node hierarchy. +rcu/rcu_pending: + Displays counts of the reasons rcu_pending() decided that RCU had + work to do. +rcu/rcutorture: + Displays rcutorture test progress. +rcu/rcuboost: + Displays RCU boosting statistics. Only present if + CONFIG_RCU_BOOST=y. The output of "cat rcu/rcudata" looks as follows: rcu_sched: - 0!c=423090 g=423091 pq=1 pqc=423090 qp=1 dt=86475/1/0 df=16319 of=163 ri=1519 ql=0 qs=.... b=10 ci=1460693 co=1648 ca=6448 - 1!c=423329 g=423330 pq=1 pqc=423329 qp=1 dt=90875/1/0 df=16231 of=157 ri=1249 ql=0 qs=.... b=10 ci=1459002 co=1614 ca=3310 - 2!c=423370 g=423371 pq=1 pqc=423370 qp=1 dt=69661/1/0 df=16125 of=163 ri=1469 ql=0 qs=.... b=10 ci=1610701 co=2015 ca=2378 - 3!c=422967 g=422968 pq=1 pqc=422967 qp=1 dt=70349/1/0 df=12528 of=163 ri=1450 ql=0 qs=.... b=10 ci=1427543 co=1430 ca=897 - 4!c=423196 g=423197 pq=1 pqc=423196 qp=0 dt=38935/1/0 df=10959 of=177 ri=1657 ql=0 qs=.... b=10 ci=1562249 co=1896 ca=533 - 5!c=422950 g=422951 pq=1 pqc=422950 qp=0 dt=25127/1/0 df=5895 of=167 ri=1549 ql=0 qs=.... b=10 ci=1777260 co=2137 ca=274 - 6!c=423396 g=423397 pq=1 pqc=423396 qp=1 dt=22639/1/0 df=4590 of=149 ri=1572 ql=0 qs=.... b=10 ci=1471186 co=1530 ca=243 - 7 c=460203 g=460203 pq=1 pqc=460202 qp=0 dt=937087/1/0 df=3298 of=149 ri=1584 ql=6 qs=N.W. b=10 ci=4026154 co=1948 ca=135 + 0!c=423090 g=423091 pq=1 pqc=423090 qp=1 dt=86475/1/0 df=16319 of=163 ri=1519 ql=0 qs=.... kt=0/W b=10 ci=1460693 co=1648 ca=6448 + 1!c=423329 g=423330 pq=1 pqc=423329 qp=1 dt=90875/1/0 df=16231 of=157 ri=1249 ql=0 qs=.... kt=0/W b=10 ci=1459002 co=1614 ca=3310 + 2!c=423370 g=423371 pq=1 pqc=423370 qp=1 dt=69661/1/0 df=16125 of=163 ri=1469 ql=0 qs=.... kt=0/W b=10 ci=1610701 co=2015 ca=2378 + 3!c=422967 g=422968 pq=1 pqc=422967 qp=1 dt=70349/1/0 df=12528 of=163 ri=1450 ql=0 qs=.... kt=0/W b=10 ci=1427543 co=1430 ca=897 + 4!c=423196 g=423197 pq=1 pqc=423196 qp=0 dt=38935/1/0 df=10959 of=177 ri=1657 ql=0 qs=.... kt=0/W b=10 ci=1562249 co=1896 ca=533 + 5!c=422950 g=422951 pq=1 pqc=422950 qp=0 dt=25127/1/0 df=5895 of=167 ri=1549 ql=0 qs=.... kt=0/W b=10 ci=1777260 co=2137 ca=274 + 6!c=423396 g=423397 pq=1 pqc=423396 qp=1 dt=22639/1/0 df=4590 of=149 ri=1572 ql=0 qs=.... kt=0/W b=10 ci=1471186 co=1530 ca=243 + 7 c=460203 g=460203 pq=1 pqc=460202 qp=0 dt=937087/1/0 df=3298 of=149 ri=1584 ql=6 qs=N.W. kt=0/W b=10 ci=4026154 co=1948 ca=135 rcu_bh: - 0!c=18446744073709551494 g=18446744073709551494 pq=0 pqc=18446744073709551493 qp=1 dt=86475/1/0 df=11 of=0 ri=0 ql=0 qs=.... b=10 ci=112 co=0 ca=0 - 1!c=18446744073709551496 g=18446744073709551496 pq=1 pqc=18446744073709551495 qp=0 dt=90875/1/0 df=15 of=0 ri=0 ql=0 qs=.... b=10 ci=143 co=0 ca=0 - 2!c=18446744073709551496 g=18446744073709551496 pq=1 pqc=18446744073709551495 qp=0 dt=69661/1/0 df=21 of=0 ri=1 ql=0 qs=.... b=10 ci=88 co=0 ca=0 - 3!c=18446744073709551494 g=18446744073709551494 pq=1 pqc=18446744073709551493 qp=0 dt=70349/1/0 df=13 of=0 ri=0 ql=0 qs=.... b=10 ci=100 co=0 ca=0 - 4!c=18446744073709551494 g=18446744073709551494 pq=0 pqc=18446744073709551493 qp=1 dt=38935/1/0 df=17 of=0 ri=0 ql=0 qs=.... b=10 ci=36 co=0 ca=0 - 5!c=18446744073709551494 g=18446744073709551494 pq=0 pqc=18446744073709551493 qp=1 dt=25127/1/0 df=7 of=0 ri=0 ql=0 qs=.... b=10 ci=32 co=0 ca=0 - 6!c=18446744073709551496 g=18446744073709551496 pq=1 pqc=18446744073709551495 qp=0 dt=22639/1/0 df=9 of=0 ri=0 ql=0 qs=.... b=10 ci=44 co=0 ca=0 - 7 c=182 g=182 pq=1 pqc=181 qp=0 dt=937087/1/0 df=14 of=0 ri=1 ql=0 qs=.... b=10 ci=627 co=0 ca=0 + 0!c=18446744073709551494 g=18446744073709551494 pq=0 pqc=18446744073709551493 qp=1 dt=86475/1/0 df=11 of=0 ri=0 ql=0 qs=.... kt=0/W b=10 ci=112 co=0 ca=0 + 1!c=18446744073709551496 g=18446744073709551496 pq=1 pqc=18446744073709551495 qp=0 dt=90875/1/0 df=15 of=0 ri=0 ql=0 qs=.... kt=0/W b=10 ci=143 co=0 ca=0 + 2!c=18446744073709551496 g=18446744073709551496 pq=1 pqc=18446744073709551495 qp=0 dt=69661/1/0 df=21 of=0 ri=1 ql=0 qs=.... kt=0/W b=10 ci=88 co=0 ca=0 + 3!c=18446744073709551494 g=18446744073709551494 pq=1 pqc=18446744073709551493 qp=0 dt=70349/1/0 df=13 of=0 ri=0 ql=0 qs=.... kt=0/W b=10 ci=100 co=0 ca=0 + 4!c=18446744073709551494 g=18446744073709551494 pq=0 pqc=18446744073709551493 qp=1 dt=38935/1/0 df=17 of=0 ri=0 ql=0 qs=.... kt=0/W b=10 ci=36 co=0 ca=0 + 5!c=18446744073709551494 g=18446744073709551494 pq=0 pqc=18446744073709551493 qp=1 dt=25127/1/0 df=7 of=0 ri=0 ql=0 qs=.... kt=0/W b=10 ci=32 co=0 ca=0 + 6!c=18446744073709551496 g=18446744073709551496 pq=1 pqc=18446744073709551495 qp=0 dt=22639/1/0 df=9 of=0 ri=0 ql=0 qs=.... kt=0/W b=10 ci=44 co=0 ca=0 + 7 c=182 g=182 pq=1 pqc=181 qp=0 dt=937087/1/0 df=14 of=0 ri=1 ql=0 qs=.... kt=0/W b=10 ci=627 co=0 ca=0 The first section lists the rcu_data structures for rcu_sched, the second for rcu_bh. Note that CONFIG_TREE_PREEMPT_RCU kernels will have an
@@ -146,6 +158,23 @@ o "qs" gives an indication of the state of the callback queue If there are no callbacks in a given one of the above states, the corresponding character is replaced by ".". +o "kt" is the per-CPU kernel-thread state. The digit preceding + the slash is zero if there is no work pending and 1 otherwise. + The character after the slash is as follows: + + "S" The kernel thread is stopped, in other words, all + CPUs corresponding to this rcu_node structure are + offline. + + "R" The kernel thread is running. + + "W" The kernel thread is waiting because there is no work + for it to do. + + "Y" The kernel thread is yielding to avoid hogging CPU. + + "?" Unknown value, indicates a bug. + o "b" is the batch limit for this CPU. If more than this number of RCU callbacks is ready to invoke, then the remainder will be deferred.
@@ -356,6 +385,113 @@ o "nn" is the number of times that this CPU needed nothing. Alert is due to short-circuit evaluation in rcu_pending(). +The output of "cat rcu/rcutorture" looks as follows: + +rcutorture test sequence: 0 (test in progress) +rcutorture update version number: 615 + +The first line shows the number of rcutorture tests that have completed +since boot. If a test is currently running, the "(test in progress)" +string will appear as shown above. The second line shows the number of +update cycles that the current test has started, or zero if there is +no test in progress. + + +The output of "cat rcu/rcuboost" looks as follows: + +0:5 tasks=.... kt=W ntb=0 neb=0 nnb=0 j=2f95 bt=300f + balk: nt=0 egt=989 bt=0 nb=0 ny=0 nos=16 +6:7 tasks=.... kt=W ntb=0 neb=0 nnb=0 j=2f95 bt=300f + balk: nt=0 egt=225 bt=0 nb=0 ny=0 nos=6 + +This information is output only for rcu_preempt. Each two-line entry +corresponds to a leaf rcu_node strcuture. The fields are as follows: + +o "n:m" is the CPU-number range for the corresponding two-line + entry. In the sample output above, the first entry covers + CPUs zero through five and the second entry covers CPUs 6 + and 7. + +o "tasks=TNEB" gives the state of the various segments of the + rnp->blocked_tasks list: + + "T" This indicates that there are some tasks that blocked + while running on one of the corresponding CPUs while + in an RCU read-side critical section. + + "N" This indicates that some of the blocked tasks are preventing + the current normal (non-expedited) grace period from + completing. + + "E" This indicates that some of the blocked tasks are preventing + the current expedited grace period from completing. + + "B" This indicates that some of the blocked tasks are in + need of RCU priority boosting. + + Each character is replaced with "." if the corresponding + condition does not hold. + +o "kt" is the state of the RCU priority-boosting kernel + thread associated with the corresponding rcu_node structure. + The state can be one of the following: + + "S" The kernel thread is stopped, in other words, all + CPUs corresponding to this rcu_node structure are + offline. + + "R" The kernel thread is running. + + "W" The kernel thread is waiting because there is no work + for it to do. + + "Y" The kernel thread is yielding to avoid hogging CPU. + + "?" Unknown value, indicates a bug. + +o "ntb" is the number of tasks boosted. + +o "neb" is the number of tasks boosted in order to complete an + expedited grace period. + +o "nnb" is the number of tasks boosted in order to complete a + normal (non-expedited) grace period. When boosting a task + that was blocking both an expedited and a normal grace period, + it is counted against the expedited total above. + +o "j" is the low-order 16 bits of the jiffies counter in + hexadecimal. + +o "bt" is the low-order 16 bits of the value that the jiffies + counter will have when we next start boosting, assuming that + the current grace period does not end beforehand. This is + also in hexadecimal. + +o "balk: nt" counts the number of times we didn't boost (in + other words, we balked) even though it was time to boost because + there were no blocked tasks to boost. This situation occurs + when there is one blocked task on one rcu_node structure and + none on some other rcu_node structure. + +o "egt" counts the number of times we balked because although + there were blocked tasks, none of them were blocking the + current grace period, whether expedited or otherwise. + +o "bt" counts the number of times we balked because boosting + had already been initiated for the current grace period. + +o "nb" counts the number of times we balked because there + was at least one task blocking the current non-expedited grace + period that never had blocked. If it is already running, it + just won't help to boost its priority! + +o "ny" counts the number of times we balked because it was + not yet time to start boosting. + +o "nos" counts the number of times we balked for other + reasons, e.g., the grace period ended first. + + CONFIG_TINY_RCU and CONFIG_TINY_PREEMPT_RCU debugfs Files and Formats These implementations of RCU provides a single debugfs file under the
@@ -422,9 +558,9 @@ o "neb" is the number of expedited grace periods that have had o "nnb" is the number of normal grace periods that have had to resort to RCU priority boosting since boot. -o "j" is the low-order 12 bits of the jiffies counter in hexadecimal. +o "j" is the low-order 16 bits of the jiffies counter in hexadecimal. -o "bt" is the low-order 12 bits of the value that the jiffies counter +o "bt" is the low-order 16 bits of the value that the jiffies counter will have at the next time that boosting is scheduled to begin. o In the line beginning with "normal balk", the fields are as follows:
Re: [PATCH tip/core/rcu 17/86] rcu: fix boost-tracing bug and update tracing documentation
Quoted 88 lines · Paul E. McKenney
Quoted 87 lines · Paul E. McKenney
Quoted 8 lines · Josh Triplett
The bugfix here should really go in a separate commit from the updated documentation. Also:
Quoted 4 lines · Paul E. McKenney
Documentation/RCU/trace.txt +0
-0@@ -10,34 +10,37 @@ for rcutree and next for rcutiny.Quoted 8 lines
Documentation/RCU/trace.txt for rcutree and next for rcutiny. · line 13
Quoted 4 lines
Documentation/RCU/trace.txt +1
-1CONFIG_TREE_RCU and CONFIG_TREE_PREEMPT_RCU debugfs Files and Formats -These implementations of RCU provides five debugfs files under the +These implementations of RCU provides seven debugfs files under thes/seven/several/, so this doesn't continue to need updates as you add more tracing? It doesn't seem entirely accurate even now, given that the set of files available now depends on
CONFIG_RCU_BOOST.Good point, will fix.
Quoted 3 lines
Documentation/RCU/trace.txt for rcutree and next for rcutiny. · line 14
Quoted 1 line
Documentation/RCU/trace.txt +0
-0top-level directory RCU: rcu/rcudata (which displays fields in structRCU or rcu?
Indeed, "rcu". Will fix.
Quoted 30 lines
Documentation/RCU/trace.txt for rcutree and next for rcutiny. · line 22
Quoted 10 lines
Documentation/RCU/trace.txt +5
-2rcu_data), rcu/rcudata.csv (which is a .csv spreadsheet version of rcu/rcudata), rcu/rcugp (which displays grace-period counters), -rcu/rcuhier (which displays the struct rcu_node hierarchy), and +rcu/rcuhier (which displays the struct rcu_node hierarchy), rcu/rcu_pending (which displays counts of the reasons that the -rcu_pending() function decided that there was core RCU work to do). +rcu_pending() function decided that there was core RCU work to do), +rcu/rcutorture (which displays rcutorture test progress), and, if the +kernel is built with CONFIG_RCU_BOOST, rcu/rcuboost (which displays RCU +boosting statistics).I think this would work better as a list:
rcu/rcudata:
Displays fields in structrcu_data.
rcu/rcudata.csv:
Comma-separated values spreadsheet version of rcudata.
rcu/rcugp:
Displays grace-period counters.
rcu/rcuhier
Displays the structrcu_nodehierarchy.
rcu/rcu_pending:
Displays counts of the reasonsrcu_pending()decided that RCU had work to do.
rcu/rcutorture:
Displays rcutorture test progress.
rcu/rcuboost
Displays RCU boosting statistics. Only present ifCONFIG_RCU_BOOST=y.Quoted 3 lines
Feel free to put the descriptions on the same lines as the filenames if you prefer; however, I thought this style worked better for the descriptions longer than one line.
Makes sense, will do a list.
Quoted 3 lines
Also, does rcu/rcutorture appear with rcutorture not loaded? Hopefully not, since rcutorture shouldn't take up any additional resources when not loaded.
Not much choice, unfortunately. If I put the info into rcutorture, then I lose it when rcutorture is unloaded. This is problematic in automated tests that repeatedly load and unload rcutorture.
But the amount of data is small, and I set things up so that
TINY_RCUcan omit this.TREE_RCUis big enough that it doesn't really matter.Quoted 13 lines
kernel/rcutree_plugin.h static void rcu_initiate_boost_trace(struct rcu_node *rnp) · line 1092
Quoted 11 lines
kernel/rcutree_plugin.h +1
-1@@ -1086,7 +1086,7 @@ static void rcu_initiate_boost_trace(struct rcu_node *rnp)else if (rnp->gp_tasks !=NULL && rnp->qsmask !=0 ) rnp->n_balk_notblocked++;else if (rnp->gp_tasks !=NULL && -ULONG_CMP_GE (jiffies, rnp->boost_time)) +ULONG_CMP_LT (jiffies, rnp->boost_time)) rnp->n_balk_notyet++;else rnp->n_balk_nos++;This bugfix should go in a separate commit.
Quoted 3 lines
Quoted 1 line
Excellent point, will fix.
Here is the updated documentation update.
And here is the bug fix.
Thanx, Paul
------------------------------------------------------------------------
rcu: fix tracing bug thinko on boost-balk attribution
The rcu_initiate_boost_trace() function mis-attributed refusals to initiate RCU priority boosting that were in fact due to its not yet being time to boost. This patch fixes the faulty comparison.
kernel/rcutree_plugin.h +1 -1
@@ -1086,7 +1086,7 @@ static void rcu_initiate_boost_trace(struct rcu_node *rnp)else if (rnp->gp_tasks !=NULL && rnp->qsmask !=0 ) rnp->n_balk_notblocked++;else if (rnp->gp_tasks !=NULL && -ULONG_CMP_GE (jiffies, rnp->boost_time)) +ULONG_CMP_LT (jiffies, rnp->boost_time)) rnp->n_balk_notyet++;else rnp->n_balk_nos++;
PATCH 18/86 rcu: add grace-period age to tracing
In reply to Paul E. McKenneyFrom: Paul E. McKenney <[email protected]>
This commit adds the age in jiffies of the current grace period along with the duration in jiffies of the longest grace period since boot to the rcu/rcugp debugfs file.
--- Documentation/RCU/trace.txt | 12 ++++++++++-- kernel/rcutree.c | 10 ++++++++++ kernel/rcutree.h | 7 +++++-- kernel/rcutree_trace.c | 37 +++++++++++++++++++++++++++++-------- 4 files changed, 54 insertions(+), 12 deletions(-)
Documentation/RCU/trace.txt +10 -2
@@ -150,8 +150,8 @@ o "qs" gives an indication of the state of the callback queue the corresponding character is replaced by ".". o "kt" is the per-CPU kernel-thread state. The digit preceding - the slash is zero if there is no work pending and 1 otherwise. - The character after the slash is as follows: + the first slash is zero if there is no work pending and 1 + otherwise. The character between the slashes is as follows: "S" The kernel thread is stopped, in other words, all CPUs corresponding to this rcu_node structure are
@@ -162,10 +162,18 @@ o "kt" is the per-CPU kernel-thread state. The digit preceding "W" The kernel thread is waiting because there is no work for it to do. + "O" The kernel thread is waiting because it has been + forced off of its designated CPU or because its + ->cpus_allowed mask permits it to run on other than + its designated CPU. + "Y" The kernel thread is yielding to avoid hogging CPU. "?" Unknown value, indicates a bug. + The number after the final slash is the CPU that the kthread + is actually running on. + o "b" is the batch limit for this CPU. If more than this number of RCU callbacks is ready to invoke, then the remainder will be deferred.
kernel/rcutree.c +10 -0
@@ -92,6 +92,7 @@ EXPORT_SYMBOL_GPL(rcu_scheduler_active);*/ static DEFINE_PER_CPU(struct task_struct *, rcu_cpu_kthread_task);DEFINE_PER_CPU (unsigned int , rcu_cpu_kthread_status); +DEFINE_PER_CPU (int, rcu_cpu_kthread_cpu); static DEFINE_PER_CPU(wait_queue_head_t, rcu_cpu_wq);DEFINE_PER_CPU (char , rcu_cpu_has_work);static char rcu_kthreads_spawnable;
@@ -888,6 +889,8 @@ rcu_start_gp(struct rcu_state *rsp, unsigned long flags)static void rcu_report_qs_rsp (struct rcu_state *rsp,unsigned long flags) __releases(rcu_get_root(rsp)->lock) { +unsigned long gp_duration; +WARN_ON_ONCE (!rcu_gp_in_progress (rsp));/*
@@ -895,6 +898,9 @@ static void rcu_report_qs_rsp(struct rcu_state *rsp, unsigned long flags)* is seen before the assignment to rsp->completed. */ smp_mb ();/* See above block comment. */ + gp_duration = jiffies - rsp->gp_start; +if (gp_duration > rsp->gp_max) + rsp->gp_max = gp_duration; rsp->completed = rsp->gpnum; rsp->signaled =RCU_GP_IDLE ;rcu_start_gp (rsp, flags);/* releases root node's rnp->lock. */
@@ -1583,12 +1589,15 @@ static int rcu_cpu_kthread_should_stop(int cpu) smp_processor_id() != cpu) {if (kthread_should_stop ())return 1 ; +per_cpu (rcu_cpu_kthread_status, cpu) =RCU_KTHREAD_OFFCPU ; +per_cpu (rcu_cpu_kthread_cpu, cpu) =raw_smp_processor_id ();local_bh_enable ();schedule_timeout_uninterruptible (1 );if (!cpumask_equal (¤t->cpus_allowed,cpumask_of (cpu)))set_cpus_allowed_ptr (current,cpumask_of (cpu));local_bh_disable (); } +per_cpu (rcu_cpu_kthread_cpu, cpu) = cpu;return 0 ; }
@@ -1656,6 +1665,7 @@ static int __cpuinit rcu_spawn_one_cpu_kthread(int cpu)if (IS_ERR (t))return PTR_ERR (t);kthread_bind (t, cpu); +per_cpu (rcu_cpu_kthread_cpu, cpu) = cpu;WARN_ON_ONCE (per_cpu (rcu_cpu_kthread_task, cpu) !=NULL );per_cpu (rcu_cpu_kthread_task, cpu) = t;wake_up_process (t);
kernel/rcutree.h +5 -2
@@ -93,8 +93,9 @@ struct rcu_dynticks {#define RCU_KTHREAD_STOPPED 0#define RCU_KTHREAD_RUNNING 1#define RCU_KTHREAD_WAITING 2 -#define RCU_KTHREAD_YIELDING 3 -#define RCU_KTHREAD_MAX 3 +#define RCU_KTHREAD_OFFCPU 3 +#define RCU_KTHREAD_YIELDING 4 +#define RCU_KTHREAD_MAX 4/* * Definition for node within the RCU grace-period-detection hierarchy.
@@ -383,6 +384,8 @@ struct rcu_state {/* but in jiffies. */ unsigned long jiffies_stall;/* Time at which to check */ /* for CPU stalls. */ +unsigned long gp_max;/* Maximum GP duration in */ +/* jiffies. */ char *name;/* Name of structure. */ };
kernel/rcutree_trace.c +29 -8
@@ -47,13 +47,14 @@#include "rcutree.h" DECLARE_PER_CPU(unsigned int, rcu_cpu_kthread_status); +DECLARE_PER_CPU(unsigned int, rcu_cpu_kthread_cpu);DECLARE_PER_CPU (char, rcu_cpu_has_work);static char convert_kthread_status (unsigned int kthread_status) {if (kthread_status >RCU_KTHREAD_MAX )return '?' ; -return "SRWY" [kthread_status]; +return "SRWOY" [kthread_status]; }static void print_one_rcu_data (struct seq_file *m,struct rcu_data *rdp)
@@ -74,7 +75,7 @@ static void print_one_rcu_data(struct seq_file *m, struct rcu_data *rdp) rdp->dynticks_fqs);#endif /* #ifdef CONFIG_NO_HZ */ seq_printf (m," of=%lu ri=%lu" , rdp->offline_fqs, rdp->resched_ipi); - seq_printf(m, " ql=%ld qs=%c%c%c%c kt=%d/%c b=%ld", + seq_printf(m, " ql=%ld qs=%c%c%c%c kt=%d/%c/%d b=%ld", rdp->qlen, ".N"[rdp->nxttail[RCU_NEXT_READY_TAIL] != rdp->nxttail[RCU_NEXT_TAIL]],
@@ -86,6 +87,7 @@ static void print_one_rcu_data(struct seq_file *m, struct rcu_data *rdp)per_cpu (rcu_cpu_has_work, rdp->cpu),convert_kthread_status (per_cpu (rcu_cpu_kthread_status, rdp->cpu)), +per_cpu (rcu_cpu_kthread_cpu, rdp->cpu), rdp->blimit);seq_printf (m," ci=%lu co=%lu ca=%lu\n" , rdp->n_cbs_invoked, rdp->n_cbs_orphaned, rdp->n_cbs_adopted);
@@ -312,16 +314,35 @@ static const struct file_operations rcuhier_fops = { .release = single_release, }; +static void show_one_rcugp (struct seq_file *m,struct rcu_state *rsp) +{ +unsigned long flags; +unsigned long completed; +unsigned long gpnum; +unsigned long gpage; +unsigned long gpmax; +struct rcu_node *rnp = &rsp->node[0 ]; + +raw_spin_lock_irqsave (&rnp->lock, flags); + completed = rsp->completed; + gpnum = rsp->gpnum; +if (rsp->completed == rsp->gpnum) + gpage =0 ; +else + gpage = jiffies - rsp->gp_start; + gpmax = rsp->gp_max; +raw_spin_unlock_irqrestore (&rnp->lock, flags); +seq_printf (m,"%s: completed=%ld gpnum=%lu age=%ld max=%ld\n" , + rsp->name, completed, gpnum, gpage, gpmax); +} +static int show_rcugp (struct seq_file *m,void *unused) {#ifdef CONFIG_TREE_PREEMPT_RCU -seq_printf (m,"rcu_preempt: completed=%ld gpnum=%lu\n" , - rcu_preempt_state.completed, rcu_preempt_state.gpnum); +show_one_rcugp (m, &rcu_preempt_state);#endif /* #ifdef CONFIG_TREE_PREEMPT_RCU */ -seq_printf (m,"rcu_sched: completed=%ld gpnum=%lu\n" , - rcu_sched_state.completed, rcu_sched_state.gpnum); -seq_printf (m,"rcu_bh: completed=%ld gpnum=%lu\n" , - rcu_bh_state.completed, rcu_bh_state.gpnum); +show_one_rcugp (m, &rcu_sched_state); +show_one_rcugp (m, &rcu_bh_state);return 0 ; }
Signature · 1 line
1.7.3.2
Josh Triplett
maintainerRe: [PATCH tip/core/rcu 18/86] rcu: add grace-period age to tracing
Quoted 5 lines · Paul E. McKenney
From: Paul E. McKenney <[email protected]>
This commit adds the age in jiffies of the current grace period along with the duration in jiffies of the longest grace period since boot to the rcu/rcugp debugfs file.
This change seems to have several other unrelated changes mixed in and not documented, related to adding and tracing RCU_KTHREAD_OFFCPU.
- Josh Triplett
Re: [PATCH tip/core/rcu 18/86] rcu: add grace-period age to tracing
Quoted 9 lines · Josh Triplett
Quoted 5 lines · Paul E. McKenney
From: Paul E. McKenney <[email protected]>
This commit adds the age in jiffies of the current grace period along with the duration in jiffies of the longest grace period since boot to the rcu/rcugp debugfs file.
This change seems to have several other unrelated changes mixed in and not documented, related to adding and tracing
RCU_KTHREAD_OFFCPU.
Hmmm... I do have two commits worth of stuff in there, don't I?
Good catch, will fix!
Thanx, Paul
Re: [PATCH tip/core/rcu 18/86] rcu: add grace-period age to tracing
Quoted 8 lines · Paul E. McKenney
Quoted 7 lines · Josh Triplett
Quoted 5 lines · Paul E. McKenney
From: Paul E. McKenney <[email protected]>
This commit adds the age in jiffies of the current grace period along with the duration in jiffies of the longest grace period since boot to the rcu/rcugp debugfs file.
Quoted 6 lines
Quoted 2 lines
This change seems to have several other unrelated changes mixed in and not documented, related to adding and tracing
RCU_KTHREAD_OFFCPU.Hmmm... I do have two commits worth of stuff in there, don't I?
Good catch, will fix!
But after reviewing again, it looks like the best fix is to make the commit log better reflect what is happening. All the changes are adding more tracing, so no need to split the commit. After all, it is not like this series is particularly short on commits... ;-)
Thanx, Paul
Re: [PATCH tip/core/rcu 18/86] rcu: add grace-period age to tracing
Quoted 12 lines · Paul E. McKenney
Quoted 11 lines · Paul E. McKenney
Quoted 9 lines · Josh Triplett
Quoted 5 lines · Paul E. McKenney
From: Paul E. McKenney <[email protected]>
This commit adds the age in jiffies of the current grace period along with the duration in jiffies of the longest grace period since boot to the rcu/rcugp debugfs file.
This change seems to have several other unrelated changes mixed in and not documented, related to adding and tracing
RCU_KTHREAD_OFFCPU.
Quoted 8 lines
Quoted 3 lines
Hmmm... I do have two commits worth of stuff in there, don't I?
Good catch, will fix!
But after reviewing again, it looks like the best fix is to make the commit log better reflect what is happening. All the changes are adding more tracing, so no need to split the commit. After all, it is not like this series is particularly short on commits... ;-)
And here it is with updated commit message.
Thanx, Paul
------------------------------------------------------------------------
rcu: add grace-period age and more kthread state to tracing
This commit adds the age in jiffies of the current grace period along with the duration in jiffies of the longest grace period since boot to the rcu/rcugp debugfs file. It also adds an additional "O" state to kthread tracing to differentiate between the kthread waiting due to having nothing to do on the one hand and waiting due to being on the wrong CPU on the other hand.
Documentation/RCU/trace.txt +10 -2
@@ -159,8 +159,8 @@ o "qs" gives an indication of the state of the callback queue the corresponding character is replaced by ".". o "kt" is the per-CPU kernel-thread state. The digit preceding - the slash is zero if there is no work pending and 1 otherwise. - The character after the slash is as follows: + the first slash is zero if there is no work pending and 1 + otherwise. The character between the slashes is as follows: "S" The kernel thread is stopped, in other words, all CPUs corresponding to this rcu_node structure are
@@ -171,10 +171,18 @@ o "kt" is the per-CPU kernel-thread state. The digit preceding "W" The kernel thread is waiting because there is no work for it to do. + "O" The kernel thread is waiting because it has been + forced off of its designated CPU or because its + ->cpus_allowed mask permits it to run on other than + its designated CPU. + "Y" The kernel thread is yielding to avoid hogging CPU. "?" Unknown value, indicates a bug. + The number after the final slash is the CPU that the kthread + is actually running on. + o "b" is the batch limit for this CPU. If more than this number of RCU callbacks is ready to invoke, then the remainder will be deferred.
kernel/rcutree.c +10 -0
@@ -92,6 +92,7 @@ EXPORT_SYMBOL_GPL(rcu_scheduler_active);*/ static DEFINE_PER_CPU(struct task_struct *, rcu_cpu_kthread_task);DEFINE_PER_CPU (unsigned int , rcu_cpu_kthread_status); +DEFINE_PER_CPU (int, rcu_cpu_kthread_cpu); static DEFINE_PER_CPU(wait_queue_head_t, rcu_cpu_wq);DEFINE_PER_CPU (char , rcu_cpu_has_work);static char rcu_kthreads_spawnable;
@@ -888,6 +889,8 @@ rcu_start_gp(struct rcu_state *rsp, unsigned long flags)static void rcu_report_qs_rsp (struct rcu_state *rsp,unsigned long flags) __releases(rcu_get_root(rsp)->lock) { +unsigned long gp_duration; +WARN_ON_ONCE (!rcu_gp_in_progress (rsp));/*
@@ -895,6 +898,9 @@ static void rcu_report_qs_rsp(struct rcu_state *rsp, unsigned long flags)* is seen before the assignment to rsp->completed. */ smp_mb ();/* See above block comment. */ + gp_duration = jiffies - rsp->gp_start; +if (gp_duration > rsp->gp_max) + rsp->gp_max = gp_duration; rsp->completed = rsp->gpnum; rsp->signaled =RCU_GP_IDLE ;rcu_start_gp (rsp, flags);/* releases root node's rnp->lock. */
@@ -1583,12 +1589,15 @@ static int rcu_cpu_kthread_should_stop(int cpu) smp_processor_id() != cpu) {if (kthread_should_stop ())return 1 ; +per_cpu (rcu_cpu_kthread_status, cpu) =RCU_KTHREAD_OFFCPU ; +per_cpu (rcu_cpu_kthread_cpu, cpu) =raw_smp_processor_id ();local_bh_enable ();schedule_timeout_uninterruptible (1 );if (!cpumask_equal (¤t->cpus_allowed,cpumask_of (cpu)))set_cpus_allowed_ptr (current,cpumask_of (cpu));local_bh_disable (); } +per_cpu (rcu_cpu_kthread_cpu, cpu) = cpu;return 0 ; }
@@ -1656,6 +1665,7 @@ static int __cpuinit rcu_spawn_one_cpu_kthread(int cpu)if (IS_ERR (t))return PTR_ERR (t);kthread_bind (t, cpu); +per_cpu (rcu_cpu_kthread_cpu, cpu) = cpu;WARN_ON_ONCE (per_cpu (rcu_cpu_kthread_task, cpu) !=NULL );per_cpu (rcu_cpu_kthread_task, cpu) = t;wake_up_process (t);
kernel/rcutree.h +5 -2
@@ -93,8 +93,9 @@ struct rcu_dynticks {#define RCU_KTHREAD_STOPPED 0#define RCU_KTHREAD_RUNNING 1#define RCU_KTHREAD_WAITING 2 -#define RCU_KTHREAD_YIELDING 3 -#define RCU_KTHREAD_MAX 3 +#define RCU_KTHREAD_OFFCPU 3 +#define RCU_KTHREAD_YIELDING 4 +#define RCU_KTHREAD_MAX 4/* * Definition for node within the RCU grace-period-detection hierarchy.
@@ -383,6 +384,8 @@ struct rcu_state {/* but in jiffies. */ unsigned long jiffies_stall;/* Time at which to check */ /* for CPU stalls. */ +unsigned long gp_max;/* Maximum GP duration in */ +/* jiffies. */ char *name;/* Name of structure. */ };
kernel/rcutree_trace.c +29 -8
@@ -47,13 +47,14 @@#include "rcutree.h" DECLARE_PER_CPU(unsigned int, rcu_cpu_kthread_status); +DECLARE_PER_CPU(unsigned int, rcu_cpu_kthread_cpu);DECLARE_PER_CPU (char, rcu_cpu_has_work);static char convert_kthread_status (unsigned int kthread_status) {if (kthread_status >RCU_KTHREAD_MAX )return '?' ; -return "SRWY" [kthread_status]; +return "SRWOY" [kthread_status]; }static void print_one_rcu_data (struct seq_file *m,struct rcu_data *rdp)
@@ -74,7 +75,7 @@ static void print_one_rcu_data(struct seq_file *m, struct rcu_data *rdp) rdp->dynticks_fqs);#endif /* #ifdef CONFIG_NO_HZ */ seq_printf (m," of=%lu ri=%lu" , rdp->offline_fqs, rdp->resched_ipi); - seq_printf(m, " ql=%ld qs=%c%c%c%c kt=%d/%c b=%ld", + seq_printf(m, " ql=%ld qs=%c%c%c%c kt=%d/%c/%d b=%ld", rdp->qlen, ".N"[rdp->nxttail[RCU_NEXT_READY_TAIL] != rdp->nxttail[RCU_NEXT_TAIL]],
@@ -86,6 +87,7 @@ static void print_one_rcu_data(struct seq_file *m, struct rcu_data *rdp)per_cpu (rcu_cpu_has_work, rdp->cpu),convert_kthread_status (per_cpu (rcu_cpu_kthread_status, rdp->cpu)), +per_cpu (rcu_cpu_kthread_cpu, rdp->cpu), rdp->blimit);seq_printf (m," ci=%lu co=%lu ca=%lu\n" , rdp->n_cbs_invoked, rdp->n_cbs_orphaned, rdp->n_cbs_adopted);
@@ -312,16 +314,35 @@ static const struct file_operations rcuhier_fops = { .release = single_release, }; +static void show_one_rcugp (struct seq_file *m,struct rcu_state *rsp) +{ +unsigned long flags; +unsigned long completed; +unsigned long gpnum; +unsigned long gpage; +unsigned long gpmax; +struct rcu_node *rnp = &rsp->node[0 ]; + +raw_spin_lock_irqsave (&rnp->lock, flags); + completed = rsp->completed; + gpnum = rsp->gpnum; +if (rsp->completed == rsp->gpnum) + gpage =0 ; +else + gpage = jiffies - rsp->gp_start; + gpmax = rsp->gp_max; +raw_spin_unlock_irqrestore (&rnp->lock, flags); +seq_printf (m,"%s: completed=%ld gpnum=%lu age=%ld max=%ld\n" , + rsp->name, completed, gpnum, gpage, gpmax); +} +static int show_rcugp (struct seq_file *m,void *unused) {#ifdef CONFIG_TREE_PREEMPT_RCU -seq_printf (m,"rcu_preempt: completed=%ld gpnum=%lu\n" , - rcu_preempt_state.completed, rcu_preempt_state.gpnum); +show_one_rcugp (m, &rcu_preempt_state);#endif /* #ifdef CONFIG_TREE_PREEMPT_RCU */ -seq_printf (m,"rcu_sched: completed=%ld gpnum=%lu\n" , - rcu_sched_state.completed, rcu_sched_state.gpnum); -seq_printf (m,"rcu_bh: completed=%ld gpnum=%lu\n" , - rcu_bh_state.completed, rcu_bh_state.gpnum); +show_one_rcugp (m, &rcu_sched_state); +show_one_rcugp (m, &rcu_bh_state);return 0 ; }
PATCH 19/86 rcu: Add forward-progress diagnostic for per-CPU kthreads
In reply to Paul E. McKenneyFrom: Paul E. McKenney <[email protected]>
Increment a per-CPU counter on each pass through rcu_cpu_kthread()'s service loop, and add it to the rcudata trace output.
--- Documentation/RCU/trace.txt | 39 ++++++++++++++++++++++----------------- kernel/rcutree.c | 2 ++ kernel/rcutree_trace.c | 4 +++- 3 files changed, 27 insertions(+), 18 deletions(-)
Documentation/RCU/trace.txt +22 -17
@@ -24,23 +24,23 @@ boosting statistics). The output of "cat rcu/rcudata" looks as follows: rcu_sched: - 0!c=423090 g=423091 pq=1 pqc=423090 qp=1 dt=86475/1/0 df=16319 of=163 ri=1519 ql=0 qs=.... kt=0/W b=10 ci=1460693 co=1648 ca=6448 - 1!c=423329 g=423330 pq=1 pqc=423329 qp=1 dt=90875/1/0 df=16231 of=157 ri=1249 ql=0 qs=.... kt=0/W b=10 ci=1459002 co=1614 ca=3310 - 2!c=423370 g=423371 pq=1 pqc=423370 qp=1 dt=69661/1/0 df=16125 of=163 ri=1469 ql=0 qs=.... kt=0/W b=10 ci=1610701 co=2015 ca=2378 - 3!c=422967 g=422968 pq=1 pqc=422967 qp=1 dt=70349/1/0 df=12528 of=163 ri=1450 ql=0 qs=.... kt=0/W b=10 ci=1427543 co=1430 ca=897 - 4!c=423196 g=423197 pq=1 pqc=423196 qp=0 dt=38935/1/0 df=10959 of=177 ri=1657 ql=0 qs=.... kt=0/W b=10 ci=1562249 co=1896 ca=533 - 5!c=422950 g=422951 pq=1 pqc=422950 qp=0 dt=25127/1/0 df=5895 of=167 ri=1549 ql=0 qs=.... kt=0/W b=10 ci=1777260 co=2137 ca=274 - 6!c=423396 g=423397 pq=1 pqc=423396 qp=1 dt=22639/1/0 df=4590 of=149 ri=1572 ql=0 qs=.... kt=0/W b=10 ci=1471186 co=1530 ca=243 - 7 c=460203 g=460203 pq=1 pqc=460202 qp=0 dt=937087/1/0 df=3298 of=149 ri=1584 ql=6 qs=N.W. kt=0/W b=10 ci=4026154 co=1948 ca=135 + 0 c=20972 g=20973 pq=1 pqc=20972 qp=0 dt=545/1/0 df=50 of=0 ri=0 ql=163 qs=NRW. kt=0/W/0 ktl=ebc3 b=10 ci=153737 co=0 ca=0 + 1 c=20972 g=20973 pq=1 pqc=20972 qp=0 dt=967/1/0 df=58 of=0 ri=0 ql=634 qs=NRW. kt=0/W/1 ktl=58c b=10 ci=191037 co=0 ca=0 + 2 c=20972 g=20973 pq=1 pqc=20972 qp=0 dt=1081/1/0 df=175 of=0 ri=0 ql=74 qs=N.W. kt=0/W/2 ktl=da94 b=10 ci=75991 co=0 ca=0 + 3 c=20942 g=20943 pq=1 pqc=20942 qp=1 dt=1846/0/0 df=404 of=0 ri=0 ql=0 qs=.... kt=0/W/3 ktl=d1cd b=10 ci=72261 co=0 ca=0 + 4 c=20972 g=20973 pq=1 pqc=20972 qp=0 dt=369/1/0 df=83 of=0 ri=0 ql=48 qs=N.W. kt=0/W/4 ktl=e0e7 b=10 ci=128365 co=0 ca=0 + 5 c=20972 g=20973 pq=1 pqc=20972 qp=0 dt=381/1/0 df=64 of=0 ri=0 ql=169 qs=NRW. kt=0/W/5 ktl=fb2f b=10 ci=164360 co=0 ca=0 + 6 c=20972 g=20973 pq=1 pqc=20972 qp=0 dt=1037/1/0 df=183 of=0 ri=0 ql=62 qs=N.W. kt=0/W/6 ktl=d2ad b=10 ci=65663 co=0 ca=0 + 7 c=20897 g=20897 pq=1 pqc=20896 qp=0 dt=1572/0/0 df=382 of=0 ri=0 ql=0 qs=.... kt=0/W/7 ktl=cf15 b=10 ci=75006 co=0 ca=0 rcu_bh: - 0!c=18446744073709551494 g=18446744073709551494 pq=0 pqc=18446744073709551493 qp=1 dt=86475/1/0 df=11 of=0 ri=0 ql=0 qs=.... kt=0/W b=10 ci=112 co=0 ca=0 - 1!c=18446744073709551496 g=18446744073709551496 pq=1 pqc=18446744073709551495 qp=0 dt=90875/1/0 df=15 of=0 ri=0 ql=0 qs=.... kt=0/W b=10 ci=143 co=0 ca=0 - 2!c=18446744073709551496 g=18446744073709551496 pq=1 pqc=18446744073709551495 qp=0 dt=69661/1/0 df=21 of=0 ri=1 ql=0 qs=.... kt=0/W b=10 ci=88 co=0 ca=0 - 3!c=18446744073709551494 g=18446744073709551494 pq=1 pqc=18446744073709551493 qp=0 dt=70349/1/0 df=13 of=0 ri=0 ql=0 qs=.... kt=0/W b=10 ci=100 co=0 ca=0 - 4!c=18446744073709551494 g=18446744073709551494 pq=0 pqc=18446744073709551493 qp=1 dt=38935/1/0 df=17 of=0 ri=0 ql=0 qs=.... kt=0/W b=10 ci=36 co=0 ca=0 - 5!c=18446744073709551494 g=18446744073709551494 pq=0 pqc=18446744073709551493 qp=1 dt=25127/1/0 df=7 of=0 ri=0 ql=0 qs=.... kt=0/W b=10 ci=32 co=0 ca=0 - 6!c=18446744073709551496 g=18446744073709551496 pq=1 pqc=18446744073709551495 qp=0 dt=22639/1/0 df=9 of=0 ri=0 ql=0 qs=.... kt=0/W b=10 ci=44 co=0 ca=0 - 7 c=182 g=182 pq=1 pqc=181 qp=0 dt=937087/1/0 df=14 of=0 ri=1 ql=0 qs=.... kt=0/W b=10 ci=627 co=0 ca=0 + 0 c=1480 g=1480 pq=1 pqc=1479 qp=0 dt=545/1/0 df=6 of=0 ri=1 ql=0 qs=.... kt=0/W/0 ktl=ebc3 b=10 ci=0 co=0 ca=0 + 1 c=1480 g=1480 pq=1 pqc=1479 qp=0 dt=967/1/0 df=3 of=0 ri=1 ql=0 qs=.... kt=0/W/1 ktl=58c b=10 ci=151 co=0 ca=0 + 2 c=1480 g=1480 pq=1 pqc=1479 qp=0 dt=1081/1/0 df=6 of=0 ri=1 ql=0 qs=.... kt=0/W/2 ktl=da94 b=10 ci=0 co=0 ca=0 + 3 c=1480 g=1480 pq=1 pqc=1479 qp=0 dt=1846/0/0 df=8 of=0 ri=1 ql=0 qs=.... kt=0/W/3 ktl=d1cd b=10 ci=0 co=0 ca=0 + 4 c=1480 g=1480 pq=1 pqc=1479 qp=0 dt=369/1/0 df=6 of=0 ri=1 ql=0 qs=.... kt=0/W/4 ktl=e0e7 b=10 ci=0 co=0 ca=0 + 5 c=1480 g=1480 pq=1 pqc=1479 qp=0 dt=381/1/0 df=4 of=0 ri=1 ql=0 qs=.... kt=0/W/5 ktl=fb2f b=10 ci=0 co=0 ca=0 + 6 c=1480 g=1480 pq=1 pqc=1479 qp=0 dt=1037/1/0 df=6 of=0 ri=1 ql=0 qs=.... kt=0/W/6 ktl=d2ad b=10 ci=0 co=0 ca=0 + 7 c=1474 g=1474 pq=1 pqc=1473 qp=0 dt=1572/0/0 df=8 of=0 ri=1 ql=0 qs=.... kt=0/W/7 ktl=cf15 b=10 ci=0 co=0 ca=0 The first section lists the rcu_data structures for rcu_sched, the second for rcu_bh. Note that CONFIG_TREE_PREEMPT_RCU kernels will have an
@@ -151,7 +151,8 @@ o "qs" gives an indication of the state of the callback queue o "kt" is the per-CPU kernel-thread state. The digit preceding the first slash is zero if there is no work pending and 1 - otherwise. The character between the slashes is as follows: + otherwise. The character between the first pair of slashes is + as follows: "S" The kernel thread is stopped, in other words, all CPUs corresponding to this rcu_node structure are
@@ -174,6 +175,10 @@ o "kt" is the per-CPU kernel-thread state. The digit preceding The number after the final slash is the CPU that the kthread is actually running on. +o "ktl" is the low-order 16 bits (in hexadecimal) of the count of + the number of times that this CPU's per-CPU kthread has gone + through its loop servicing invoke_rcu_cpu_kthread() requests. + o "b" is the batch limit for this CPU. If more than this number of RCU callbacks is ready to invoke, then the remainder will be deferred.
kernel/rcutree.c +2 -0
@@ -93,6 +93,7 @@ EXPORT_SYMBOL_GPL(rcu_scheduler_active); static DEFINE_PER_CPU(struct task_struct *, rcu_cpu_kthread_task);DEFINE_PER_CPU (unsigned int , rcu_cpu_kthread_status);DEFINE_PER_CPU (int, rcu_cpu_kthread_cpu); +DEFINE_PER_CPU(unsigned int, rcu_cpu_kthread_loops); static DEFINE_PER_CPU(wait_queue_head_t, rcu_cpu_wq);DEFINE_PER_CPU (char , rcu_cpu_has_work);static char rcu_kthreads_spawnable;
@@ -1625,6 +1626,7 @@ static int rcu_cpu_kthread(void *arg)break ; } *statusp =RCU_KTHREAD_RUNNING ; +per_cpu (rcu_cpu_kthread_loops, cpu)++;local_irq_save (flags); work = *workp; *workp =0 ;
kernel/rcutree_trace.c +3 -1
@@ -48,6 +48,7 @@ DECLARE_PER_CPU(unsigned int, rcu_cpu_kthread_status); DECLARE_PER_CPU(unsigned int, rcu_cpu_kthread_cpu); +DECLARE_PER_CPU(unsigned int, rcu_cpu_kthread_loops);DECLARE_PER_CPU (char, rcu_cpu_has_work);static char convert_kthread_status (unsigned int kthread_status)
@@ -75,7 +76,7 @@ static void print_one_rcu_data(struct seq_file *m, struct rcu_data *rdp) rdp->dynticks_fqs);#endif /* #ifdef CONFIG_NO_HZ */ seq_printf (m," of=%lu ri=%lu" , rdp->offline_fqs, rdp->resched_ipi); - seq_printf(m, " ql=%ld qs=%c%c%c%c kt=%d/%c/%d b=%ld", + seq_printf(m, " ql=%ld qs=%c%c%c%c kt=%d/%c/%d ktl=%x b=%ld", rdp->qlen, ".N"[rdp->nxttail[RCU_NEXT_READY_TAIL] != rdp->nxttail[RCU_NEXT_TAIL]],
@@ -88,6 +89,7 @@ static void print_one_rcu_data(struct seq_file *m, struct rcu_data *rdp)convert_kthread_status (per_cpu (rcu_cpu_kthread_status, rdp->cpu)),per_cpu (rcu_cpu_kthread_cpu, rdp->cpu), +per_cpu (rcu_cpu_kthread_loops, rdp->cpu) &0xffff , rdp->blimit);seq_printf (m," ci=%lu co=%lu ca=%lu\n" , rdp->n_cbs_invoked, rdp->n_cbs_orphaned, rdp->n_cbs_adopted);
Signature · 1 line
1.7.3.2
PATCH 20/86 rcu: Enable DEBUG_OBJECTS_RCU_HEAD from !PREEMPT
In reply to Paul E. McKenneyFrom: Mathieu Desnoyers <[email protected]>
The prohibition of DEBUG_OBJECTS_RCU_HEAD from !PREEMPT was due to the fixup actions. So just produce a warning from !PREEMPT.
--- kernel/rcupdate.c | 26 +++++++++++++++++++++----- lib/Kconfig.debug | 2 +- 2 files changed, 22 insertions(+), 6 deletions(-)
kernel/rcupdate.c +21 -5
@@ -142,7 +142,14 @@ static int rcuhead_fixup_init(void *addr, enum debug_obj_state state)* Ensure that queued callbacks are all executed. * If we detect that we are nested in a RCU read-side critical * section, we should simply fail, otherwise we would deadlock. +* In !PREEMPT configurations, there is no way to tell if we are +* in a RCU read-side critical section or not, so we never +* attempt any fixup and just print a warning. */ +#ifndef CONFIG_PREEMPT +WARN_ON (1 ); +return 0 ; +#endif if (rcu_preempt_depth () !=0 ||preempt_count () !=0 ||irqs_disabled ()) {WARN_ON (1 );
@@ -184,7 +191,14 @@ static int rcuhead_fixup_activate(void *addr, enum debug_obj_state state)* Ensure that queued callbacks are all executed. * If we detect that we are nested in a RCU read-side critical * section, we should simply fail, otherwise we would deadlock. +* In !PREEMPT configurations, there is no way to tell if we are +* in a RCU read-side critical section or not, so we never +* attempt any fixup and just print a warning. */ +#ifndef CONFIG_PREEMPT +WARN_ON (1 ); +return 0 ; +#endif if (rcu_preempt_depth () !=0 ||preempt_count () !=0 ||irqs_disabled ()) {WARN_ON (1 );
@@ -214,12 +228,14 @@ static int rcuhead_fixup_free(void *addr, enum debug_obj_state state)* Ensure that queued callbacks are all executed. * If we detect that we are nested in a RCU read-side critical * section, we should simply fail, otherwise we would deadlock. -* Note that the machinery to reliably determine whether -* or not we are in an RCU read-side critical section -* exists only in the preemptible RCU implementations -* (TINY_PREEMPT_RCU and TREE_PREEMPT_RCU), which is why -* DEBUG_OBJECTS_RCU_HEAD is disallowed if !PREEMPT. +* In !PREEMPT configurations, there is no way to tell if we are +* in a RCU read-side critical section or not, so we never +* attempt any fixup and just print a warning. */ +#ifndef CONFIG_PREEMPT +WARN_ON (1 ); +return 0 ; +#endif if (rcu_preempt_depth () !=0 ||preempt_count () !=0 ||irqs_disabled ()) {WARN_ON (1 );
lib/Kconfig.debug +1 -1
@@ -337,7 +337,7 @@ config DEBUG_OBJECTS_WORK config DEBUG_OBJECTS_RCU_HEAD bool "Debug RCU callbacks objects" - depends on DEBUG_OBJECTS && PREEMPT + depends on DEBUG_OBJECTS help Enable this to turn on debugging of RCU list heads (call_rcu() usage).
Signature · 1 line
1.7.3.2
PATCH 21/86 rcu: add DEBUG_OBJECTS_RCU_HEAD check for alignment
In reply to Paul E. McKenneyVerify that rcu_head structures are aligned to a four-byte boundary. This check is enabled by CONFIG_DEBUG_OBJECTS_RCU_HEAD.
--- include/linux/rcupdate.h | 1 + 1 files changed, 1 insertions(+), 0 deletions(-)
include/linux/rcupdate.h +1 -0
@@ -785,6 +785,7 @@ extern struct debug_obj_descr rcuhead_debug_descr;static inline void debug_rcu_head_queue (struct rcu_head *head) { +WARN_ON_ONCE ((unsigned long )head &0x3 );debug_object_activate (head, &rcuhead_debug_descr); debug_object_active_state(head, &rcuhead_debug_descr, STATE_RCU_HEAD_READY,
Signature · 1 line
1.7.3.2
PATCH 22/86 rcu: mark rcutorture boosting callback as being on-stack
In reply to Paul E. McKenneyFrom: Paul E. McKenney <[email protected]>
The CONFIG_DEBUG_OBJECTS_RCU_HEAD facility requires that on-stack RCU callbacks be flagged explicitly to debug-objects using the init_rcu_head_on_stack() and destroy_rcu_head_on_stack() functions. This commit applies those functions to the rcutorture code that tests RCU priority boosting.
--- kernel/rcutorture.c | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-)
kernel/rcutorture.c +2 -0
@@ -751,6 +751,7 @@ static int rcu_torture_boost(void *arg) n_rcu_torture_boost_rterror++; } +init_rcu_head_on_stack (&rbi.rcu);/* Each pass through the following loop does one boost-test cycle. */ do { /* Wait for the next test interval. */
@@ -810,6 +811,7 @@ checkwait: rcu_stutter_wait("rcu_torture_boost");/* Clean up and exit. */ VERBOSE_PRINTK_STRING ("rcu_torture_boost task stopping" ); +destroy_rcu_head_on_stack (&rbi.rcu);rcutorture_shutdown_absorb ("rcu_torture_boost" );while (!kthread_should_stop () || rbi.inflight)schedule_timeout_uninterruptible (1 );
Signature · 1 line
1.7.3.2
PATCH 23/86 rcu: Use WARN_ON_ONCE for DEBUG_OBJECTS_RCU_HEAD warnings
In reply to Paul E. McKenneyAvoid additional multiple-warning confusion in memory-corruption scenarios.
--- kernel/rcupdate.c | 12 ++++++------ 1 files changed, 6 insertions(+), 6 deletions(-)
kernel/rcupdate.c +6 -6
@@ -147,12 +147,12 @@ static int rcuhead_fixup_init(void *addr, enum debug_obj_state state)* attempt any fixup and just print a warning. */ #ifndef CONFIG_PREEMPT -WARN_ON (1 ); +WARN_ON_ONCE (1 );return 0 ;#endif if (rcu_preempt_depth () !=0 ||preempt_count () !=0 ||irqs_disabled ()) { -WARN_ON (1 ); +WARN_ON_ONCE (1 );return 0 ; }rcu_barrier ();
@@ -196,12 +196,12 @@ static int rcuhead_fixup_activate(void *addr, enum debug_obj_state state)* attempt any fixup and just print a warning. */ #ifndef CONFIG_PREEMPT -WARN_ON (1 ); +WARN_ON_ONCE (1 );return 0 ;#endif if (rcu_preempt_depth () !=0 ||preempt_count () !=0 ||irqs_disabled ()) { -WARN_ON (1 ); +WARN_ON_ONCE (1 );return 0 ; }rcu_barrier ();
@@ -233,12 +233,12 @@ static int rcuhead_fixup_free(void *addr, enum debug_obj_state state)* attempt any fixup and just print a warning. */ #ifndef CONFIG_PREEMPT -WARN_ON (1 ); +WARN_ON_ONCE (1 );return 0 ;#endif if (rcu_preempt_depth () !=0 ||preempt_count () !=0 ||irqs_disabled ()) { -WARN_ON (1 ); +WARN_ON_ONCE (1 );return 0 ; }rcu_barrier ();
Signature · 1 line
1.7.3.2
PATCH 24/86 rcu: Switch to this_cpu() primitives
In reply to Paul E. McKenneyFrom: Paul E. McKenney <[email protected]>
This removes a couple of lines from invoke_rcu_cpu_kthread(), improving readability.
--- kernel/rcutree.c | 10 +++------- 1 files changed, 3 insertions(+), 7 deletions(-)
kernel/rcutree.c +3 -7
@@ -1480,18 +1480,14 @@ static void rcu_process_callbacks(void)static void invoke_rcu_cpu_kthread (void ) {unsigned long flags; -wait_queue_head_t *q; -int cpu;local_irq_save (flags); - cpu =smp_processor_id (); -per_cpu (rcu_cpu_has_work, cpu) =1 ; -if (per_cpu (rcu_cpu_kthread_task, cpu) ==NULL ) { +__this_cpu_write (rcu_cpu_has_work,1 ); +if (__this_cpu_read (rcu_cpu_kthread_task) ==NULL ) {local_irq_restore (flags);return ; } - q = &per_cpu (rcu_cpu_wq, cpu); -wake_up (q); +wake_up (&__get_cpu_var (rcu_cpu_wq));local_irq_restore (flags); }
Signature · 1 line
1.7.3.2
PATCH 25/86 rcu: code cleanups in TINY_RCU priority boosting.
In reply to Paul E. McKenneyFrom: Paul E. McKenney <[email protected]>
Extraneous semicolon, bad comment, and fold INIT_LIST_HEAD() into list_del() to get list_del_init().
--- kernel/rcutiny_plugin.h | 7 +++---- 1 files changed, 3 insertions(+), 4 deletions(-)
kernel/rcutiny_plugin.h +3 -4
@@ -339,7 +339,7 @@ static void rcu_initiate_expedited_boost(void)raw_local_irq_restore (flags); } -#define RCU_BOOST_DELAY_JIFFIES DIV_ROUND_UP(CONFIG_RCU_BOOST_DELAY * HZ, 1000); +#define RCU_BOOST_DELAY_JIFFIES DIV_ROUND_UP(CONFIG_RCU_BOOST_DELAY * HZ, 1000)/* * Do priority-boost accounting for the start of a new grace period.
@@ -418,7 +418,7 @@ static void rcu_preempt_cpu_qs(void)if (!rcu_preempt_gp_in_progress ())return ;/* -* Check up on boosting. If there are no readers blocking the +* Check up on boosting. If there are readers blocking the * current grace period, leave. */ if (rcu_initiate_boost ())
@@ -578,7 +578,7 @@ static void rcu_read_unlock_special(struct task_struct *t) empty = !rcu_preempt_blocked_readers_cgp (); empty_exp = rcu_preempt_ctrlblk.exp_tasks ==NULL ; np =rcu_next_node_entry (t); -list_del (&t->rcu_node_entry); +list_del_init (&t->rcu_node_entry);if (&t->rcu_node_entry == rcu_preempt_ctrlblk.gp_tasks) rcu_preempt_ctrlblk.gp_tasks = np;if (&t->rcu_node_entry == rcu_preempt_ctrlblk.exp_tasks)
@@ -587,7 +587,6 @@ static void rcu_read_unlock_special(struct task_struct *t)if (&t->rcu_node_entry == rcu_preempt_ctrlblk.boost_tasks) rcu_preempt_ctrlblk.boost_tasks = np;#endif /* #ifdef CONFIG_RCU_BOOST */ -INIT_LIST_HEAD (&t->rcu_node_entry);/* * If this was the last task on the current list, and if
Signature · 1 line
1.7.3.2
PATCH 26/86 rcu: remove useless ->boosted_this_gp field
In reply to Paul E. McKenneyFrom: Paul E. McKenney <[email protected]>
The ->boosted_this_gp field is a holdover from an earlier design that was to carry out multiple boost operations in parallel. It is not required by the current design, which boosts one task at a time.
--- kernel/rcutiny_plugin.h | 35 ++++------------------------------- 1 files changed, 4 insertions(+), 31 deletions(-)
kernel/rcutiny_plugin.h +4 -31
@@ -100,7 +100,6 @@ struct rcu_preempt_ctrlblk {u8 completed;/* Last grace period completed. */ /* If all three are equal, RCU is idle. */ #ifdef CONFIG_RCU_BOOST -s8 boosted_this_gp;/* Has boosting already happened? */ unsigned long boost_time;/* When to start boosting (jiffies) */ #endif /* #ifdef CONFIG_RCU_BOOST */ #ifdef CONFIG_RCU_TRACE
@@ -112,7 +111,6 @@ struct rcu_preempt_ctrlblk {unsigned long n_normal_balk_blkd_tasks;unsigned long n_normal_balk_gp_tasks;unsigned long n_normal_balk_boost_tasks; -unsigned long n_normal_balk_boosted;unsigned long n_normal_balk_notyet;unsigned long n_normal_balk_nos;unsigned long n_exp_balk_blkd_tasks;
@@ -219,36 +217,19 @@ static void show_tiny_preempt_stats(struct seq_file *m)"N." [!rcu_preempt_ctrlblk.gp_tasks], "E."[!rcu_preempt_ctrlblk.exp_tasks]);#ifdef CONFIG_RCU_BOOST -seq_printf (m," ttb=%c btg=" , -"B." [!rcu_preempt_ctrlblk.boost_tasks]); -switch (rcu_preempt_ctrlblk.boosted_this_gp) { -case -1 : -seq_puts (m,"exp" ); -break ; -case 0 : -seq_puts (m,"no" ); -break ; -case 1 : -seq_puts (m,"begun" ); -break ; -case 2 : -seq_puts (m,"done" ); -break ; -default : -seq_printf (m,"?%d?" , rcu_preempt_ctrlblk.boosted_this_gp); - } -seq_printf (m," ntb=%lu neb=%lu nnb=%lu j=%04x bt=%04x\n" , +seq_printf (m,"%sttb=%c ntb=%lu neb=%lu nnb=%lu j=%04x bt=%04x\n" , +" " , +"B." [!rcu_preempt_ctrlblk.boost_tasks], rcu_preempt_ctrlblk.n_tasks_boosted, rcu_preempt_ctrlblk.n_exp_boosts, rcu_preempt_ctrlblk.n_normal_boosts, (int )(jiffies &0xffff ), (int )(rcu_preempt_ctrlblk.boost_time &0xffff )); -seq_printf (m," %s: nt=%lu gt=%lu bt=%lu b=%lu ny=%lu nos=%lu\n" , +seq_printf (m," %s: nt=%lu gt=%lu bt=%lu ny=%lu nos=%lu\n" ,"normal balk" , rcu_preempt_ctrlblk.n_normal_balk_blkd_tasks, rcu_preempt_ctrlblk.n_normal_balk_gp_tasks, rcu_preempt_ctrlblk.n_normal_balk_boost_tasks, - rcu_preempt_ctrlblk.n_normal_balk_boosted, rcu_preempt_ctrlblk.n_normal_balk_notyet, rcu_preempt_ctrlblk.n_normal_balk_nos); seq_printf(m, " exp balk: bt=%lu nos=%lu\n",
@@ -277,7 +258,6 @@ static int rcu_boost(void)if (rcu_preempt_ctrlblk.boost_tasks ==NULL )return 0 ;/* Nothing to boost. */ raw_local_irq_save (flags); - rcu_preempt_ctrlblk.boosted_this_gp++; t = container_of(rcu_preempt_ctrlblk.boost_tasks, struct task_struct, rcu_node_entry); np =rcu_next_node_entry (t);
@@ -287,7 +267,6 @@ static int rcu_boost(void)raw_local_irq_restore (flags);rt_mutex_lock (&mtx);RCU_TRACE (rcu_preempt_ctrlblk.n_tasks_boosted++); - rcu_preempt_ctrlblk.boosted_this_gp++;rt_mutex_unlock (&mtx);return rcu_preempt_ctrlblk.boost_tasks !=NULL ; }
@@ -310,7 +289,6 @@ static int rcu_initiate_boost(void) }if (rcu_preempt_ctrlblk.gp_tasks !=NULL && rcu_preempt_ctrlblk.boost_tasks ==NULL && - rcu_preempt_ctrlblk.boosted_this_gp ==0 &&ULONG_CMP_GE (jiffies, rcu_preempt_ctrlblk.boost_time)) { rcu_preempt_ctrlblk.boost_tasks = rcu_preempt_ctrlblk.gp_tasks;invoke_rcu_kthread ();
@@ -331,7 +309,6 @@ static void rcu_initiate_expedited_boost(void)if (!list_empty (&rcu_preempt_ctrlblk.blkd_tasks)) { rcu_preempt_ctrlblk.boost_tasks = rcu_preempt_ctrlblk.blkd_tasks.next; - rcu_preempt_ctrlblk.boosted_this_gp =-1 ;invoke_rcu_kthread ();RCU_TRACE (rcu_preempt_ctrlblk.n_exp_boosts++); }else
@@ -347,8 +324,6 @@ static void rcu_initiate_expedited_boost(void)static void rcu_preempt_boost_start_gp (void ) { rcu_preempt_ctrlblk.boost_time = jiffies +RCU_BOOST_DELAY_JIFFIES ; -if (rcu_preempt_ctrlblk.boosted_this_gp >0 ) - rcu_preempt_ctrlblk.boosted_this_gp =0 ; }#else /* #ifdef CONFIG_RCU_BOOST */
@@ -934,8 +909,6 @@ static void rcu_initiate_boost_trace(void) rcu_preempt_ctrlblk.n_normal_balk_gp_tasks++; else if (rcu_preempt_ctrlblk.boost_tasks != NULL) rcu_preempt_ctrlblk.n_normal_balk_boost_tasks++; - else if (rcu_preempt_ctrlblk.boosted_this_gp != 0) - rcu_preempt_ctrlblk.n_normal_balk_boosted++; else if (!ULONG_CMP_GE(jiffies, rcu_preempt_ctrlblk.boost_time)) rcu_preempt_ctrlblk.n_normal_balk_notyet++; else
Signature · 1 line
1.7.3.2
Josh Triplett
maintainerRe: [PATCH tip/core/rcu 26/86] rcu: remove useless ->boosted_this_gp field
Quoted 8 lines · Paul E. McKenney
From: Paul E. McKenney <[email protected]>
The ->boosted_this_gp field is a holdover from an earlier design that was to carry out multiple boost operations in parallel. It is not required by the current design, which boosts one task at a time.
Signed-off-by Paul E. McKenney <[email protected]>Signed-off-by Paul E. McKenney <[email protected]>
Can you squash this patch into the commit that introduces boosted_this_gp in the first place?
- Josh Triplett
Re: [PATCH tip/core/rcu 26/86] rcu: remove useless ->boosted_this_gp field
Quoted 7 lines · Josh Triplett
Quoted 6 lines · Paul E. McKenney
From: Paul E. McKenney <[email protected]>
The ->boosted_this_gp field is a holdover from an earlier design that was to carry out multiple boost operations in parallel. It is not required by the current design, which boosts one task at a time.
Quoted 5 lines
Quoted 2 lines
Signed-off-by Paul E. McKenney <[email protected]>Signed-off-by Paul E. McKenney <[email protected]>Can you squash this patch into the commit that introduces
boosted_this_gpin the first place?
Unfortunately, no. That commit is already in mainline.
Thanx, Paul
PATCH 27/86 rcu: Converge TINY_RCU expedited and normal boosting
In reply to Paul E. McKenneyFrom: Paul E. McKenney <[email protected]>
This applies a trick from TREE_RCU boosting to TINY_RCU, eliminating code and adding comments. The key point is that it is possible for the booster thread itself to work out whether there is a normal or expedited boost required based solely on local information. There is therefore no need for boost initiation to know or care what type of boosting is required. In addition, when boosting is complete for a given grace period, then by definition there cannot be any more boosting for that grace period. This allows eliminating yet more state and statistics.
--- kernel/rcutiny_plugin.h | 163 +++++++++++++++++++++++++--------------------- 1 files changed, 89 insertions(+), 74 deletions(-)
kernel/rcutiny_plugin.h +89 -74
@@ -106,15 +106,22 @@ struct rcu_preempt_ctrlblk {unsigned long n_grace_periods;#ifdef CONFIG_RCU_BOOST unsigned long n_tasks_boosted; +/* Total number of tasks boosted. */ unsigned long n_exp_boosts; +/* Number of tasks boosted for expedited GP. */ unsigned long n_normal_boosts; -unsigned long n_normal_balk_blkd_tasks; -unsigned long n_normal_balk_gp_tasks; -unsigned long n_normal_balk_boost_tasks; -unsigned long n_normal_balk_notyet; -unsigned long n_normal_balk_nos; -unsigned long n_exp_balk_blkd_tasks; -unsigned long n_exp_balk_nos; +/* Number of tasks boosted for normal GP. */ +unsigned long n_balk_blkd_tasks; +/* Refused to boost: no blocked tasks. */ +unsigned long n_balk_exp_gp_tasks; +/* Refused to boost: nothing blocking GP. */ +unsigned long n_balk_boost_tasks; +/* Refused to boost: already boosting. */ +unsigned long n_balk_notyet; +/* Refused to boost: not yet time. */ +unsigned long n_balk_nos; +/* Refused to boost: not sure why, though. */ +/* This can happen due to race conditions. */ #endif /* #ifdef CONFIG_RCU_BOOST */ #endif /* #ifdef CONFIG_RCU_TRACE */ };
@@ -199,7 +206,6 @@ static struct list_head *rcu_next_node_entry(struct task_struct *t)#ifdef CONFIG_RCU_BOOST static void rcu_initiate_boost_trace (void ); -static void rcu_initiate_exp_boost_trace (void );#endif /* #ifdef CONFIG_RCU_BOOST */ /*
@@ -225,16 +231,13 @@ static void show_tiny_preempt_stats(struct seq_file *m) rcu_preempt_ctrlblk.n_normal_boosts, (int )(jiffies &0xffff ), (int)(rcu_preempt_ctrlblk.boost_time & 0xffff)); -seq_printf (m," %s: nt=%lu gt=%lu bt=%lu ny=%lu nos=%lu\n" , -"normal balk" , - rcu_preempt_ctrlblk.n_normal_balk_blkd_tasks, - rcu_preempt_ctrlblk.n_normal_balk_gp_tasks, - rcu_preempt_ctrlblk.n_normal_balk_boost_tasks, - rcu_preempt_ctrlblk.n_normal_balk_notyet, - rcu_preempt_ctrlblk.n_normal_balk_nos); -seq_printf (m," exp balk: bt=%lu nos=%lu\n" , - rcu_preempt_ctrlblk.n_exp_balk_blkd_tasks, - rcu_preempt_ctrlblk.n_exp_balk_nos); +seq_printf (m,"%s: nt=%lu egt=%lu bt=%lu ny=%lu nos=%lu\n" , +" balk" , + rcu_preempt_ctrlblk.n_balk_blkd_tasks, + rcu_preempt_ctrlblk.n_balk_exp_gp_tasks, + rcu_preempt_ctrlblk.n_balk_boost_tasks, + rcu_preempt_ctrlblk.n_balk_notyet, + rcu_preempt_ctrlblk.n_balk_nos);#endif /* #ifdef CONFIG_RCU_BOOST */ }
@@ -252,23 +255,59 @@ static int rcu_boost(void) {unsigned long flags;struct rt_mutex mtx; -struct list_head *np;struct task_struct *t; +struct list_head *tb; -if (rcu_preempt_ctrlblk.boost_tasks ==NULL ) +if (rcu_preempt_ctrlblk.boost_tasks ==NULL && + rcu_preempt_ctrlblk.exp_tasks ==NULL )return 0 ;/* Nothing to boost. */ +raw_local_irq_save (flags); - t = container_of(rcu_preempt_ctrlblk.boost_tasks, struct task_struct, - rcu_node_entry); - np =rcu_next_node_entry (t); + +/* +* Recheck with irqs disabled: all tasks in need of boosting +* might exit their RCU read-side critical sections on their own +* if we are preempted just before disabling irqs. +*/ +if (rcu_preempt_ctrlblk.boost_tasks ==NULL && + rcu_preempt_ctrlblk.exp_tasks ==NULL ) { +raw_local_irq_restore (flags); +return 0 ; + } + +/* +* Preferentially boost tasks blocking expedited grace periods. +* This cannot starve the normal grace periods because a second +* expedited grace period must boost all blocked tasks, including +* those blocking the pre-existing normal grace period. +*/ +if (rcu_preempt_ctrlblk.exp_tasks !=NULL ) { + tb = rcu_preempt_ctrlblk.exp_tasks; +RCU_TRACE (rcu_preempt_ctrlblk.n_exp_boosts++); + }else { + tb = rcu_preempt_ctrlblk.boost_tasks; +RCU_TRACE (rcu_preempt_ctrlblk.n_normal_boosts++); + } +RCU_TRACE (rcu_preempt_ctrlblk.n_tasks_boosted++); + +/* +* We boost task t by manufacturing an rt_mutex that appears to +* be held by task t. We leave a pointer to that rt_mutex where +* task t can find it, and task t will release the mutex when it +* exits its outermost RCU read-side critical section. Then +* simply acquiring this artificial rt_mutex will boost task +* t's priority. (Thanks to tglx for suggesting this approach!) +*/ + t = container_of(tb, struct task_struct, rcu_node_entry);rt_mutex_init_proxy_locked (&mtx, t); t->rcu_boost_mutex = &mtx; t->rcu_read_unlock_special |=RCU_READ_UNLOCK_BOOSTED ;raw_local_irq_restore (flags);rt_mutex_lock (&mtx); -RCU_TRACE (rcu_preempt_ctrlblk.n_tasks_boosted++); -rt_mutex_unlock (&mtx); -return rcu_preempt_ctrlblk.boost_tasks !=NULL ; +rt_mutex_unlock (&mtx);/* Keep lockdep happy. */ + +return rcu_preempt_ctrlblk.boost_tasks !=NULL || + rcu_preempt_ctrlblk.exp_tasks !=NULL ; }/*
@@ -283,39 +322,24 @@ static int rcu_boost(void)*/ static int rcu_initiate_boost (void ) { -if (!rcu_preempt_blocked_readers_cgp ()) { -RCU_TRACE (rcu_preempt_ctrlblk.n_normal_balk_blkd_tasks++); +if (!rcu_preempt_blocked_readers_cgp () && + rcu_preempt_ctrlblk.exp_tasks ==NULL ) { +RCU_TRACE (rcu_preempt_ctrlblk.n_balk_exp_gp_tasks++);return 0 ; } -if (rcu_preempt_ctrlblk.gp_tasks !=NULL && - rcu_preempt_ctrlblk.boost_tasks ==NULL && -ULONG_CMP_GE (jiffies, rcu_preempt_ctrlblk.boost_time)) { - rcu_preempt_ctrlblk.boost_tasks = rcu_preempt_ctrlblk.gp_tasks; +if (rcu_preempt_ctrlblk.exp_tasks !=NULL || + (rcu_preempt_ctrlblk.gp_tasks !=NULL && + rcu_preempt_ctrlblk.boost_tasks ==NULL && +ULONG_CMP_GE (jiffies, rcu_preempt_ctrlblk.boost_time))) { +if (rcu_preempt_ctrlblk.exp_tasks ==NULL ) + rcu_preempt_ctrlblk.boost_tasks = + rcu_preempt_ctrlblk.gp_tasks;invoke_rcu_kthread (); -RCU_TRACE (rcu_preempt_ctrlblk.n_normal_boosts++); }else RCU_TRACE (rcu_initiate_boost_trace ());return 1 ; } -/* -* Initiate boosting for an expedited grace period. -*/ -static void rcu_initiate_expedited_boost (void ) -{ -unsigned long flags; - -raw_local_irq_save (flags); -if (!list_empty (&rcu_preempt_ctrlblk.blkd_tasks)) { - rcu_preempt_ctrlblk.boost_tasks = - rcu_preempt_ctrlblk.blkd_tasks.next; -invoke_rcu_kthread (); -RCU_TRACE (rcu_preempt_ctrlblk.n_exp_boosts++); - }else -RCU_TRACE (rcu_initiate_exp_boost_trace ()); -raw_local_irq_restore (flags); -} -#define RCU_BOOST_DELAY_JIFFIES DIV_ROUND_UP(CONFIG_RCU_BOOST_DELAY * HZ, 1000)/*
@@ -347,13 +371,6 @@ static int rcu_initiate_boost(void) }/* -* If there is no RCU priority boosting, we don't initiate expedited boosting. -*/ -static void rcu_initiate_expedited_boost (void ) -{ -} - -/* * If there is no RCU priority boosting, nothing to do at grace-period start. */ static void rcu_preempt_boost_start_gp (void )
@@ -786,13 +803,16 @@ void synchronize_rcu_expedited(void) rpcp->exp_tasks = rpcp->blkd_tasks.next;if (rpcp->exp_tasks == &rpcp->blkd_tasks) rpcp->exp_tasks =NULL ; -local_irq_restore (flags);/* Wait for tail of ->blkd_tasks list to drain. */ -if (rcu_preempted_readers_exp ()) -rcu_initiate_expedited_boost (); +if (!rcu_preempted_readers_exp ()) +local_irq_restore (flags); +else { +rcu_initiate_boost (); +local_irq_restore (flags);wait_event (sync_rcu_preempt_exp_wq, !rcu_preempted_readers_exp ()); + }/* Clean up and exit. */ barrier ();/* ensure expedited GP seen before counter increment. */
@@ -905,22 +925,17 @@ void __init rcu_scheduler_starting(void)static void rcu_initiate_boost_trace (void ) { -if (rcu_preempt_ctrlblk.gp_tasks ==NULL ) - rcu_preempt_ctrlblk.n_normal_balk_gp_tasks++; +if (list_empty (&rcu_preempt_ctrlblk.blkd_tasks)) + rcu_preempt_ctrlblk.n_balk_blkd_tasks++; +else if (rcu_preempt_ctrlblk.gp_tasks ==NULL && + rcu_preempt_ctrlblk.exp_tasks ==NULL ) + rcu_preempt_ctrlblk.n_balk_exp_gp_tasks++;else if (rcu_preempt_ctrlblk.boost_tasks !=NULL ) - rcu_preempt_ctrlblk.n_normal_balk_boost_tasks++; + rcu_preempt_ctrlblk.n_balk_boost_tasks++;else if (!ULONG_CMP_GE (jiffies, rcu_preempt_ctrlblk.boost_time)) - rcu_preempt_ctrlblk.n_normal_balk_notyet++; -else - rcu_preempt_ctrlblk.n_normal_balk_nos++; -} - -static void rcu_initiate_exp_boost_trace (void ) -{ -if (list_empty (&rcu_preempt_ctrlblk.blkd_tasks)) - rcu_preempt_ctrlblk.n_exp_balk_blkd_tasks++; + rcu_preempt_ctrlblk.n_balk_notyet++;else - rcu_preempt_ctrlblk.n_exp_balk_nos++; + rcu_preempt_ctrlblk.n_balk_nos++; }#endif /* #ifdef CONFIG_RCU_BOOST */
Signature · 1 line
1.7.3.2
PATCH 28/86 rcu: call __rcu_read_unlock() in exit_rcu for tree RCU
In reply to Paul E. McKenneyFrom: Lai Jiangshan <[email protected]>
Using __rcu_read_lock() in place of rcu_read_lock() leaves any debug state as it really should be, namely with the lock still held.
--- kernel/rcutree_plugin.h | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
kernel/rcutree_plugin.h +1 -1
@@ -858,7 +858,7 @@ void exit_rcu(void)if (t->rcu_read_lock_nesting ==0 )return ; t->rcu_read_lock_nesting =1 ; - rcu_read_unlock(); + __rcu_read_unlock(); }#else /* #ifdef CONFIG_TREE_PREEMPT_RCU */
Signature · 1 line
1.7.3.2
PATCH 29/86 rcu: fix spelling
In reply to Paul E. McKenneyThe "preemptible" spelling is preferable. May as well fix it.
--- kernel/rcutree.c | 10 ++++---- kernel/rcutree.h | 2 +- kernel/rcutree_plugin.h | 62 +++++++++++++++++++++++----------------------- 3 files changed, 37 insertions(+), 37 deletions(-)
kernel/rcutree.c +5 -5
@@ -290,8 +290,8 @@ static int rcu_implicit_offline_qs(struct rcu_data *rdp)return 1 ; } -/* If preemptable RCU, no point in sending reschedule IPI. */ -if (rdp->preemptable) +/* If preemptible RCU, no point in sending reschedule IPI. */ +if (rdp->preemptible)return 0 ;/* The CPU is online, so send it a reschedule IPI. */
@@ -1982,7 +1982,7 @@ static int __rcu_pending(struct rcu_state *rsp, struct rcu_data *rdp)* or RCU-bh, force a local reschedule. */ rdp->n_rp_qs_pending++; -if (!rdp->preemptable && +if (!rdp->preemptible &&ULONG_CMP_LT (ACCESS_ONCE (rsp->jiffies_force_qs) -1 , jiffies))set_need_resched ();
@@ -2159,7 +2159,7 @@ rcu_boot_init_percpu_data(int cpu, struct rcu_state *rsp)* that this CPU cannot possibly have any RCU callbacks in flight yet. */ static void __cpuinit -rcu_init_percpu_data (int cpu,struct rcu_state *rsp,int preemptable) +rcu_init_percpu_data (int cpu,struct rcu_state *rsp,int preemptible) {unsigned long flags;unsigned long mask;
@@ -2171,7 +2171,7 @@ rcu_init_percpu_data(int cpu, struct rcu_state *rsp, int preemptable) rdp->passed_quiesc =0 ;/* We could be racing with new GP, */ rdp->qs_pending =1 ;/* so set up to respond to current GP. */ rdp->beenonline =1 ;/* We have now been online. */ - rdp->preemptable = preemptable; + rdp->preemptible = preemptible; rdp->qlen_last_fqs_check =0 ; rdp->n_force_qs_snap = rsp->n_force_qs; rdp->blimit = blimit;
kernel/rcutree.h +1 -1
@@ -239,7 +239,7 @@ struct rcu_data {bool passed_quiesc;/* User-mode/idle loop etc. */ bool qs_pending;/* Core waits for quiesc state. */ bool beenonline;/* CPU online at least once. */ -bool preemptable;/* Preemptable RCU? */ +bool preemptible;/* Preemptible RCU? */ struct rcu_node *mynode;/* This CPU's leaf of hierarchy */ unsigned long grpmask;/* Mask to apply to leaf qsmask. */
kernel/rcutree_plugin.h +31 -31
248 lines not on this page · raw message
Signature · 1 line
1.7.3.2
PATCH 30/86 rcu: introduce kfree_rcu()
In reply to Paul E. McKenneyFrom: Lai Jiangshan <[email protected]>
Many rcu callbacks functions just call kfree() on the base structure. These functions are trivial, but their size adds up, and furthermore when they are used in a kernel module, that module must invoke the high-latency rcu_barrier() function at module-unload time.
The kfree_rcu() function introduced by this commit addresses this issue. Rather than encoding a function address in the embedded rcu_head structure, kfree_rcu() instead encodes the offset of the rcu_head structure within the base structure. Because the functions are not allowed in the low-order 4096 bytes of kernel virtual memory, offsets up to 4095 bytes can be accommodated. If the offset is larger than 4095 bytes, a compile-time error will be generated in __kfree_rcu(). If this error is triggered, you can either fall back to use of call_rcu() or rearrange the structure to position the rcu_head structure into the first 4096 bytes.
Note that the allowable offset might decrease in the future, for example, to allow something like kmem_cache_free_rcu().
The new kfree_rcu() function can replace code as follows:
call_rcu(&p->rcu, simple_kfree_callback);
where "simple_kfree_callback()" might be defined as follows:
void simple_kfree_callback(struct rcu_head *p)
{
struct foo *q = container_of(p, struct foo, rcu);
kfree(q);
}with the following:
kfree_rcu(&p->rcu, rcu);
Note that the "rcu" is the name of a field in the structure being freed. The reason for using this rather than passing in a pointer to the base structure is that the above approach allows better type checking.
This commit is based on earlier work by Lai Jiangshan and Manfred Spraul:
Lai's V1 patch: http://lkml.org/lkml/2008/9/18/1
Manfred's patch: http://lkml.org/lkml/2009/1/2/115
--- include/linux/rcupdate.h | 56 ++++++++++++++++++++++++++++++++++++++++++++++ kernel/rcutiny.c | 2 +- kernel/rcutree.c | 2 +- 3 files changed, 58 insertions(+), 2 deletions(-)
include/linux/rcupdate.h +56 -0
@@ -809,4 +809,60 @@ static inline void debug_rcu_head_unqueue(struct rcu_head *head) }#endif /* #else !CONFIG_DEBUG_OBJECTS_RCU_HEAD */ +static __always_inline bool __is_kfree_rcu_offset(unsigned long offset) +{ +return offset <4096 ; +} + +static __always_inline +void __kfree_rcu(struct rcu_head *head, unsigned long offset) +{ +typedef void (*rcu_callback )(struct rcu_head *); + +BUILD_BUG_ON (!__builtin_constant_p (offset)); + +/* See the kfree_rcu() header comment. */ +BUILD_BUG_ON (!__is_kfree_rcu_offset (offset)); + +call_rcu (head, (rcu_callback )offset); +} + +extern void kfree (const void *); + +static inline void __rcu_reclaim (struct rcu_head *head) +{ +unsigned long offset = (unsigned long )head->func; + +if (__is_kfree_rcu_offset (offset)) +kfree ((void *)head - offset); +else + head->func (head); +} + +/** +* kfree_rcu() - kfree an object after a grace period. +* @ptr: pointer to kfree +* @rcu_head: the name of the struct rcu_head within the type of @ptr. +* +* Many rcu callbacks functions just call kfree() on the base structure. +* These functions are trivial, but their size adds up, and furthermore +* when they are used in a kernel module, that module must invoke the +* high-latency rcu_barrier() function at module-unload time. +* +* The kfree_rcu() function handles this issue. Rather than encoding a +* function address in the embedded rcu_head structure, kfree_rcu() instead +* encodes the offset of the rcu_head structure within the base structure. +* Because the functions are not allowed in the low-order 4096 bytes of +* kernel virtual memory, offsets up to 4095 bytes can be accommodated. +* If the offset is larger than 4095 bytes, a compile-time error will +* be generated in __kfree_rcu(). If this error is triggered, you can +* either fall back to use of call_rcu() or rearrange the structure to +* position the rcu_head structure into the first 4096 bytes. +* +* Note that the allowable offset might decrease in the future, for example, +* to allow something like kmem_cache_free_rcu(). +*/ +#define kfree_rcu (ptr, rcu_head) \ + __kfree_rcu(&((ptr)->rcu_head), offsetof(typeof(*(ptr)), rcu_head)) +#endif /* __LINUX_RCUPDATE_H */
kernel/rcutiny.c +1 -1
@@ -167,7 +167,7 @@ static void rcu_process_callbacks(struct rcu_ctrlblk *rcp)prefetch (next);debug_rcu_head_unqueue (list);local_bh_disable (); - list->func (list); +__rcu_reclaim (list);local_bh_enable (); list = next;RCU_TRACE (cb_count++);
kernel/rcutree.c +1 -1
@@ -1206,7 +1206,7 @@ static void rcu_do_batch(struct rcu_state *rsp, struct rcu_data *rdp) next = list->next;prefetch (next);debug_rcu_head_unqueue (list); - list->func (list); +__rcu_reclaim (list); list = next;if (++count >= rdp->blimit)break ;
Signature · 1 line
1.7.3.2
PATCH 31/86 rcu: further lower priority in rcu_yield()
In reply to Paul E. McKenneyFrom: Paul E. McKenney <[email protected]>
Although rcu_yield() dropped from real-time to normal priority, there is always the possibility that the competing tasks have been niced. So nice to 19 in rcu_yield() to help ensure that other tasks have a better chance of running.
--- kernel/rcutree.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-)
kernel/rcutree.c +1 -0
@@ -1561,6 +1561,7 @@ static void rcu_yield(void (*f)(unsigned long), unsigned long arg)mod_timer (&yield_timer, jiffies +2 ); sp.sched_priority =0 ;sched_setscheduler_nocheck (current,SCHED_NORMAL , &sp); +set_user_nice (current,19 );schedule (); sp.sched_priority =RCU_KTHREAD_PRIO ;sched_setscheduler_nocheck (current,SCHED_FIFO , &sp);
Signature · 1 line
1.7.3.2
Re: [PATCH tip/core/rcu 31/86] rcu: further lower priority in rcu_yield()
Quoted 6 lines · Paul E. McKenney
From: Paul E. McKenney <[email protected]>
Although
rcu_yield()dropped from real-time to normal priority, there is always the possibility that the competing tasks have been niced. So nice to 19 inrcu_yield()to help ensure that other tasks have a better chance of running.
But.. that just prolongs the pain of overhead you _have_ to eat, no? In a brief surge, fine, you can spread the cost out.. but how do you know when it's ok to yield?
(When maintenance threads worrying about their CPU usage is worrisome.)
Quoted 18 lines
Signed-off-by Paul E. McKenney <[email protected]>Signed-off-by Paul E. McKenney <[email protected]>--- kernel/rcutree.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-)kernel/rcutree.c +1
-0@@ -1561,6 +1561,7 @@ static void rcu_yield(void (*f)(unsigned long), unsigned long arg)mod_timer (&yield_timer, jiffies +2 ); sp.sched_priority =0 ;sched_setscheduler_nocheck (current,SCHED_NORMAL , &sp); +set_user_nice (current,19 );schedule (); sp.sched_priority =RCU_KTHREAD_PRIO ;sched_setscheduler_nocheck (current,SCHED_FIFO , &sp);
Re: [PATCH tip/core/rcu 31/86] rcu: further lower priority in rcu_yield()
Quoted 11 lines · Mike Galbraith
Quoted 6 lines · Paul E. McKenney
From: Paul E. McKenney <[email protected]>
Although
rcu_yield()dropped from real-time to normal priority, there is always the possibility that the competing tasks have been niced. So nice to 19 inrcu_yield()to help ensure that other tasks have a better chance of running.But.. that just prolongs the pain of overhead you _have_ to eat, no? In a brief surge, fine, you can spread the cost out.. but how do you know when it's ok to yield?
I modeled this code on the existing code in ksoftirqd. But yes, this is a heuristic. I do believe that it is quite robust, but time will tell.
Quoted 1 line
(When maintenance threads worrying about their CPU usage is worrisome.)
Indeed. But I am not introducing this, just moving the existing checking from ksoftirqd.
So I believe that I am OK here.
Thanx, Paul
Quoted 20 lines
Quoted 18 lines
Signed-off-by Paul E. McKenney <[email protected]>Signed-off-by Paul E. McKenney <[email protected]>--- kernel/rcutree.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-)kernel/rcutree.c +1
-0@@ -1561,6 +1561,7 @@ static void rcu_yield(void (*f)(unsigned long), unsigned long arg)mod_timer (&yield_timer, jiffies +2 ); sp.sched_priority =0 ;sched_setscheduler_nocheck (current,SCHED_NORMAL , &sp); +set_user_nice (current,19 );schedule (); sp.sched_priority =RCU_KTHREAD_PRIO ;sched_setscheduler_nocheck (current,SCHED_FIFO , &sp);
Re: [PATCH tip/core/rcu 31/86] rcu: further lower priority in rcu_yield()
Quoted 9 lines · Paul E. McKenney
Quoted 8 lines · Mike Galbraith
Quoted 6 lines · Paul E. McKenney
From: Paul E. McKenney <[email protected]>
Although
rcu_yield()dropped from real-time to normal priority, there is always the possibility that the competing tasks have been niced. So nice to 19 inrcu_yield()to help ensure that other tasks have a better chance of running.
Quoted 6 lines
Quoted 3 lines
But.. that just prolongs the pain of overhead you _have_ to eat, no? In a brief surge, fine, you can spread the cost out.. but how do you know when it's ok to yield?
I modeled this code on the existing code in ksoftirqd. But yes, this is a heuristic. I do believe that it is quite robust, but time will tell.
(It probably is fine, but when I see 'yield', alarms and sirens go off)
PATCH 32/86 rcu: prevent call_rcu() from diving into rcu core if irqs disabled
In reply to Paul E. McKenneyThis commit marks a first step towards making call_rcu() have real-time behavior. If irqs are disabled, don't dive into the RCU core. Later on, this new early exit will wake up the per-CPU kthread, which first must be modified to handle the cases involving callback storms.
--- kernel/rcutree.c | 9 ++++++++- 1 files changed, 8 insertions(+), 1 deletions(-)
kernel/rcutree.c +8 -1
@@ -1839,6 +1839,13 @@ __call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu),/* Add the callback to our list. */ *rdp->nxttail[RCU_NEXT_TAIL ] = head; rdp->nxttail[RCU_NEXT_TAIL ] = &head->next; + rdp->qlen++; + +/* If interrupts were disabled, don't dive into RCU core. */ +if (irqs_disabled_flags (flags)) { +local_irq_restore (flags); +return ; + }/* * Force the grace period if too many callbacks or too long waiting.
@@ -1847,7 +1854,7 @@ __call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu),* invoking force_quiescent_state() if the newly enqueued callback * is the only one waiting for a grace period to complete. */ -if (unlikely (++rdp->qlen > rdp->qlen_last_fqs_check + qhimark)) { +if (unlikely (rdp->qlen > rdp->qlen_last_fqs_check + qhimark)) {/* Are we ignoring a completed grace period? */ rcu_process_gp_end (rsp, rdp);
Signature · 1 line
1.7.3.2
PATCH 33/86 rcu: optimize rcutiny
In reply to Paul E. McKenneyFrom: Eric Dumazet <[email protected]>
rcu_sched_qs() currently calls local_irq_save()/local_irq_restore() up to three times.
Remove irq masking from rcu_qsctr_help() / invoke_rcu_kthread() and do it once in rcu_sched_qs() / rcu_bh_qs()
This generates smaller code as well.
# size kernel/rcutiny.old.o kernel/rcutiny.new.o text data bss dec hex filename 2314 156 24 2494 9be kernel/rcutiny.old.o 2250 156 24 2430 97e kernel/rcutiny.new.o
Fix an outdated comment for rcu_qsctr_help() Move invoke_rcu_kthread() definition before its use.
--- kernel/rcutiny.c | 42 ++++++++++++++++++++---------------------- 1 files changed, 20 insertions(+), 22 deletions(-)
kernel/rcutiny.c +20 -22
@@ -40,7 +40,6 @@static struct task_struct *rcu_kthread_task;static DECLARE_WAIT_QUEUE_HEAD (rcu_kthread_wq);static unsigned long have_rcu_kthread_work; -static void invoke_rcu_kthread (void );/* Forward declarations for rcutiny_plugin.h. */ struct rcu_ctrlblk ;
@@ -79,36 +78,45 @@ void rcu_exit_nohz(void)#endif /* #ifdef CONFIG_NO_HZ */ /* -* Helper function for rcu_qsctr_inc() and rcu_bh_qsctr_inc(). -* Also disable irqs to avoid confusion due to interrupt handlers +* Helper function for rcu_sched_qs() and rcu_bh_qs(). +* Also irqs are disabled to avoid confusion due to interrupt handlers * invoking call_rcu(). */ static int rcu_qsctr_help (struct rcu_ctrlblk *rcp) { -unsigned long flags; - -local_irq_save (flags);if (rcp->rcucblist !=NULL && rcp->donetail != rcp->curtail) { rcp->donetail = rcp->curtail; -local_irq_restore (flags);return 1 ; } -local_irq_restore (flags);return 0 ; }/* +* Wake up rcu_kthread() to process callbacks now eligible for invocation +* or to boost readers. +*/ +static void invoke_rcu_kthread (void ) +{ + have_rcu_kthread_work =1 ; +wake_up (&rcu_kthread_wq); +} + +/* * Record an rcu quiescent state. And an rcu_bh quiescent state while we * are at it, given that any rcu quiescent state is also an rcu_bh * quiescent state. Use "+" instead of "||" to defeat short circuiting. */ void rcu_sched_qs (int cpu) { +unsigned long flags; + +local_irq_save (flags);if (rcu_qsctr_help (&rcu_sched_ctrlblk) +rcu_qsctr_help (&rcu_bh_ctrlblk))invoke_rcu_kthread (); +local_irq_restore (flags); }/*
@@ -116,8 +124,12 @@ void rcu_sched_qs(int cpu)*/ void rcu_bh_qs (int cpu) { +unsigned long flags; + +local_irq_save (flags);if (rcu_qsctr_help (&rcu_bh_ctrlblk))invoke_rcu_kthread (); +local_irq_restore (flags); }/*
@@ -208,20 +220,6 @@ static int rcu_kthread(void *arg) }/* -* Wake up rcu_kthread() to process callbacks now eligible for invocation -* or to boost readers. -*/ -static void invoke_rcu_kthread (void ) -{ -unsigned long flags; - -local_irq_save (flags); - have_rcu_kthread_work =1 ; -wake_up (&rcu_kthread_wq); -local_irq_restore (flags); -} - -/* * Wait for a grace period to elapse. But it is illegal to invoke * synchronize_sched() from within an RCU read-side critical section. * Therefore, any legal call to synchronize_sched() is a quiescent
Signature · 1 line
1.7.3.2
PATCH 34/86 cgroup,rcu: convert call_rcu(free_css_set_rcu) to kfree_rcu()
In reply to Paul E. McKenneyFrom: Lai Jiangshan <[email protected]>
The rcu callback free_css_set_rcu() just calls a kfree(), so we use kfree_rcu() instead of the call_rcu(free_css_set_rcu).
--- kernel/cgroup.c | 8 +------- 1 files changed, 1 insertions(+), 7 deletions(-)
kernel/cgroup.c +1 -7
@@ -326,12 +326,6 @@ static struct hlist_head *css_set_hash(struct cgroup_subsys_state *css[])return &css_set_table[index]; } -static void free_css_set_rcu (struct rcu_head *obj) -{ - struct css_set *cg = container_of(obj, struct css_set, rcu_head); -kfree (cg); -} -/* We don't maintain the lists running through each css_set to its * task until after the first call to cgroup_iter_start(). This * reduces the fork()/exit() overhead for people who have cgroups
@@ -375,7 +369,7 @@ static void __put_css_set(struct css_set *cg, int taskexit) }write_unlock (&css_set_lock); -call_rcu (&cg->rcu_head, free_css_set_rcu); +kfree_rcu (cg, rcu_head); }/*
Signature · 1 line
1.7.3.2
PATCH 35/86 cgroup,rcu: convert call_rcu(free_cgroup_rcu) to kfree_rcu()
In reply to Paul E. McKenneyFrom: Lai Jiangshan <[email protected]>
The rcu callback free_cgroup_rcu() just calls a kfree(), so we use kfree_rcu() instead of the call_rcu(free_cgroup_rcu).
--- kernel/cgroup.c | 9 +-------- 1 files changed, 1 insertions(+), 8 deletions(-)
kernel/cgroup.c +1 -8
@@ -806,13 +806,6 @@ static int cgroup_call_pre_destroy(struct cgroup *cgrp)return ret; } -static void free_cgroup_rcu (struct rcu_head *obj) -{ - struct cgroup *cgrp = container_of(obj, struct cgroup, rcu_head); - -kfree (cgrp); -} -static void cgroup_diput (struct dentry *dentry,struct inode *inode) {/* is dentry a directory ? if so, kfree() associated cgroup */
@@ -850,7 +843,7 @@ static void cgroup_diput(struct dentry *dentry, struct inode *inode)*/ BUG_ON (!list_empty (&cgrp->pidlists)); -call_rcu (&cgrp->rcu_head, free_cgroup_rcu); +kfree_rcu (cgrp, rcu_head); }iput (inode); }
Signature · 1 line
1.7.3.2
PATCH 36/86 cgroup,rcu: convert call_rcu(__free_css_id_cb) to kfree_rcu()
In reply to Paul E. McKenneyFrom: Lai Jiangshan <[email protected]>
The rcu callback __free_css_id_cb() just calls a kfree(), so we use kfree_rcu() instead of the call_rcu(__free_css_id_cb).
--- kernel/cgroup.c | 10 +--------- 1 files changed, 1 insertions(+), 9 deletions(-)
kernel/cgroup.c +1 -9
@@ -4610,14 +4610,6 @@ bool css_is_ancestor(struct cgroup_subsys_state *child,return ret; } -static void __free_css_id_cb (struct rcu_head *head) -{ -struct css_id *id; - - id = container_of(head, struct css_id, rcu_head); -kfree (id); -} -void free_css_id (struct cgroup_subsys *ss,struct cgroup_subsys_state *css) {struct css_id *id = css->id;
@@ -4632,7 +4624,7 @@ void free_css_id(struct cgroup_subsys *ss, struct cgroup_subsys_state *css)spin_lock (&ss->id_lock);idr_remove (&ss->idr, id->id);spin_unlock (&ss->id_lock); -call_rcu (&id->rcu_head, __free_css_id_cb); +kfree_rcu (id, rcu_head); }EXPORT_SYMBOL_GPL (free_css_id);
Signature · 1 line
1.7.3.2
PATCH 37/86 net,rcu: convert call_rcu(tcf_common_free_rcu) to kfree_rcu()
In reply to Paul E. McKenneyFrom: Lai Jiangshan <[email protected]>
The rcu callback tcf_common_free_rcu() just calls a kfree(), so we use kfree_rcu() instead of the call_rcu(tcf_common_free_rcu).
--- net/sched/act_api.c | 7 +------ 1 files changed, 1 insertions(+), 6 deletions(-)
net/sched/act_api.c +1 -6
@@ -26,11 +26,6 @@#include <net/act_api.h> #include <net/netlink.h> -static void tcf_common_free_rcu (struct rcu_head *head) -{ -kfree (container_of(head ,struct tcf_common ,tcfc_rcu )); -} -void tcf_hash_destroy (struct tcf_common *p,struct tcf_hashinfo *hinfo) {unsigned int h =tcf_hash (p->tcfc_index, hinfo->hmask);
@@ -47,7 +42,7 @@ void tcf_hash_destroy(struct tcf_common *p, struct tcf_hashinfo *hinfo)* gen_estimator est_timer() might access p->tcfc_lock * or bstats, wait a RCU grace period before freeing p */ -call_rcu (&p->tcfc_rcu, tcf_common_free_rcu); +kfree_rcu (p, tcfc_rcu);return ; } }
Signature · 1 line
1.7.3.2
PATCH 38/86 net,rcu: convert call_rcu(tcf_police_free_rcu) to kfree_rcu()
In reply to Paul E. McKenneyFrom: Lai Jiangshan <[email protected]>
[PATCH 05/17] net,rcu: convert call_rcu(tcf_police_free_rcu) to kfree_rcu()
The rcu callback tcf_police_free_rcu() just calls a kfree(), so we use kfree_rcu() instead of the call_rcu(tcf_police_free_rcu).
--- net/sched/act_police.c | 7 +------ 1 files changed, 1 insertions(+), 6 deletions(-)
net/sched/act_police.c +1 -6
@@ -96,11 +96,6 @@ nla_put_failure: goto done; } -static void tcf_police_free_rcu (struct rcu_head *head) -{ -kfree (container_of(head ,struct tcf_police ,tcf_rcu )); -} -static void tcf_police_destroy (struct tcf_police *p) {unsigned int h =tcf_hash (p->tcf_index,POL_TAB_MASK );
@@ -121,7 +116,7 @@ static void tcf_police_destroy(struct tcf_police *p)* gen_estimator est_timer() might access p->tcf_lock * or bstats, wait a RCU grace period before freeing p */ -call_rcu (&p->tcf_rcu, tcf_police_free_rcu); +kfree_rcu (p, tcf_rcu);return ; } }
Signature · 1 line
1.7.3.2
PATCH 39/86 net,rcu: convert call_rcu(in6_dev_finish_destroy_rcu) to kfree_rcu()
In reply to Paul E. McKenneyFrom: Lai Jiangshan <[email protected]>
The rcu callback in6_dev_finish_destroy_rcu() just calls a kfree(), so we use kfree_rcu() instead of the call_rcu(in6_dev_finish_destroy_rcu).
--- net/ipv6/addrconf.c | 8 +------- 1 files changed, 1 insertions(+), 7 deletions(-)
net/ipv6/addrconf.c +1 -7
@@ -317,12 +317,6 @@ static void snmp6_free_dev(struct inet6_dev *idev)/* Nobody refers to this device, we may destroy it. */ -static void in6_dev_finish_destroy_rcu (struct rcu_head *head) -{ - struct inet6_dev *idev = container_of(head, struct inet6_dev, rcu); -kfree (idev); -} -void in6_dev_finish_destroy (struct inet6_dev *idev) {struct net_device *dev = idev->dev;
@@ -339,7 +333,7 @@ void in6_dev_finish_destroy(struct inet6_dev *idev)return ; }snmp6_free_dev (idev); -call_rcu (&idev->rcu, in6_dev_finish_destroy_rcu); +kfree_rcu (idev, rcu); }EXPORT_SYMBOL (in6_dev_finish_destroy);
Signature · 1 line
1.7.3.2
PATCH 40/86 net,rcu: convert call_rcu(inet6_ifa_finish_destroy_rcu) to kfree_rcu()
In reply to Paul E. McKenneyFrom: Lai Jiangshan <[email protected]>
The rcu callback inet6_ifa_finish_destroy_rcu() just calls a kfree(), so we use kfree_rcu() instead of the call_rcu(inet6_ifa_finish_destroy_rcu).
--- net/ipv6/addrconf.c | 8 +------- 1 files changed, 1 insertions(+), 7 deletions(-)
net/ipv6/addrconf.c +1 -7
@@ -529,12 +529,6 @@ static int addrconf_fixup_forwarding(struct ctl_table *table, int *p, int old) }#endif -static void inet6_ifa_finish_destroy_rcu (struct rcu_head *head) -{ - struct inet6_ifaddr *ifp = container_of(head, struct inet6_ifaddr, rcu); -kfree (ifp); -} -/* Nobody refers to this ifaddr, destroy it */ void inet6_ifa_finish_destroy (struct inet6_ifaddr *ifp) {
@@ -555,7 +549,7 @@ void inet6_ifa_finish_destroy(struct inet6_ifaddr *ifp) }dst_release (&ifp->rt->dst); -call_rcu (&ifp->rcu, inet6_ifa_finish_destroy_rcu); +kfree_rcu (ifp, rcu); } static void
Signature · 1 line
1.7.3.2
PATCH 41/86 net,rcu: convert call_rcu(listeners_free_rcu) to kfree_rcu()
In reply to Paul E. McKenneyFrom: Lai Jiangshan <[email protected]>
The rcu callback listeners_free_rcu() just calls a kfree(), so we use kfree_rcu() instead of the call_rcu(listeners_free_rcu).
--- net/netlink/af_netlink.c | 8 +------- 1 files changed, 1 insertions(+), 7 deletions(-)
net/netlink/af_netlink.c +1 -7
@@ -1566,12 +1566,6 @@ netlink_kernel_release(struct sock *sk) }EXPORT_SYMBOL (netlink_kernel_release); - -static void listeners_free_rcu (struct rcu_head *head) -{ -kfree (container_of(head ,struct listeners ,rcu )); -} -int __netlink_change_ngroups (struct sock *sk,unsigned int groups) {struct listeners *new, *old;
@@ -1588,7 +1582,7 @@ int __netlink_change_ngroups(struct sock *sk, unsigned int groups)memcpy (new->masks, old->masks,NLGRPSZ (tbl->groups));rcu_assign_pointer (tbl->listeners, new); -call_rcu (&old->rcu, listeners_free_rcu); +kfree_rcu (old, rcu); } tbl->groups = groups;
Signature · 1 line
1.7.3.2
PATCH 42/86 net,rcu: convert call_rcu(sctp_local_addr_free) to kfree_rcu()
In reply to Paul E. McKenneyFrom: Lai Jiangshan <[email protected]>
The rcu callback sctp_local_addr_free() just calls a kfree(), so we use kfree_rcu() instead of the call_rcu(sctp_local_addr_free).
--- include/net/sctp/sctp.h | 1 - net/sctp/bind_addr.c | 2 +- net/sctp/ipv6.c | 2 +- net/sctp/protocol.c | 9 +-------- 4 files changed, 3 insertions(+), 11 deletions(-)
include/net/sctp/sctp.h +0 -1
@@ -115,7 +115,6 @@* sctp/protocol.c */ extern struct sock *sctp_get_ctl_sock (void ); -extern void sctp_local_addr_free (struct rcu_head *head);extern int sctp_copy_local_addr_list (struct sctp_bind_addr *,sctp_scope_t ,gfp_t gfp,int flags);
net/sctp/bind_addr.c +1 -1
@@ -219,7 +219,7 @@ int sctp_del_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *del_addr) }if (found) { -call_rcu (&addr->rcu, sctp_local_addr_free); +kfree_rcu (addr, rcu);SCTP_DBG_OBJCNT_DEC (addr);return 0 ; }
net/sctp/ipv6.c +1 -1
@@ -123,7 +123,7 @@ static int sctp_inet6addr_event(struct notifier_block *this, unsigned long ev, }spin_unlock_bh (&sctp_local_addr_lock);if (found) -call_rcu (&addr->rcu, sctp_local_addr_free); +kfree_rcu (addr, rcu);break ; }
net/sctp/protocol.c +1 -8
@@ -230,13 +230,6 @@ static void sctp_free_local_addr_list(void) } } -void sctp_local_addr_free (struct rcu_head *head) -{ -struct sctp_sockaddr_entry *e =container_of (head, - struct sctp_sockaddr_entry, rcu); -kfree (e); -} -/* Copy the local addresses which are valid for 'scope' into 'bp'. */ int sctp_copy_local_addr_list (struct sctp_bind_addr *bp,sctp_scope_t scope,gfp_t gfp,int copy_flags)
@@ -681,7 +674,7 @@ static int sctp_inetaddr_event(struct notifier_block *this, unsigned long ev, }spin_unlock_bh (&sctp_local_addr_lock);if (found) -call_rcu (&addr->rcu, sctp_local_addr_free); +kfree_rcu (addr, rcu);break ; }
Signature · 1 line
1.7.3.2
PATCH 43/86 net,rcu: convert call_rcu(ha_rcu_free) to kfree_rcu()
In reply to Paul E. McKenneyFrom: Lai Jiangshan <[email protected]>
The rcu callback ha_rcu_free() just calls a kfree(), so we use kfree_rcu() instead of the call_rcu(ha_rcu_free).
--- net/core/dev_addr_lists.c | 12 ++---------- 1 files changed, 2 insertions(+), 10 deletions(-)
net/core/dev_addr_lists.c +2 -10
@@ -68,14 +68,6 @@ static int __hw_addr_add(struct netdev_hw_addr_list *list, unsigned char *addr,return __hw_addr_add_ex (list, addr, addr_len, addr_type, false); } -static void ha_rcu_free (struct rcu_head *head) -{ -struct netdev_hw_addr *ha; - - ha = container_of(head, struct netdev_hw_addr, rcu_head); -kfree (ha); -} -static int __hw_addr_del_ex (struct netdev_hw_addr_list *list,unsigned char *addr,int addr_len,unsigned char addr_type,bool global)
@@ -94,7 +86,7 @@ static int __hw_addr_del_ex(struct netdev_hw_addr_list *list,if (--ha->refcount)return 0 ;list_del_rcu (&ha->list); -call_rcu (&ha->rcu_head, ha_rcu_free); +kfree_rcu (ha, rcu_head); list->count--;return 0 ; }
@@ -197,7 +189,7 @@ void __hw_addr_flush(struct netdev_hw_addr_list *list)list_for_each_entry_safe (ha, tmp, &list->list, list) {list_del_rcu (&ha->list); -call_rcu (&ha->rcu_head, ha_rcu_free); +kfree_rcu (ha, rcu_head); } list->count =0 ; }
Signature · 1 line
1.7.3.2
PATCH 44/86 net,rcu: convert call_rcu(dn_dev_free_ifa_rcu) to kfree_rcu()
In reply to Paul E. McKenneyFrom: Lai Jiangshan <[email protected]>
The rcu callback dn_dev_free_ifa_rcu() just calls a kfree(), so we use kfree_rcu() instead of the call_rcu(dn_dev_free_ifa_rcu).
--- net/decnet/dn_dev.c | 7 +------ 1 files changed, 1 insertions(+), 6 deletions(-)
net/decnet/dn_dev.c +1 -6
@@ -332,14 +332,9 @@ static struct dn_ifaddr *dn_dev_alloc_ifa(void)return ifa; } -static void dn_dev_free_ifa_rcu (struct rcu_head *head) -{ -kfree (container_of(head ,struct dn_ifaddr ,rcu )); -} -static void dn_dev_free_ifa (struct dn_ifaddr *ifa) { -call_rcu (&ifa->rcu, dn_dev_free_ifa_rcu); +kfree_rcu (ifa, rcu); }static void dn_dev_del_ifa (struct dn_dev *dn_db,struct dn_ifaddr __rcu **ifap,int destroy)
Signature · 1 line
1.7.3.2
PATCH 45/86 net,act_police,rcu: remove rcu_barrier()
In reply to Paul E. McKenneyFrom: Lai Jiangshan <[email protected]>
There is no callback of this module maybe queued
since we use kfree_rcu(), we can safely remove the rcu_barrier().
--- net/sched/act_police.c | 1 - 1 files changed, 0 insertions(+), 1 deletions(-)
net/sched/act_police.c +0 -1
@@ -396,7 +396,6 @@ static void __exitpolice_cleanup_module (void) {tcf_unregister_action (&act_police_ops); -rcu_barrier ();/* Wait for completion of call_rcu()'s (tcf_police_free_rcu) */ }module_init (police_init_module);
Signature · 1 line
1.7.3.2
Josh Triplett
maintainerRe: [PATCH tip/core/rcu 45/86] net,act_police,rcu: remove rcu_barrier()
Quoted 17 lines · Paul E. McKenney
From: Lai Jiangshan <[email protected]>
There is no callback of this module maybe queued
since we usekfree_rcu(), we can safely remove thercu_barrier().Signed-off-by Lai Jiangshan <[email protected]>Acked-by David S. Miller <[email protected]>Signed-off-by Paul E. McKenney <[email protected]>--- net/sched/act_police.c | 1 - 1 files changed, 0 insertions(+), 1 deletions(-)net/sched/act_police.c +0
-0
net/sched/act_police.c static void __exit · line 399
Quoted 5 lines
net/sched/act_police.c +0
-1@@ -396,7 +396,6 @@ static void __exitpolice_cleanup_module (void) {tcf_unregister_action (&act_police_ops); -rcu_barrier ();/* Wait for completion of call_rcu()'s (tcf_police_free_rcu) */ }
Very nice side-effect of having common callback code. Seems worth doing a review of other callers of rcu_barrier as well, to see if they still need to do so.
- Josh Triplett
Re: [PATCH tip/core/rcu 45/86] net,act_police,rcu: remove rcu_barrier()
Quoted 13 lines · Josh Triplett
Quoted 12 lines · Paul E. McKenney
From: Lai Jiangshan <[email protected]>
There is no callback of this module maybe queued
since we usekfree_rcu(), we can safely remove thercu_barrier().Signed-off-by Lai Jiangshan <[email protected]>Acked-by David S. Miller <[email protected]>Signed-off-by Paul E. McKenney <[email protected]>--- net/sched/act_police.c | 1 - 1 files changed, 0 insertions(+), 1 deletions(-)
Quoted 14 lines
net/sched/act_police.c static void __exit · line 399
Quoted 10 lines
net/sched/act_police.c +0
-1@@ -396,7 +396,6 @@ static void __exitpolice_cleanup_module (void) {tcf_unregister_action (&act_police_ops); -rcu_barrier ();/* Wait for completion of call_rcu()'s (tcf_police_free_rcu) */ }Very nice side-effect of having common callback code. Seems worth doing a review of other callers of
rcu_barrieras well, to see if they still need to do so.
Agreed, and good point on the review. /me wonders how this review could be automated...
Thanx, Paul
Josh Triplett
maintainerRe: [PATCH tip/core/rcu 45/86] net,act_police,rcu: remove rcu_barrier()
Quoted 29 lines · Paul E. McKenney
Quoted 13 lines · Josh Triplett
Quoted 12 lines · Paul E. McKenney
From: Lai Jiangshan <[email protected]>
There is no callback of this module maybe queued
since we usekfree_rcu(), we can safely remove thercu_barrier().Signed-off-by Lai Jiangshan <[email protected]>Acked-by David S. Miller <[email protected]>Signed-off-by Paul E. McKenney <[email protected]>--- net/sched/act_police.c | 1 - 1 files changed, 0 insertions(+), 1 deletions(-)Quoted 14 lines
net/sched/act_police.c static void __exit · line 399
Quoted 10 lines
net/sched/act_police.c +0
-1@@ -396,7 +396,6 @@ static void __exitpolice_cleanup_module (void) {tcf_unregister_action (&act_police_ops); -rcu_barrier ();/* Wait for completion of call_rcu()'s (tcf_police_free_rcu) */ }Very nice side-effect of having common callback code. Seems worth doing a review of other callers of
rcu_barrieras well, to see if they still need to do so.
Quoted 2 lines
Agreed, and good point on the review. /me wonders how this review could be automated...
Build everything as a module, and for each module check whether it uses the symbol rcu_barrier but not the symbol call_rcu. Same for the corresponding call_rcu_sched and call_rcu_bh.
Also, Coccinelle could likely handle simple cases of call_rcu(function_that_calls_container_of_then_kfree), at least when the call and the function appear in the same source file.
- Josh Triplett
Re: [PATCH tip/core/rcu 45/86] net,act_police,rcu: remove rcu_barrier()
Quoted 30 lines · Josh Triplett
Quoted 29 lines · Paul E. McKenney
Quoted 27 lines · Josh Triplett
Quoted 17 lines · Paul E. McKenney
From: Lai Jiangshan <[email protected]>
There is no callback of this module maybe queued
since we usekfree_rcu(), we can safely remove thercu_barrier().Signed-off-by Lai Jiangshan <[email protected]>Acked-by David S. Miller <[email protected]>Signed-off-by Paul E. McKenney <[email protected]>--- net/sched/act_police.c | 1 - 1 files changed, 0 insertions(+), 1 deletions(-)net/sched/act_police.c +0
-0net/sched/act_police.c static void __exit · line 399
Quoted 5 lines
net/sched/act_police.c +0
-1@@ -396,7 +396,6 @@ static void __exitpolice_cleanup_module (void) {tcf_unregister_action (&act_police_ops); -rcu_barrier ();/* Wait for completion of call_rcu()'s (tcf_police_free_rcu) */ }Very nice side-effect of having common callback code. Seems worth doing a review of other callers of
rcu_barrieras well, to see if they still need to do so.
Quoted 6 lines
Quoted 2 lines
Agreed, and good point on the review. /me wonders how this review could be automated...
Build everything as a module, and for each module check whether it uses the symbol
rcu_barrierbut not the symbolcall_rcu. Same for the correspondingcall_rcu_schedandcall_rcu_bh.
Good point -- I will give this a shot when I find AC power.
Quoted 3 lines
Also, Coccinelle could likely handle simple cases of
call_rcu(function_that_calls_container_of_then_kfree), at least when the call and the function appear in the same source file.
Good point -- it wasn't too hard by hand this time, but it would be a good addition to RCU checking.
Thanx, Paul
PATCH 46/86 security,rcu: convert call_rcu(user_update_rcu_disposal) to kfree_rcu()
In reply to Paul E. McKenneyFrom: Lai Jiangshan <[email protected]>
The rcu callback user_update_rcu_disposal() just calls a kfree(), so we use kfree_rcu() instead of the call_rcu(user_update_rcu_disposal).
--- security/keys/user_defined.c | 16 ++-------------- 1 files changed, 2 insertions(+), 14 deletions(-)
security/keys/user_defined.c +2 -14
@@ -69,18 +69,6 @@ error:EXPORT_SYMBOL_GPL (user_instantiate);/* -* dispose of the old data from an updated user defined key -*/ -static void user_update_rcu_disposal (struct rcu_head *rcu) -{ -struct user_key_payload *upayload; - - upayload = container_of(rcu, struct user_key_payload, rcu); - -kfree (upayload); -} - -/* * update a user defined key * - the key's semaphore is write-locked */
@@ -114,7 +102,7 @@ int user_update(struct key *key, const void *data, size_t datalen) key->expiry =0 ; } -call_rcu (&zap->rcu, user_update_rcu_disposal); +kfree_rcu (zap, rcu); error:return ret;
@@ -145,7 +133,7 @@ void user_revoke(struct key *key)if (upayload) {rcu_assign_pointer (key->payload.data,NULL ); -call_rcu (&upayload->rcu, user_update_rcu_disposal); +kfree_rcu (upayload, rcu); } }
Signature · 1 line
1.7.3.2
PATCH 47/86 net,rcu: convert call_rcu(fc_rport_free_rcu) to kfree_rcu()
In reply to Paul E. McKenneyFrom: Lai Jiangshan <[email protected]>
The rcu callback fc_rport_free_rcu() just calls a kfree(), so we use kfree_rcu() instead of the call_rcu(fc_rport_free_rcu).
--- net/ipv4/fib_semantics.c | 12 +----------- 1 files changed, 1 insertions(+), 11 deletions(-)
net/ipv4/fib_semantics.c +1 -11
@@ -141,18 +141,8 @@ const struct fib_prop fib_props[RTN_MAX + 1] = { }, }; -/* Release a nexthop info record */ -static void free_fib_info_rcu (struct rcu_head *head) -{ - struct fib_info *fi = container_of(head, struct fib_info, rcu); - -if (fi->fib_metrics != (u32 *) dst_default_metrics) -kfree (fi->fib_metrics); -kfree (fi); -} -void free_fib_info (struct fib_info *fi) {if (fi->fib_dead ==0 ) {
@@ -166,7 +156,7 @@ void free_fib_info(struct fib_info *fi) }endfor_nexthops (fi); fib_info_cnt--;release_net (fi->fib_net); -call_rcu (&fi->rcu, free_fib_info_rcu); +kfree_rcu (fi, rcu); }void fib_release_info (struct fib_info *fi)
Signature · 1 line
1.7.3.2
PATCH 48/86 net,rcu: convert call_rcu(__leaf_info_free_rcu) to kfree_rcu()
In reply to Paul E. McKenneyFrom: Lai Jiangshan <[email protected]>
The rcu callback __leaf_info_free_rcu() just calls a kfree(), so we use kfree_rcu() instead of the call_rcu(__leaf_info_free_rcu).
--- net/ipv4/fib_trie.c | 7 +------ 1 files changed, 1 insertions(+), 6 deletions(-)
net/ipv4/fib_trie.c +1 -6
@@ -350,14 +350,9 @@ static inline void free_leaf(struct leaf *l)call_rcu_bh (&l->rcu, __leaf_free_rcu); } -static void __leaf_info_free_rcu (struct rcu_head *head) -{ -kfree (container_of(head ,struct leaf_info ,rcu )); -} -static inline void free_leaf_info (struct leaf_info *leaf) { -call_rcu (&leaf->rcu, __leaf_info_free_rcu); +kfree_rcu (leaf, rcu); }static struct tnode *tnode_alloc (size_t size)
Signature · 1 line
1.7.3.2
PATCH 49/86 net,rcu: convert call_rcu(__gen_kill_estimator) to kfree_rcu()
In reply to Paul E. McKenneyFrom: Lai Jiangshan <[email protected]>
The rcu callback __gen_kill_estimator() just calls a kfree(), so we use kfree_rcu() instead of the call_rcu(__gen_kill_estimator).
--- net/core/gen_estimator.c | 9 +-------- 1 files changed, 1 insertions(+), 8 deletions(-)
net/core/gen_estimator.c +1 -8
@@ -249,13 +249,6 @@ int gen_new_estimator(struct gnet_stats_basic_packed *bstats, }EXPORT_SYMBOL (gen_new_estimator); -static void __gen_kill_estimator (struct rcu_head *head) -{ -struct gen_estimator *e =container_of (head, - struct gen_estimator, e_rcu); -kfree (e); -} -/** * gen_kill_estimator - remove a rate estimator * @bstats: basic statistics
@@ -279,7 +272,7 @@ void gen_kill_estimator(struct gnet_stats_basic_packed *bstats,write_unlock (&est_lock);list_del_rcu (&e->list); -call_rcu (&e->e_rcu, __gen_kill_estimator); +kfree_rcu (e, e_rcu); }spin_unlock_bh (&est_tree_lock); }
Signature · 1 line
1.7.3.2
PATCH 50/86 net,rcu: convert call_rcu(ip_mc_list_reclaim) to kfree_rcu()
In reply to Paul E. McKenneyFrom: Lai Jiangshan <[email protected]>
The rcu callback ip_mc_list_reclaim() just calls a kfree(), so we use kfree_rcu() instead of the call_rcu(ip_mc_list_reclaim).
--- net/ipv4/igmp.c | 8 +------- 1 files changed, 1 insertions(+), 7 deletions(-)
net/ipv4/igmp.c +1 -7
@@ -149,17 +149,11 @@ static void ip_mc_clear_src(struct ip_mc_list *pmc);static int ip_mc_add_src (struct in_device *in_dev,__be32 *pmca,int sfmode,int sfcount,__be32 *psfsrc,int delta); - -static void ip_mc_list_reclaim (struct rcu_head *head) -{ -kfree (container_of(head ,struct ip_mc_list ,rcu )); -} -static void ip_ma_put (struct ip_mc_list *im) {if (atomic_dec_and_test (&im->refcnt)) {in_dev_put (im->interface); -call_rcu (&im->rcu, ip_mc_list_reclaim); +kfree_rcu (im, rcu); } }
Signature · 1 line
1.7.3.2
PATCH 51/86 net,rcu: convert call_rcu(ip_sf_socklist_reclaim) to kfree_rcu()
In reply to Paul E. McKenneyFrom: Lai Jiangshan <[email protected]>
The rcu callback ip_sf_socklist_reclaim() just calls a kfree(), so we use kfree_rcu() instead of the call_rcu(ip_sf_socklist_reclaim).
--- net/ipv4/igmp.c | 12 +++--------- 1 files changed, 3 insertions(+), 9 deletions(-)
net/ipv4/igmp.c +3 -9
@@ -1830,12 +1830,6 @@ done: }EXPORT_SYMBOL (ip_mc_join_group); -static void ip_sf_socklist_reclaim (struct rcu_head *rp) -{ -kfree (container_of(rp ,struct ip_sf_socklist ,rcu )); -/* sk_omem_alloc should have been decreased by the caller*/ -} -static int ip_mc_leave_src (struct sock *sk,struct ip_mc_socklist *iml,struct in_device *in_dev) {
@@ -1852,7 +1846,7 @@ static int ip_mc_leave_src(struct sock *sk, struct ip_mc_socklist *iml,rcu_assign_pointer (iml->sflist,NULL );/* decrease mem now to avoid the memleak warning */ atomic_sub (IP_SFLSIZE (psf->sl_max), &sk->sk_omem_alloc); -call_rcu (&psf->rcu, ip_sf_socklist_reclaim); +kfree_rcu (psf, rcu);return err; }
@@ -2020,7 +2014,7 @@ int ip_mc_source(int add, int omode, struct sock *sk, struct newpsl->sl_addr[i] = psl->sl_addr[i];/* decrease mem now to avoid the memleak warning */ atomic_sub (IP_SFLSIZE (psl->sl_max), &sk->sk_omem_alloc); -call_rcu (&psl->rcu, ip_sf_socklist_reclaim); +kfree_rcu (psl, rcu); }rcu_assign_pointer (pmc->sflist, newpsl); psl = newpsl;
@@ -2121,7 +2115,7 @@ int ip_mc_msfilter(struct sock *sk, struct ip_msfilter *msf, int ifindex) psl->sl_count, psl->sl_addr, 0);/* decrease mem now to avoid the memleak warning */ atomic_sub (IP_SFLSIZE (psl->sl_max), &sk->sk_omem_alloc); -call_rcu (&psl->rcu, ip_sf_socklist_reclaim); +kfree_rcu (psl, rcu); }else (void )ip_mc_del_src (in_dev, &msf->imsf_multiaddr, pmc->sfmode,0 ,NULL ,0 );
Signature · 1 line
1.7.3.2
PATCH 52/86 net,rcu: convert call_rcu(ip_mc_socklist_reclaim) to kfree_rcu()
In reply to Paul E. McKenneyFrom: Lai Jiangshan <[email protected]>
The rcu callback ip_mc_socklist_reclaim() just calls a kfree(), so we use kfree_rcu() instead of the call_rcu(ip_mc_socklist_reclaim).
--- net/ipv4/igmp.c | 12 ++---------- 1 files changed, 2 insertions(+), 10 deletions(-)
net/ipv4/igmp.c +2 -10
@@ -1850,14 +1850,6 @@ static int ip_mc_leave_src(struct sock *sk, struct ip_mc_socklist *iml,return err; } - -static void ip_mc_socklist_reclaim (struct rcu_head *rp) -{ -kfree (container_of(rp ,struct ip_mc_socklist ,rcu )); -/* sk_omem_alloc should have been decreased by the caller*/ -} - -/* * Ask a socket to leave a group. */
@@ -1897,7 +1889,7 @@ int ip_mc_leave_group(struct sock *sk, struct ip_mreqn *imr)rtnl_unlock ();/* decrease mem now to avoid the memleak warning */ atomic_sub (sizeof (*iml), &sk->sk_omem_alloc); -call_rcu (&iml->rcu, ip_mc_socklist_reclaim); +kfree_rcu (iml, rcu);return 0 ; }if (!in_dev)
@@ -2312,7 +2304,7 @@ void ip_mc_drop_socket(struct sock *sk)ip_mc_dec_group (in_dev, iml->multi.imr_multiaddr.s_addr);/* decrease mem now to avoid the memleak warning */ atomic_sub (sizeof (*iml), &sk->sk_omem_alloc); -call_rcu (&iml->rcu, ip_mc_socklist_reclaim); +kfree_rcu (iml, rcu); }rtnl_unlock (); }
Signature · 1 line
1.7.3.2
PATCH 53/86 net,rcu: convert call_rcu(free_dm_hw_stat) to kfree_rcu()
In reply to Paul E. McKenneyFrom: Lai Jiangshan <[email protected]>
The rcu callback free_dm_hw_stat() just calls a kfree(), so we use kfree_rcu() instead of the call_rcu(free_dm_hw_stat).
--- net/core/drop_monitor.c | 12 ++---------- 1 files changed, 2 insertions(+), 10 deletions(-)
net/core/drop_monitor.c +2 -10
@@ -207,14 +207,6 @@ static void trace_napi_poll_hit(void *ignore, struct napi_struct *napi)rcu_read_unlock (); } - -static void free_dm_hw_stat (struct rcu_head *head) -{ -struct dm_hw_stat_delta *n; - n = container_of(head, struct dm_hw_stat_delta, rcu); -kfree (n); -} -static int set_all_monitor_traces (int state) {int rc =0 ;
@@ -245,7 +237,7 @@ static int set_all_monitor_traces(int state)list_for_each_entry_safe (new_stat, temp, &hw_stats_list, list) {if (new_stat->dev ==NULL ) {list_del_rcu (&new_stat->list); -call_rcu (&new_stat->rcu, free_dm_hw_stat); +kfree_rcu (new_stat, rcu); } }break ;
@@ -314,7 +306,7 @@ static int dropmon_net_event(struct notifier_block *ev_block, new_stat->dev =NULL ;if (trace_state ==TRACE_OFF ) {list_del_rcu (&new_stat->list); -call_rcu (&new_stat->rcu, free_dm_hw_stat); +kfree_rcu (new_stat, rcu);break ; } }
Signature · 1 line
1.7.3.2
PATCH 54/86 ixgbe,rcu: convert call_rcu(ring_free_rcu) to kfree_rcu()
In reply to Paul E. McKenneyFrom: Lai Jiangshan <[email protected]>
The rcu callback ring_free_rcu() just calls a kfree(), so we use kfree_rcu() instead of the call_rcu(ring_free_rcu).
--- drivers/net/ixgbe/ixgbe_main.c | 7 +------ 1 files changed, 1 insertions(+), 6 deletions(-)
drivers/net/ixgbe/ixgbe_main.c +1 -6
@@ -5100,11 +5100,6 @@ err_set_interrupt:return err; } -static void ring_free_rcu (struct rcu_head *head) -{ -kfree (container_of(head ,struct ixgbe_ring ,rcu )); -} -/** * ixgbe_clear_interrupt_scheme - Clear the current interrupt scheme settings * @adapter: board private structure to clear interrupt scheme on
@@ -5126,7 +5121,7 @@ void ixgbe_clear_interrupt_scheme(struct ixgbe_adapter *adapter)/* ixgbe_get_stats64() might access this ring, we must wait * a grace period before freeing it. */ -call_rcu (&ring->rcu, ring_free_rcu); +kfree_rcu (ring, rcu); adapter->rx_ring[i] =NULL ; }
Signature · 1 line
1.7.3.2
PATCH 55/86 macvlan,rcu: convert call_rcu(macvlan_port_rcu_free) to kfree_rcu()
In reply to Paul E. McKenneyFrom: Lai Jiangshan <[email protected]>
The rcu callback macvlan_port_rcu_free() just calls a kfree(), so we use kfree_rcu() instead of the call_rcu(macvlan_port_rcu_free).
--- drivers/net/macvlan.c | 10 +--------- 1 files changed, 1 insertions(+), 9 deletions(-)
drivers/net/macvlan.c +1 -9
@@ -603,21 +603,13 @@ static int macvlan_port_create(struct net_device *dev)return err; } -static void macvlan_port_rcu_free (struct rcu_head *head) -{ -struct macvlan_port *port; - - port = container_of(head, struct macvlan_port, rcu); -kfree (port); -} -static void macvlan_port_destroy (struct net_device *dev) {struct macvlan_port *port =macvlan_port_get (dev); dev->priv_flags &= ~IFF_MACVLAN_PORT ;netdev_rx_handler_unregister (dev); -call_rcu (&port->rcu, macvlan_port_rcu_free); +kfree_rcu (port, rcu); }static int macvlan_validate (struct nlattr *tb[],struct nlattr *data[])
Signature · 1 line
1.7.3.2
PATCH 56/86 net,rcu: convert call_rcu(ipv6_mc_socklist_reclaim) to kfree_rcu()
In reply to Paul E. McKenneyFrom: Lai Jiangshan <[email protected]>
The rcu callback ipv6_mc_socklist_reclaim() just calls a kfree(), so we use kfree_rcu() instead of the call_rcu(ipv6_mc_socklist_reclaim).
--- net/ipv6/mcast.c | 8 ++------ 1 files changed, 2 insertions(+), 6 deletions(-)
net/ipv6/mcast.c +2 -6
@@ -201,10 +201,6 @@ int ipv6_sock_mc_join(struct sock *sk, int ifindex, const struct in6_addr *addr)return 0 ; } -static void ipv6_mc_socklist_reclaim (struct rcu_head *head) -{ -kfree (container_of(head ,struct ipv6_mc_socklist ,rcu )); -}/* * socket leave on multicast group */
@@ -239,7 +235,7 @@ int ipv6_sock_mc_drop(struct sock *sk, int ifindex, const struct in6_addr *addr) (void )ip6_mc_leave_src (sk, mc_lst,NULL );rcu_read_unlock ();atomic_sub (sizeof (*mc_lst), &sk->sk_omem_alloc); -call_rcu (&mc_lst->rcu, ipv6_mc_socklist_reclaim); +kfree_rcu (mc_lst, rcu);return 0 ; } }
@@ -307,7 +303,7 @@ void ipv6_sock_mc_close(struct sock *sk)rcu_read_unlock ();atomic_sub (sizeof (*mc_lst), &sk->sk_omem_alloc); -call_rcu (&mc_lst->rcu, ipv6_mc_socklist_reclaim); +kfree_rcu (mc_lst, rcu);spin_lock (&ipv6_sk_mc_lock); }
Signature · 1 line
1.7.3.2
PATCH 57/86 net,rcu: convert call_rcu(rps_map_release) to kfree_rcu()
In reply to Paul E. McKenneyFrom: Lai Jiangshan <[email protected]>
The rcu callback rps_map_release() just calls a kfree(), so we use kfree_rcu() instead of the call_rcu(rps_map_release).
--- net/core/net-sysfs.c | 11 ++--------- 1 files changed, 2 insertions(+), 9 deletions(-)
net/core/net-sysfs.c +2 -9
@@ -565,13 +565,6 @@ static ssize_t show_rps_map(struct netdev_rx_queue *queue,return len; } -static void rps_map_release (struct rcu_head *rcu) -{ - struct rps_map *map = container_of(rcu, struct rps_map, rcu); - -kfree (map); -} -static ssize_t store_rps_map (struct netdev_rx_queue *queue,struct rx_queue_attribute *attribute,const char *buf,size_t len)
@@ -619,7 +612,7 @@ static ssize_t store_rps_map(struct netdev_rx_queue *queue,spin_unlock (&rps_map_lock);if (old_map) -call_rcu (&old_map->rcu, rps_map_release); +kfree_rcu (old_map, rcu);free_cpumask_var (mask);return len;
@@ -728,7 +721,7 @@ static void rx_queue_release(struct kobject *kobj) map =rcu_dereference_raw (queue->rps_map);if (map) {RCU_INIT_POINTER (queue->rps_map,NULL ); -call_rcu (&map->rcu, rps_map_release); +kfree_rcu (map, rcu); } flow_table =rcu_dereference_raw (queue->rps_flow_table);
Signature · 1 line
1.7.3.2
PATCH 58/86 net,rcu: convert call_rcu(xps_map_release) to kfree_rcu()
In reply to Paul E. McKenneyFrom: Lai Jiangshan <[email protected]>
The rcu callback xps_map_release() just calls a kfree(), so we use kfree_rcu() instead of the call_rcu(xps_map_release).
--- net/core/net-sysfs.c | 11 ++--------- 1 files changed, 2 insertions(+), 9 deletions(-)
net/core/net-sysfs.c +2 -9
@@ -891,13 +891,6 @@ static ssize_t show_xps_map(struct netdev_queue *queue,return len; } -static void xps_map_release (struct rcu_head *rcu) -{ - struct xps_map *map = container_of(rcu, struct xps_map, rcu); - -kfree (map); -} -static void xps_dev_maps_release (struct rcu_head *rcu) { struct xps_dev_maps *dev_maps =
@@ -1002,7 +995,7 @@ static ssize_t store_xps_map(struct netdev_queue *queue, map = dev_maps ?xmap_dereference (dev_maps->cpu_map[cpu]) :NULL ;if (map &&xmap_dereference (new_dev_maps->cpu_map[cpu]) != map) -call_rcu (&map->rcu, xps_map_release); +kfree_rcu (map, rcu);if (new_dev_maps->cpu_map[cpu]) nonempty =1 ; }
@@ -1077,7 +1070,7 @@ static void netdev_queue_release(struct kobject *kobj)else {RCU_INIT_POINTER (dev_maps->cpu_map[i],NULL ); -call_rcu (&map->rcu, xps_map_release); +kfree_rcu (map, rcu); map =NULL ; } }
Signature · 1 line
1.7.3.2
PATCH 59/86 net,rcu: convert call_rcu(xps_dev_maps_release) to kfree_rcu()
In reply to Paul E. McKenneyFrom: Lai Jiangshan <[email protected]>
The rcu callback xps_dev_maps_release() just calls a kfree(), so we use kfree_rcu() instead of the call_rcu(xps_dev_maps_release).
--- net/core/net-sysfs.c | 12 ++---------- 1 files changed, 2 insertions(+), 10 deletions(-)
net/core/net-sysfs.c +2 -10
@@ -891,14 +891,6 @@ static ssize_t show_xps_map(struct netdev_queue *queue,return len; } -static void xps_dev_maps_release (struct rcu_head *rcu) -{ -struct xps_dev_maps *dev_maps = - container_of(rcu, struct xps_dev_maps, rcu); - -kfree (dev_maps); -} -static DEFINE_MUTEX (xps_map_mutex);#define xmap_dereference (P ) \ rcu_dereference_protected((P), lockdep_is_held(&xps_map_mutex))
@@ -1008,7 +1000,7 @@ static ssize_t store_xps_map(struct netdev_queue *queue, }if (dev_maps) -call_rcu (&dev_maps->rcu, xps_dev_maps_release); +kfree_rcu (dev_maps, rcu);netdev_queue_numa_node_write (queue, (numa_node >=0 ) ? numa_node :NUMA_NO_NODE );
@@ -1080,7 +1072,7 @@ static void netdev_queue_release(struct kobject *kobj)if (!nonempty) {RCU_INIT_POINTER (dev->xps_maps,NULL ); -call_rcu (&dev_maps->rcu, xps_dev_maps_release); +kfree_rcu (dev_maps, rcu); } }
Signature · 1 line
1.7.3.2
PATCH 60/86 security,rcu: convert call_rcu(sel_netif_free) to kfree_rcu()
In reply to Paul E. McKenneyFrom: Lai Jiangshan <[email protected]>
The rcu callback sel_netif_free() just calls a kfree(), so we use kfree_rcu() instead of the call_rcu(sel_netif_free).
--- security/selinux/netif.c | 18 +----------------- 1 files changed, 1 insertions(+), 17 deletions(-)
security/selinux/netif.c +1 -17
@@ -104,22 +104,6 @@ static int sel_netif_insert(struct sel_netif *netif) }/** -* sel_netif_free - Frees an interface entry -* @p: the entry's RCU field -* -* Description: -* This function is designed to be used as a callback to the call_rcu() -* function so that memory allocated to a hash table interface entry can be -* released safely. -* -*/ -static void sel_netif_free (struct rcu_head *p) -{ - struct sel_netif *netif = container_of(p, struct sel_netif, rcu_head); -kfree (netif); -} - -/** * sel_netif_destroy - Remove an interface record from the table * @netif: the existing interface record *
@@ -131,7 +115,7 @@ static void sel_netif_destroy(struct sel_netif *netif) {list_del_rcu (&netif->list); sel_netif_total--; -call_rcu (&netif->rcu_head, sel_netif_free); +kfree_rcu (netif, rcu_head); }/**
Signature · 1 line
1.7.3.2
PATCH 61/86 net,rcu: convert call_rcu(netlbl_unlhsh_free_addr4) to kfree_rcu()
In reply to Paul E. McKenneyFrom: Lai Jiangshan <[email protected]>
The rcu callback netlbl_unlhsh_free_addr4() just calls a kfree(), so we use kfree_rcu() instead of the call_rcu(netlbl_unlhsh_free_addr4).
--- net/netlabel/netlabel_unlabeled.c | 20 +------------------- 1 files changed, 1 insertions(+), 19 deletions(-)
net/netlabel/netlabel_unlabeled.c +1 -19
@@ -153,24 +153,6 @@ static const struct nla_policy netlbl_unlabel_genl_policy[NLBL_UNLABEL_A_MAX + 1* Unlabeled Connection Hash Table Functions */ -/** -* netlbl_unlhsh_free_addr4 - Frees an IPv4 address entry from the hash table -* @entry: the entry's RCU field -* -* Description: -* This function is designed to be used as a callback to the call_rcu() -* function so that memory allocated to a hash table address entry can be -* released safely. -* -*/ -static void netlbl_unlhsh_free_addr4 (struct rcu_head *entry) -{ -struct netlbl_unlhsh_addr4 *ptr; - - ptr = container_of(entry, struct netlbl_unlhsh_addr4, rcu); -kfree (ptr); -} -#if defined(CONFIG_IPV6 ) || defined(CONFIG_IPV6_MODULE )/** * netlbl_unlhsh_free_addr6 - Frees an IPv6 address entry from the hash table
@@ -568,7 +550,7 @@ static int netlbl_unlhsh_remove_addr4(struct net *net,if (entry ==NULL )return -ENOENT ; -call_rcu (&entry->rcu, netlbl_unlhsh_free_addr4); +kfree_rcu (entry, rcu);return 0 ; }
Signature · 1 line
1.7.3.2
PATCH 62/86 net,rcu: convert call_rcu(netlbl_unlhsh_free_addr6) to kfree_rcu()
In reply to Paul E. McKenneyFrom: Lai Jiangshan <[email protected]>
The rcu callback netlbl_unlhsh_free_addr6() just calls a kfree(), so we use kfree_rcu() instead of the call_rcu(netlbl_unlhsh_free_addr6).
--- net/netlabel/netlabel_unlabeled.c | 22 +--------------------- 1 files changed, 1 insertions(+), 21 deletions(-)
net/netlabel/netlabel_unlabeled.c +1 -21
@@ -153,26 +153,6 @@ static const struct nla_policy netlbl_unlabel_genl_policy[NLBL_UNLABEL_A_MAX + 1* Unlabeled Connection Hash Table Functions */ -#if defined(CONFIG_IPV6 ) || defined(CONFIG_IPV6_MODULE ) -/** -* netlbl_unlhsh_free_addr6 - Frees an IPv6 address entry from the hash table -* @entry: the entry's RCU field -* -* Description: -* This function is designed to be used as a callback to the call_rcu() -* function so that memory allocated to a hash table address entry can be -* released safely. -* -*/ -static void netlbl_unlhsh_free_addr6 (struct rcu_head *entry) -{ -struct netlbl_unlhsh_addr6 *ptr; - - ptr = container_of(entry, struct netlbl_unlhsh_addr6, rcu); -kfree (ptr); -} -#endif /* IPv6 */ -/** * netlbl_unlhsh_free_iface - Frees an interface entry from the hash table * @entry: the entry's RCU field
@@ -611,7 +591,7 @@ static int netlbl_unlhsh_remove_addr6(struct net *net,if (entry ==NULL )return -ENOENT ; -call_rcu (&entry->rcu, netlbl_unlhsh_free_addr6); +kfree_rcu (entry, rcu); return 0; }#endif /* IPv6 */
Signature · 1 line
1.7.3.2
PATCH 63/86 net,rcu: convert call_rcu(net_generic_release) to kfree_rcu()
In reply to Paul E. McKenneyFrom: Lai Jiangshan <[email protected]>
The rcu callback net_generic_release() just calls a kfree(), so we use kfree_rcu() instead of the call_rcu(net_generic_release).
--- net/core/net_namespace.c | 10 +--------- 1 files changed, 1 insertions(+), 9 deletions(-)
net/core/net_namespace.c +1 -9
@@ -27,14 +27,6 @@ EXPORT_SYMBOL(init_net);#define INITIAL_NET_GEN_PTRS 13/* +1 for len +2 for rcu_head */ -static void net_generic_release (struct rcu_head *rcu) -{ -struct net_generic *ng; - - ng = container_of(rcu, struct net_generic, rcu); -kfree (ng); -} -static int net_assign_generic (struct net *net,int id,void *data) {struct net_generic *ng, *old_ng;
@@ -68,7 +60,7 @@ static int net_assign_generic(struct net *net, int id, void *data)memcpy (&ng->ptr, &old_ng->ptr, old_ng->len *sizeof (void *));rcu_assign_pointer (net->gen, ng); -call_rcu (&old_ng->rcu, net_generic_release); +kfree_rcu (old_ng, rcu); assign: ng->ptr[id -1 ] = data;return 0 ;
Signature · 1 line
1.7.3.2
PATCH 64/86 net,rcu: convert call_rcu(__nf_ct_ext_free_rcu) to kfree_rcu()
In reply to Paul E. McKenneyFrom: Lai Jiangshan <[email protected]>
The rcu callback __nf_ct_ext_free_rcu() just calls a kfree(), so we use kfree_rcu() instead of the call_rcu(__nf_ct_ext_free_rcu).
--- net/netfilter/nf_conntrack_extend.c | 8 +------- 1 files changed, 1 insertions(+), 7 deletions(-)
net/netfilter/nf_conntrack_extend.c +1 -7
@@ -68,12 +68,6 @@ nf_ct_ext_create(struct nf_ct_ext **ext, enum nf_ct_ext_id id, gfp_t gfp)return (void *)(*ext) + off; } -static void __nf_ct_ext_free_rcu (struct rcu_head *head) -{ - struct nf_ct_ext *ext = container_of(head, struct nf_ct_ext, rcu); -kfree (ext); -} -void *__nf_ct_ext_add (struct nf_conn *ct,enum nf_ct_ext_id id,gfp_t gfp) {struct nf_ct_ext *old, *new;
@@ -114,7 +108,7 @@ void *__nf_ct_ext_add(struct nf_conn *ct, enum nf_ct_ext_id id, gfp_t gfp) (void *)old + old->offset[i]);rcu_read_unlock (); } -call_rcu (&old->rcu, __nf_ct_ext_free_rcu); +kfree_rcu (old, rcu); ct->ext = new; }
Signature · 1 line
1.7.3.2
PATCH 65/86 perf,rcu: convert call_rcu(free_ctx) to kfree_rcu()
In reply to Paul E. McKenneyFrom: Lai Jiangshan <[email protected]>
The rcu callback free_ctx() just calls a kfree(), so we use kfree_rcu() instead of the call_rcu(free_ctx).
--- kernel/perf_event.c | 10 +--------- 1 files changed, 1 insertions(+), 9 deletions(-)
kernel/perf_event.c +1 -9
@@ -585,14 +585,6 @@ static void get_ctx(struct perf_event_context *ctx)WARN_ON (!atomic_inc_not_zero (&ctx->refcount)); } -static void free_ctx (struct rcu_head *head) -{ -struct perf_event_context *ctx; - - ctx = container_of(head, struct perf_event_context, rcu_head); -kfree (ctx); -} -static void put_ctx (struct perf_event_context *ctx) {if (atomic_dec_and_test (&ctx->refcount)) {
@@ -600,7 +592,7 @@ static void put_ctx(struct perf_event_context *ctx)put_ctx (ctx->parent_ctx);if (ctx->task)put_task_struct (ctx->task); -call_rcu (&ctx->rcu_head, free_ctx); +kfree_rcu (ctx, rcu_head); } }
Signature · 1 line
1.7.3.2
PATCH 66/86 perf,rcu: convert call_rcu(swevent_hlist_release_rcu) to kfree_rcu()
In reply to Paul E. McKenneyFrom: Lai Jiangshan <[email protected]>
The rcu callback swevent_hlist_release_rcu() just calls a kfree(), so we use kfree_rcu() instead of the call_rcu(swevent_hlist_release_rcu).
--- kernel/perf_event.c | 10 +--------- 1 files changed, 1 insertions(+), 9 deletions(-)
kernel/perf_event.c +1 -9
@@ -5311,14 +5311,6 @@ swevent_hlist_deref(struct swevent_htable *swhash) lockdep_is_held(&swhash->hlist_mutex)); } -static void swevent_hlist_release_rcu (struct rcu_head *rcu_head) -{ -struct swevent_hlist *hlist; - - hlist = container_of(rcu_head, struct swevent_hlist, rcu_head); -kfree (hlist); -} -static void swevent_hlist_release (struct swevent_htable *swhash) {struct swevent_hlist *hlist =swevent_hlist_deref (swhash);
@@ -5327,7 +5319,7 @@ static void swevent_hlist_release(struct swevent_htable *swhash)return ;rcu_assign_pointer (swhash->swevent_hlist,NULL ); -call_rcu (&hlist->rcu_head, swevent_hlist_release_rcu); +kfree_rcu (hlist, rcu_head); }static void swevent_hlist_put_cpu (struct perf_event *event,int cpu)
Signature · 1 line
1.7.3.2
PATCH 67/86 net,rcu: convert call_rcu(phonet_device_rcu_free) to kfree_rcu()
In reply to Paul E. McKenneyFrom: Lai Jiangshan <[email protected]>
The rcu callback phonet_device_rcu_free() just calls a kfree(), so we use kfree_rcu() instead of the call_rcu(phonet_device_rcu_free).
--- net/phonet/pn_dev.c | 10 +--------- 1 files changed, 1 insertions(+), 9 deletions(-)
net/phonet/pn_dev.c +1 -9
@@ -162,14 +162,6 @@ int phonet_address_add(struct net_device *dev, u8 addr)return err; } -static void phonet_device_rcu_free (struct rcu_head *head) -{ -struct phonet_device *pnd; - - pnd = container_of(head, struct phonet_device, rcu); -kfree (pnd); -} -int phonet_address_del (struct net_device *dev,u8 addr) {struct phonet_device_list *pndevs =phonet_device_list (dev_net (dev));
@@ -188,7 +180,7 @@ int phonet_address_del(struct net_device *dev, u8 addr)mutex_unlock (&pndevs->lock);if (pnd) -call_rcu (&pnd->rcu, phonet_device_rcu_free); +kfree_rcu (pnd, rcu);return err; }
Signature · 1 line
1.7.3.2
PATCH 68/86 net,rcu: convert call_rcu(wq_free_rcu) to kfree_rcu()
In reply to Paul E. McKenneyFrom: Lai Jiangshan <[email protected]>
The rcu callback wq_free_rcu() just calls a kfree(), so we use kfree_rcu() instead of the call_rcu(wq_free_rcu).
--- net/socket.c | 11 +---------- 1 files changed, 1 insertions(+), 10 deletions(-)
net/socket.c +1 -10
@@ -263,15 +263,6 @@ static struct inode *sock_alloc_inode(struct super_block *sb)return &ei->vfs_inode; } - - -static void wq_free_rcu (struct rcu_head *head) -{ - struct socket_wq *wq = container_of(head, struct socket_wq, rcu); - -kfree (wq); -} -static void sock_destroy_inode (struct inode *inode) {struct socket_alloc *ei;
@@ -279,7 +270,7 @@ static void sock_destroy_inode(struct inode *inode) ei = container_of(inode, struct socket_alloc, vfs_inode); wq =rcu_dereference_protected (ei->socket.wq,1 ); -call_rcu (&wq->rcu, wq_free_rcu); +kfree_rcu (wq, rcu);kmem_cache_free (sock_inode_cachep, ei); }
Signature · 1 line
1.7.3.2
PATCH 69/86 net/mac80211,rcu: convert call_rcu(work_free_rcu) to kfree_rcu()
In reply to Paul E. McKenneyFrom: Lai Jiangshan <[email protected]>
The rcu callback work_free_rcu() just calls a kfree(), so we use kfree_rcu() instead of the call_rcu(work_free_rcu).
--- net/mac80211/work.c | 10 +--------- 1 files changed, 1 insertions(+), 9 deletions(-)
net/mac80211/work.c +1 -9
@@ -65,17 +65,9 @@ static void run_again(struct ieee80211_local *local,mod_timer (&local->work_timer, timeout); } -static void work_free_rcu (struct rcu_head *head) -{ -struct ieee80211_work *wk = - container_of(head, struct ieee80211_work, rcu_head); - -kfree (wk); -} -void free_work (struct ieee80211_work *wk) { -call_rcu (&wk->rcu_head, work_free_rcu); +kfree_rcu (wk, rcu_head); } static int ieee80211_compatible_rates(const u8 *supp_rates, int supp_rates_len,
Signature · 1 line
1.7.3.2
PATCH 70/86 net,rcu: convert call_rcu(xt_osf_finger_free_rcu) to kfree_rcu()
In reply to Paul E. McKenneyFrom: Lai Jiangshan <[email protected]>
The rcu callback xt_osf_finger_free_rcu() just calls a kfree(), so we use kfree_rcu() instead of the call_rcu(xt_osf_finger_free_rcu).
--- net/netfilter/xt_osf.c | 11 ++--------- 1 files changed, 2 insertions(+), 9 deletions(-)
net/netfilter/xt_osf.c +2 -9
@@ -62,13 +62,6 @@ static const struct nla_policy xt_osf_policy[OSF_ATTR_MAX + 1] = { [OSF_ATTR_FINGER] = { .len = sizeof(struct xt_osf_user_finger) }, }; -static void xt_osf_finger_free_rcu (struct rcu_head *rcu_head) -{ - struct xt_osf_finger *f = container_of(rcu_head, struct xt_osf_finger, rcu_head); - -kfree (f); -} -static int xt_osf_add_callback (struct sock *ctnl,struct sk_buff *skb,const struct nlmsghdr *nlh,const struct nlattr *const osf_attrs[])
@@ -133,7 +126,7 @@ static int xt_osf_remove_callback(struct sock *ctnl, struct sk_buff *skb,* We are protected by nfnl mutex. */ list_del_rcu (&sf->finger_entry); -call_rcu (&sf->rcu_head, xt_osf_finger_free_rcu); +kfree_rcu (sf, rcu_head); err =0 ;break ;
@@ -414,7 +407,7 @@ static void __exit xt_osf_fini(void)list_for_each_entry_rcu (f, &xt_osf_fingers[i], finger_entry) {list_del_rcu (&f->finger_entry); -call_rcu (&f->rcu_head, xt_osf_finger_free_rcu); +kfree_rcu (f, rcu_head); } }rcu_read_unlock ();
Signature · 1 line
1.7.3.2
PATCH 71/86 net,rcu: convert call_rcu(kfree_tid_tx) to kfree_rcu()
In reply to Paul E. McKenneyFrom: Lai Jiangshan <[email protected]>
The rcu callback kfree_tid_tx() just calls a kfree(), so we use kfree_rcu() instead of the call_rcu(kfree_tid_tx).
--- net/mac80211/agg-tx.c | 14 +++----------- 1 files changed, 3 insertions(+), 11 deletions(-)
net/mac80211/agg-tx.c +3 -11
@@ -136,14 +136,6 @@ void ieee80211_send_bar(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, u1ieee80211_tx_skb (sdata, skb); } -static void kfree_tid_tx (struct rcu_head *rcu_head) -{ -struct tid_ampdu_tx *tid_tx = - container_of(rcu_head, struct tid_ampdu_tx, rcu_head); - -kfree (tid_tx); -} -int ___ieee80211_stop_tx_ba_session (struct sta_info *sta,u16 tid,enum ieee80211_back_parties initiator,bool tx)
@@ -163,7 +155,7 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,/* not even started yet! */ rcu_assign_pointer (sta->ampdu_mlme.tid_tx[tid],NULL );spin_unlock_bh (&sta->lock); -call_rcu (&tid_tx->rcu_head, kfree_tid_tx); +kfree_rcu (tid_tx, rcu_head);return 0 ; }
@@ -322,7 +314,7 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid)spin_unlock_bh (&sta->lock);ieee80211_wake_queue_agg (local, tid); -call_rcu (&tid_tx->rcu_head, kfree_tid_tx); +kfree_rcu (tid_tx, rcu_head);return ; }
@@ -701,7 +693,7 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid)ieee80211_agg_splice_finish (local, tid); -call_rcu (&tid_tx->rcu_head, kfree_tid_tx); +kfree_rcu (tid_tx, rcu_head); unlock_sta:spin_unlock_bh (&sta->lock);
Signature · 1 line
1.7.3.2
PATCH 72/86 audit_tree,rcu: convert call_rcu(__put_tree) to kfree_rcu()
In reply to Paul E. McKenneyFrom: Lai Jiangshan <[email protected]>
The rcu callback __put_tree() just calls a kfree(), so we use kfree_rcu() instead of the call_rcu(__put_tree).
--- kernel/audit_tree.c | 8 +------- 1 files changed, 1 insertions(+), 7 deletions(-)
kernel/audit_tree.c +1 -7
@@ -93,16 +93,10 @@ static inline void get_tree(struct audit_tree *tree)atomic_inc (&tree->count); } -static void __put_tree (struct rcu_head *rcu) -{ - struct audit_tree *tree = container_of(rcu, struct audit_tree, head); -kfree (tree); -} -static inline void put_tree (struct audit_tree *tree) {if (atomic_dec_and_test (&tree->count)) -call_rcu (&tree->head, __put_tree); +kfree_rcu (tree, head); }/* to avoid bringing the entire thing in audit.h */
Signature · 1 line
1.7.3.2
PATCH 73/86 block,rcu: convert call_rcu(cfq_cfqd_free) to kfree_rcu()
In reply to Paul E. McKenneyFrom: Lai Jiangshan <[email protected]>
The rcu callback cfq_cfqd_free() just calls a kfree(), so we use kfree_rcu() instead of the call_rcu(cfq_cfqd_free).
--- block/cfq-iosched.c | 7 +------ 1 files changed, 1 insertions(+), 6 deletions(-)
block/cfq-iosched.c +1 -6
@@ -3824,11 +3824,6 @@ static void cfq_put_async_queues(struct cfq_data *cfqd)cfq_put_queue (cfqd->async_idle_cfqq); } -static void cfq_cfqd_free (struct rcu_head *head) -{ -kfree (container_of(head ,struct cfq_data ,rcu )); -} -static void cfq_exit_queue (struct elevator_queue *e) {struct cfq_data *cfqd = e->elevator_data;
@@ -3862,7 +3857,7 @@ static void cfq_exit_queue(struct elevator_queue *e)spin_unlock (&cic_index_lock);/* Wait for cfqg->blkg->key accessors to exit their grace periods. */ -call_rcu (&cfqd->rcu, cfq_cfqd_free); +kfree_rcu (cfqd, rcu); }static int cfq_alloc_cic_index (void )
Signature · 1 line
1.7.3.2
PATCH 74/86 nfs,rcu: convert call_rcu(nfs_free_delegation_callback) to kfree_rcu()
In reply to Paul E. McKenneyFrom: Lai Jiangshan <[email protected]>
The rcu callback nfs_free_delegation_callback() just calls a kfree(), so we use kfree_rcu() instead of the call_rcu(nfs_free_delegation_callback).
--- fs/nfs/delegation.c | 14 +------------- 1 files changed, 1 insertions(+), 13 deletions(-)
fs/nfs/delegation.c +1 -13
@@ -21,25 +21,13 @@#include "delegation.h" #include "internal.h" -static void nfs_do_free_delegation (struct nfs_delegation *delegation) -{ -kfree (delegation); -} - -static void nfs_free_delegation_callback (struct rcu_head *head) -{ - struct nfs_delegation *delegation = container_of(head, struct nfs_delegation, rcu); - -nfs_do_free_delegation (delegation); -} -static void nfs_free_delegation (struct nfs_delegation *delegation) {if (delegation->cred) {put_rpccred (delegation->cred); delegation->cred =NULL ; } -call_rcu (&delegation->rcu, nfs_free_delegation_callback); +kfree_rcu (delegation, rcu); }/**
Signature · 1 line
1.7.3.2
PATCH 75/86 security,rcu: convert call_rcu(whitelist_item_free) to kfree_rcu()
In reply to Paul E. McKenneyFrom: Lai Jiangshan <[email protected]>
The rcu callback whitelist_item_free() just calls a kfree(), so we use kfree_rcu() instead of the call_rcu(whitelist_item_free).
--- security/device_cgroup.c | 10 +--------- 1 files changed, 1 insertions(+), 9 deletions(-)
security/device_cgroup.c +1 -9
@@ -126,14 +126,6 @@ static int dev_whitelist_add(struct dev_cgroup *dev_cgroup,return 0 ; } -static void whitelist_item_free (struct rcu_head *rcu) -{ -struct dev_whitelist_item *item; - - item = container_of(rcu, struct dev_whitelist_item, rcu); -kfree (item); -} -/* * called under devcgroup_mutex */
@@ -156,7 +148,7 @@ remove: walk->access &= ~wh->access;if (!walk->access) {list_del_rcu (&walk->list); -call_rcu (&walk->rcu, whitelist_item_free); +kfree_rcu (walk, rcu); } } }
Signature · 1 line
1.7.3.2
PATCH 76/86 scsi,rcu: convert call_rcu(fc_rport_free_rcu) to kfree_rcu()
In reply to Paul E. McKenneyFrom: Lai Jiangshan <[email protected]>
The rcu callback fc_rport_free_rcu() just calls a kfree(), so we use kfree_rcu() instead of the call_rcu(fc_rport_free_rcu).
--- drivers/scsi/libfc/fc_rport.c | 14 +------------- 1 files changed, 1 insertions(+), 13 deletions(-)
drivers/scsi/libfc/fc_rport.c +1 -13
@@ -153,18 +153,6 @@ static struct fc_rport_priv *fc_rport_create(struct fc_lport *lport, }/** -* fc_rport_free_rcu() - Free a remote port -* @rcu: The rcu_head structure inside the remote port -*/ -static void fc_rport_free_rcu (struct rcu_head *rcu) -{ -struct fc_rport_priv *rdata; - - rdata = container_of(rcu, struct fc_rport_priv, rcu); -kfree (rdata); -} - -/** * fc_rport_destroy() - Free a remote port after last reference is released * @kref: The remote port's kref */
@@ -173,7 +161,7 @@ static void fc_rport_destroy(struct kref *kref)struct fc_rport_priv *rdata; rdata = container_of(kref, struct fc_rport_priv, kref); -call_rcu (&rdata->rcu, fc_rport_free_rcu); +kfree_rcu (rdata, rcu); }/**
Signature · 1 line
1.7.3.2
PATCH 77/86 block,rcu: convert call_rcu(disk_free_ptbl_rcu_cb) to kfree_rcu()
In reply to Paul E. McKenneyFrom: Lai Jiangshan <[email protected]>
The rcu callback disk_free_ptbl_rcu_cb() just calls a kfree(), so we use kfree_rcu() instead of the call_rcu(disk_free_ptbl_rcu_cb).
--- block/genhd.c | 10 +--------- 1 files changed, 1 insertions(+), 9 deletions(-)
block/genhd.c +1 -9
@@ -1018,14 +1018,6 @@ static const struct attribute_group *disk_attr_groups[] = { NULL }; -static void disk_free_ptbl_rcu_cb (struct rcu_head *head) -{ -struct disk_part_tbl *ptbl = - container_of(head, struct disk_part_tbl, rcu_head); - -kfree (ptbl); -} -/** * disk_replace_part_tbl - replace disk->part_tbl in RCU-safe way * @disk: disk to replace part_tbl for
@@ -1046,7 +1038,7 @@ static void disk_replace_part_tbl(struct gendisk *disk,if (old_ptbl) {rcu_assign_pointer (old_ptbl->last_lookup,NULL ); -call_rcu (&old_ptbl->rcu_head, disk_free_ptbl_rcu_cb); +kfree_rcu (old_ptbl, rcu_head); } }
Signature · 1 line
1.7.3.2
PATCH 78/86 ia64,rcu: convert call_rcu(sn_irq_info_free) to kfree_rcu()
In reply to Paul E. McKenneyFrom: Lai Jiangshan <[email protected]>
The rcu callback sn_irq_info_free() just calls a kfree(), so we use kfree_rcu() instead of the call_rcu(sn_irq_info_free).
--- arch/ia64/sn/kernel/irq.c | 14 ++------------ 1 files changed, 2 insertions(+), 12 deletions(-)
arch/ia64/sn/kernel/irq.c +2 -12
@@ -112,8 +112,6 @@ static void sn_ack_irq(struct irq_data *data)irq_move_irq (data); } -static void sn_irq_info_free (struct rcu_head *head); -struct sn_irq_info *sn_retarget_vector (struct sn_irq_info *sn_irq_info,nasid_t nasid,int slice) {
@@ -177,7 +175,7 @@ struct sn_irq_info *sn_retarget_vector(struct sn_irq_info *sn_irq_info,spin_lock (&sn_irq_info_lock);list_replace_rcu (&sn_irq_info->list, &new_irq_info->list);spin_unlock (&sn_irq_info_lock); -call_rcu (&sn_irq_info->rcu, sn_irq_info_free); +kfree_rcu (sn_irq_info, rcu); finish_up:
@@ -338,14 +336,6 @@ static void unregister_intr_pda(struct sn_irq_info *sn_irq_info)rcu_read_unlock (); } -static void sn_irq_info_free (struct rcu_head *head) -{ -struct sn_irq_info *sn_irq_info; - - sn_irq_info = container_of(head, struct sn_irq_info, rcu); -kfree (sn_irq_info); -} -void sn_irq_fixup (struct pci_dev *pci_dev,struct sn_irq_info *sn_irq_info) {nasid_t nasid = sn_irq_info->irq_nasid;
@@ -399,7 +389,7 @@ void sn_irq_unfixup(struct pci_dev *pci_dev)spin_unlock (&sn_irq_info_lock);if (list_empty (sn_irq_lh[sn_irq_info->irq_irq]))free_irq_vector (sn_irq_info->irq_irq); -call_rcu (&sn_irq_info->rcu, sn_irq_info_free); +kfree_rcu (sn_irq_info, rcu);pci_dev_put (pci_dev); }
Signature · 1 line
1.7.3.2
PATCH 79/86 jbd2,rcu: convert call_rcu(free_devcache) to kfree_rcu()
In reply to Paul E. McKenneyFrom: Lai Jiangshan <[email protected]>
The rcu callback free_devcache() just calls a kfree(), so we use kfree_rcu() instead of the call_rcu(free_devcache).
--- fs/jbd2/journal.c | 7 +------ 1 files changed, 1 insertions(+), 6 deletions(-)
fs/jbd2/journal.c +1 -6
@@ -2390,11 +2390,6 @@ struct devname_cache {static struct devname_cache *devcache[1 <<CACHE_SIZE_BITS ];static DEFINE_SPINLOCK (devname_cache_lock); -static void free_devcache (struct rcu_head *rcu) -{ -kfree (rcu); -} -const char *jbd2_dev_to_name (dev_t device) {int i =hash_32 (device,CACHE_SIZE_BITS );
@@ -2423,7 +2418,7 @@ const char *jbd2_dev_to_name(dev_t device)spin_unlock (&devname_cache_lock);return ret; } -call_rcu (&devcache[i]->rcu, free_devcache); +kfree_rcu (devcache[i], rcu); } devcache[i] = new_dev; devcache[i]->device = device;
Signature · 1 line
1.7.3.2
PATCH 80/86 md,rcu: convert call_rcu(free_conf) to kfree_rcu()
In reply to Paul E. McKenneyFrom: Lai Jiangshan <[email protected]>
The rcu callback free_conf() just calls a kfree(), so we use kfree_rcu() instead of the call_rcu(free_conf).
--- drivers/md/linear.c | 8 +------- 1 files changed, 1 insertions(+), 7 deletions(-)
drivers/md/linear.c +1 -7
@@ -213,12 +213,6 @@ static int linear_run (mddev_t *mddev)return md_integrity_register (mddev); } -static void free_conf (struct rcu_head *head) -{ -linear_conf_t *conf =container_of (head, linear_conf_t, rcu); -kfree (conf); -} -static int linear_add (mddev_t *mddev,mdk_rdev_t *rdev) {/* Adding a drive to a linear array allows the array to grow.
@@ -247,7 +241,7 @@ static int linear_add(mddev_t *mddev, mdk_rdev_t *rdev)md_set_array_sectors (mddev,linear_size (mddev,0 ,0 ));set_capacity (mddev->gendisk, mddev->array_sectors);revalidate_disk (mddev->gendisk); -call_rcu (&oldconf->rcu, free_conf); +kfree_rcu (oldconf, rcu);return 0 ; }
Signature · 1 line
1.7.3.2
PATCH 81/86 security,rcu: convert call_rcu(sel_netnode_free) to kfree_rcu()
In reply to Paul E. McKenneyFrom: Lai Jiangshan <[email protected]>
The rcu callback sel_netnode_free() just calls a kfree(), so we use kfree_rcu() instead of the call_rcu(sel_netnode_free).
--- security/selinux/netnode.c | 20 ++------------------ 1 files changed, 2 insertions(+), 18 deletions(-)
security/selinux/netnode.c +2 -18
@@ -69,22 +69,6 @@ static DEFINE_SPINLOCK(sel_netnode_lock);static struct sel_netnode_bkt sel_netnode_hash[SEL_NETNODE_HASH_SIZE ];/** -* sel_netnode_free - Frees a node entry -* @p: the entry's RCU field -* -* Description: -* This function is designed to be used as a callback to the call_rcu() -* function so that memory allocated to a hash table node entry can be -* released safely. -* -*/ -static void sel_netnode_free (struct rcu_head *p) -{ - struct sel_netnode *node = container_of(p, struct sel_netnode, rcu); -kfree (node); -} - -/** * sel_netnode_hashfn_ipv4 - IPv4 hashing function for the node table * @addr: IPv4 address *
@@ -192,7 +176,7 @@ static void sel_netnode_insert(struct sel_netnode *node)rcu_dereference (sel_netnode_hash[idx].list.prev), struct sel_netnode, list);list_del_rcu (&tail->list); -call_rcu (&tail->rcu, sel_netnode_free); +kfree_rcu (tail, rcu); }else sel_netnode_hash[idx].size++; }
@@ -305,7 +289,7 @@ static void sel_netnode_flush(void)list_for_each_entry_safe (node, node_tmp, &sel_netnode_hash[idx].list, list) {list_del_rcu (&node->list); -call_rcu (&node->rcu, sel_netnode_free); +kfree_rcu (node, rcu); } sel_netnode_hash[idx].size =0 ; }
Signature · 1 line
1.7.3.2
PATCH 82/86 security,rcu: convert call_rcu(sel_netport_free) to kfree_rcu()
In reply to Paul E. McKenneyFrom: Lai Jiangshan <[email protected]>
The rcu callback sel_netport_free() just calls a kfree(), so we use kfree_rcu() instead of the call_rcu(sel_netport_free).
--- security/selinux/netport.c | 20 ++------------------ 1 files changed, 2 insertions(+), 18 deletions(-)
security/selinux/netport.c +2 -18
@@ -68,22 +68,6 @@ static DEFINE_SPINLOCK(sel_netport_lock);static struct sel_netport_bkt sel_netport_hash[SEL_NETPORT_HASH_SIZE ];/** -* sel_netport_free - Frees a port entry -* @p: the entry's RCU field -* -* Description: -* This function is designed to be used as a callback to the call_rcu() -* function so that memory allocated to a hash table port entry can be -* released safely. -* -*/ -static void sel_netport_free (struct rcu_head *p) -{ - struct sel_netport *port = container_of(p, struct sel_netport, rcu); -kfree (port); -} - -/** * sel_netport_hashfn - Hashing function for the port table * @pnum: port number *
@@ -142,7 +126,7 @@ static void sel_netport_insert(struct sel_netport *port)rcu_dereference (sel_netport_hash[idx].list.prev), struct sel_netport, list);list_del_rcu (&tail->list); -call_rcu (&tail->rcu, sel_netport_free); +kfree_rcu (tail, rcu); }else sel_netport_hash[idx].size++; }
@@ -241,7 +225,7 @@ static void sel_netport_flush(void)list_for_each_entry_safe (port, port_tmp, &sel_netport_hash[idx].list, list) {list_del_rcu (&port->list); -call_rcu (&port->rcu, sel_netport_free); +kfree_rcu (port, rcu); } sel_netport_hash[idx].size =0 ; }
Signature · 1 line
1.7.3.2
PATCH 83/86 ipc,rcu: convert call_rcu(free_un) to kfree_rcu()
In reply to Paul E. McKenneyFrom: Lai Jiangshan <[email protected]>
The rcu callback free_un() just calls a kfree(), so we use kfree_rcu() instead of the call_rcu(free_un).
--- ipc/sem.c | 10 ++-------- 1 files changed, 2 insertions(+), 8 deletions(-)
ipc/sem.c +2 -8
@@ -689,12 +689,6 @@ static int count_semzcnt (struct sem_array * sma, ushort semnum)return semzcnt; } -static void free_un (struct rcu_head *head) -{ - struct sem_undo *un = container_of(head, struct sem_undo, rcu); -kfree (un); -} -/* Free a semaphore set. freeary() is called with sem_ids.rw_mutex locked * as a writer and the spinlock for this semaphore set hold. sem_ids.rw_mutex * remains locked on exit.
@@ -714,7 +708,7 @@ static void freeary(struct ipc_namespace *ns, struct kern_ipc_perm *ipcp) un->semid =-1 ;list_del_rcu (&un->list_proc);spin_unlock (&un->ulp->lock); -call_rcu (&un->rcu, free_un); +kfree_rcu (un, rcu); }/* Wake up all pending processes and let them fail with EIDRM. */
@@ -1612,7 +1606,7 @@ void exit_sem(struct task_struct *tsk)sem_unlock (sma);wake_up_sem_queue_do (&tasks); -call_rcu (&un->rcu, free_un); +kfree_rcu (un, rcu); }kfree (ulp); }
Signature · 1 line
1.7.3.2
PATCH 84/86 ipc,rcu: convert call_rcu(ipc_immediate_free) to kfree_rcu()
In reply to Paul E. McKenneyFrom: Lai Jiangshan <[email protected]>
The rcu callback ipc_immediate_free() just calls a kfree(), so we use kfree_rcu() instead of the call_rcu(ipc_immediate_free).
--- ipc/util.c | 16 +--------------- 1 files changed, 1 insertions(+), 15 deletions(-)
ipc/util.c +1 -15
@@ -579,19 +579,6 @@ static void ipc_schedule_free(struct rcu_head *head)schedule_work (&sched->work); } -/** -* ipc_immediate_free - free ipc + rcu space -* @head: RCU callback structure that contains pointer to be freed -* -* Free from the RCU callback context. -*/ -static void ipc_immediate_free (struct rcu_head *head) -{ -struct ipc_rcu_grace *free = - container_of(head, struct ipc_rcu_grace, rcu); -kfree (free); -} -void ipc_rcu_putref (void *ptr) { if (--container_of(ptr, struct ipc_rcu_hdr, data)->refcount > 0)
@@ -601,8 +588,7 @@ void ipc_rcu_putref(void *ptr) call_rcu(&container_of(ptr, struct ipc_rcu_grace, data)->rcu, ipc_schedule_free); }else { - call_rcu(&container_of(ptr, struct ipc_rcu_grace, data)->rcu, - ipc_immediate_free); + kfree_rcu(container_of(ptr, struct ipc_rcu_grace, data), rcu); } }
Signature · 1 line
1.7.3.2
PATCH 85/86 vmalloc,rcu: convert call_rcu(rcu_free_va) to kfree_rcu()
In reply to Paul E. McKenneyFrom: Lai Jiangshan <[email protected]>
The rcu callback rcu_free_va() just calls a kfree(), so we use kfree_rcu() instead of the call_rcu(rcu_free_va).
--- mm/vmalloc.c | 9 +-------- 1 files changed, 1 insertions(+), 8 deletions(-)
mm/vmalloc.c +1 -8
@@ -452,13 +452,6 @@ overflow:return ERR_PTR (-EBUSY ); } -static void rcu_free_va (struct rcu_head *head) -{ - struct vmap_area *va = container_of(head, struct vmap_area, rcu_head); - -kfree (va); -} -static void __free_vmap_area (struct vmap_area *va) {BUG_ON (RB_EMPTY_NODE (&va->rb_node));
@@ -491,7 +484,7 @@ static void __free_vmap_area(struct vmap_area *va)if (va->va_end >VMALLOC_START && va->va_end <=VMALLOC_END ) vmap_area_pcpu_hole =max (vmap_area_pcpu_hole, va->va_end); -call_rcu (&va->rcu_head, rcu_free_va); +kfree_rcu (va, rcu_head); }/*
Signature · 1 line
1.7.3.2
PATCH 86/86 vmalloc,rcu: convert call_rcu(rcu_free_vb) to kfree_rcu()
In reply to Paul E. McKenneyFrom: Lai Jiangshan <[email protected]>
The rcu callback rcu_free_vb() just calls a kfree(), so we use kfree_rcu() instead of the call_rcu(rcu_free_vb).
--- mm/vmalloc.c | 9 +-------- 1 files changed, 1 insertions(+), 8 deletions(-)
mm/vmalloc.c +1 -8
@@ -830,13 +830,6 @@ static struct vmap_block *new_vmap_block(gfp_t gfp_mask)return vb; } -static void rcu_free_vb (struct rcu_head *head) -{ - struct vmap_block *vb = container_of(head, struct vmap_block, rcu_head); - -kfree (vb); -} -static void free_vmap_block (struct vmap_block *vb) {struct vmap_block *tmp;
@@ -849,7 +842,7 @@ static void free_vmap_block(struct vmap_block *vb)BUG_ON (tmp != vb);free_vmap_area_noflush (vb->va); -call_rcu (&vb->rcu_head, rcu_free_vb); +kfree_rcu (vb, rcu_head); }static void purge_fragmented_blocks (int cpu)
Signature · 1 line
1.7.3.2
Quoted 5 lines · Paul E. McKenney
Hello!
This patchset introduces
RCU_TREEpriority boosting, a new "fire and forget"kfree_rcu()API, numerous uses ofkfree_rcu(), plus a number of other fixes and improvements. The patches are as follows:
I replied to patches 7, 9, 17, 18, and 26 with some issues that need fixing. For all the remaining patches (including others I replied to):
Quoted 11 lines · Josh Triplett
Quoted 5 lines · Paul E. McKenney
Hello!
This patchset introduces
RCU_TREEpriority boosting, a new "fire and forget"kfree_rcu()API, numerous uses ofkfree_rcu(), plus a number of other fixes and improvements. The patches are as follows:I replied to patches 7, 9, 17, 18, and 26 with some issues that need fixing. For all the remaining patches (including others I replied to):
Reviewed-by Josh Triplett <[email protected]>
Thank you very much for your careful review and thoughtful comments!!!
Thanx, Paul
Quoted 5 lines · Paul E. McKenney
Hello!
This patchset introduces
RCU_TREEpriority boosting, a new "fire and forget"kfree_rcu()API, numerous uses ofkfree_rcu(), plus a number of other fixes and improvements. The patches are as follows:
.....
Quoted 4 lines
34-70. Use
kfree_rcu()throughout the kernel. This set of patches has
Acked-by's, so will go up -tip.71-86. Ditto, but lacking Acked-by's.
Any reason why dentry and inode freeing was not converted in this series?
Cheers,
Dave.
Signature · 2 lines
Dave Chinner [email protected]
Quoted 12 lines · Dave Chinner
Quoted 5 lines · Paul E. McKenney
Hello!
This patchset introduces
RCU_TREEpriority boosting, a new "fire and forget"kfree_rcu()API, numerous uses ofkfree_rcu(), plus a number of other fixes and improvements. The patches are as follows:.....
Quoted 3 lines
34-70. Use
kfree_rcu()throughout the kernel. This set of patches has
Acked-by's, so will go up -tip.
Quoted 6 lines
Quoted 1 line
71-86. Ditto, but lacking Acked-by's.
Any reason why dentry and inode freeing was not converted in this series?
From what I can see, they use
kmem_cache_free()rather thankfree(),
so we cannot use kfree_rcu() for them. But there are many tens of RCU callback functions that just do kmem_cache_free(), so maybe we need a kmem_cache_free_rcu().
Lai, any thoughts on this? Perhaps a global array of pointers to all the kmem_caches, so that the low-order bit can say kmem_cache_free() rather than kfree()? Then the offset can be encoded in the kmem_cache structure, allowing the ->func field of rcu_head to encode only the index of the global array of pointers to kmem_cache structures? Or would something else work better?
Thanx, Paul