Dyntick changes for v4.20/v5.0
cover Dyntick changes for v4.20/v5.0
Hello!
Now that there is only one rcu_data structure per CPU, there isn't a whole lot of point in maintaining a separate per-CPU rcu_dynticks structure. This series therefore merges the rcu_dynticks structure into the rcu_data structure.
1. Remove unused rcu_dynticks_snap() from Tiny RCU.
2. Merge rcu_dynticks structure into rcu_data structure, but
continue using the rcu_dynticks structure's fields.
3-8. Change the code to use the fields in the rcu_data structure
instead of those in the rcu_dynticks structure.
9. Remove the now-obsolete ->dynticks_fqs and ->cond_resched_completed
fields from the rcu_data structure.
10. Convert rcu_state.ofl_lock to raw_spinlock_t to make -rt feel
better, courtesy of Mike Galbraith.
Thanx, Paul
------------------------------------------------------------------------
include/linux/rcutiny.h | 6 - kernel/rcu/tree.c | 196 ++++++++++++++++++++++------------------------- kernel/rcu/tree.h | 82 +++++++------------ kernel/rcu/tree_exp.h | 8 - kernel/rcu/tree_plugin.h | 69 +++++++--------- 5 files changed, 163 insertions(+), 198 deletions(-)
PATCH 1/10 rcu: Remove unused rcu_dynticks_snap() from Tiny RCU
The rcu_dynticks_snap() function is defined in include/linux/rcutiny.h, but is no longer used by Tiny RCU. This commit therefore removes it.
--- include/linux/rcutiny.h | 6 ------ 1 file changed, 6 deletions(-)
include/linux/rcutiny.h +0 -6
@@ -27,12 +27,6 @@#include <linux/ktime.h> -struct rcu_dynticks ; -static inline int rcu_dynticks_snap (struct rcu_dynticks *rdtp) -{ -return 0 ; -} -/* Never flag non-existent other CPUs! */ static inline bool rcu_eqs_special_set (int cpu) {return false; }
Signature · 1 line
2.17.1
PATCH 2/10 rcu: Merge rcu_dynticks structure into rcu_data structure
In reply to Paul E. McKenneyNow that there is only ever one rcu_data structure per CPU, there is no need for a separate rcu_dynticks structure. This commit therefore adds the rcu_dynticks fields into the rcu_data structure in preparation for removing the rcu_dynticks structure entirely. Note that the ->dynticks field will be handled specially because there is a field by that name in both structures.
--- kernel/rcu/tree.h | 17 +++++++++++++++++ 1 file changed, 17 insertions(+)
kernel/rcu/tree.h +17 -0
@@ -212,6 +212,23 @@ struct rcu_data {/* 3) dynticks interface. */ struct rcu_dynticks *dynticks;/* Shared per-CPU dynticks state. */ int dynticks_snap;/* Per-GP tracking for dynticks. */ +long dynticks_nesting;/* Track process nesting level. */ +long dynticks_nmi_nesting;/* Track irq/NMI nesting level. */ +// atomic_t dynticks; /* Even value for idle, else odd. */ +bool rcu_need_heavy_qs;/* GP old, need heavy quiescent state. */ +bool rcu_urgent_qs;/* GP old need light quiescent state. */ +#ifdef CONFIG_RCU_FAST_NO_HZ +bool all_lazy;/* Are all CPU's CBs lazy? */ +unsigned long nonlazy_posted; +/* # times non-lazy CBs posted to CPU. */ +unsigned long nonlazy_posted_snap; +/* idle-period nonlazy_posted snapshot. */ +unsigned long last_accelerate; +/* Last jiffy CBs were accelerated. */ +unsigned long last_advance_all; +/* Last jiffy CBs were all advanced. */ +int tick_nohz_enabled_snap;/* Previously seen value from sysfs. */ +#endif /* #ifdef CONFIG_RCU_FAST_NO_HZ */ /* 4) reasons this CPU needed to be kicked by force_quiescent_state */ unsigned long dynticks_fqs;/* Kicked due to dynticks idle. */
Signature · 1 line
2.17.1
PATCH 3/10 rcu: Switch ->tick_nohz_enabled_snap to rcu_data structure
In reply to Paul E. McKenneyThis commit removes ->tick_nohz_enabled_snap from the rcu_dynticks structure and updates the code to access it from the rcu_data structure.
--- kernel/rcu/tree.h | 1 - kernel/rcu/tree_plugin.h | 10 +++++----- 2 files changed, 5 insertions(+), 6 deletions(-)
kernel/rcu/tree.h +0 -1
@@ -53,7 +53,6 @@ struct rcu_dynticks {/* Last jiffy CBs were accelerated. */ unsigned long last_advance_all;/* Last jiffy CBs were all advanced. */ -int tick_nohz_enabled_snap;/* Previously seen value from sysfs. */ #endif /* #ifdef CONFIG_RCU_FAST_NO_HZ */ };
kernel/rcu/tree_plugin.h +5 -5
@@ -1681,7 +1681,7 @@ int rcu_needs_cpu(u64 basemono, u64 *nextevt)static void rcu_prepare_for_idle (void ) {bool needwake; -struct rcu_data *rdp; +struct rcu_data *rdp =this_cpu_ptr (&rcu_data);struct rcu_dynticks *rdtp =this_cpu_ptr (&rcu_dynticks);struct rcu_node *rnp;int tne;
@@ -1692,10 +1692,10 @@ static void rcu_prepare_for_idle(void)/* Handle nohz enablement switches conservatively. */ tne =READ_ONCE (tick_nohz_active); -if (tne != rdtp->tick_nohz_enabled_snap) { +if (tne != rdp->tick_nohz_enabled_snap) {if (rcu_cpu_has_callbacks (NULL ))invoke_rcu_core ();/* force nohz to see update. */ - rdtp->tick_nohz_enabled_snap = tne; + rdp->tick_nohz_enabled_snap = tne;return ; }if (!tne)
@@ -1721,7 +1721,6 @@ static void rcu_prepare_for_idle(void)if (rdtp->last_accelerate == jiffies)return ; rdtp->last_accelerate = jiffies; - rdp =this_cpu_ptr (&rcu_data);if (rcu_segcblist_pend_cbs (&rdp->cblist)) { rnp = rdp->mynode;raw_spin_lock_rcu_node (rnp);/* irqs already disabled. */
@@ -1765,6 +1764,7 @@ static void rcu_idle_count_callbacks_posted(void)static void print_cpu_stall_fast_no_hz (char *cp,int cpu) { +struct rcu_data *rdp = &per_cpu (rcu_data, cpu);struct rcu_dynticks *rdtp = &per_cpu (rcu_dynticks, cpu);unsigned long nlpd = rdtp->nonlazy_posted - rdtp->nonlazy_posted_snap;
@@ -1772,7 +1772,7 @@ static void print_cpu_stall_fast_no_hz(char *cp, int cpu) rdtp->last_accelerate &0xffff , jiffies &0xffff ,ulong2long (nlpd), rdtp->all_lazy ?'L' :'.' , - rdtp->tick_nohz_enabled_snap ? '.' : 'D'); + rdp->tick_nohz_enabled_snap ? '.' : 'D'); }#else /* #ifdef CONFIG_RCU_FAST_NO_HZ */
Signature · 1 line
2.17.1
PATCH 4/10 rcu: Switch last accelerate/advance to rcu_data structure
In reply to Paul E. McKenneyThis commit removes ->last_accelerate and ->last_advance_all from the rcu_dynticks structure and updates the code to access them from the rcu_data structure.
--- kernel/rcu/tree.h | 4 ---- kernel/rcu/tree_plugin.h | 17 ++++++++--------- 2 files changed, 8 insertions(+), 13 deletions(-)
kernel/rcu/tree.h +0 -4
@@ -49,10 +49,6 @@ struct rcu_dynticks {/* # times non-lazy CBs posted to CPU. */ unsigned long nonlazy_posted_snap;/* idle-period nonlazy_posted snapshot. */ -unsigned long last_accelerate; -/* Last jiffy CBs were accelerated. */ -unsigned long last_advance_all; -/* Last jiffy CBs were all advanced. */ #endif /* #ifdef CONFIG_RCU_FAST_NO_HZ */ };
kernel/rcu/tree_plugin.h +8 -9
@@ -1597,16 +1597,14 @@ module_param(rcu_idle_lazy_gp_delay, int, 0644);static bool __maybe_unused rcu_try_advance_all_cbs (void ) {bool cbs_ready = false; -struct rcu_data *rdp; -struct rcu_dynticks *rdtp =this_cpu_ptr (&rcu_dynticks); +struct rcu_data *rdp =this_cpu_ptr (&rcu_data);struct rcu_node *rnp;/* Exit early if we advanced recently. */ -if (jiffies == rdtp->last_advance_all) +if (jiffies == rdp->last_advance_all)return false; - rdtp->last_advance_all = jiffies; + rdp->last_advance_all = jiffies; - rdp =this_cpu_ptr (&rcu_data); rnp = rdp->mynode;/*
@@ -1635,6 +1633,7 @@ static bool __maybe_unused rcu_try_advance_all_cbs(void)*/ int rcu_needs_cpu (u64 basemono,u64 *nextevt) { +struct rcu_data *rdp =this_cpu_ptr (&rcu_data);struct rcu_dynticks *rdtp =this_cpu_ptr (&rcu_dynticks);unsigned long dj;
@@ -1655,7 +1654,7 @@ int rcu_needs_cpu(u64 basemono, u64 *nextevt)invoke_rcu_core ();return 1 ; } - rdtp->last_accelerate = jiffies; + rdp->last_accelerate = jiffies;/* Request timer delay depending on laziness, and round. */ if (!rdtp->all_lazy) {
@@ -1718,9 +1717,9 @@ static void rcu_prepare_for_idle(void)* If we have not yet accelerated this jiffy, accelerate all * callbacks on this CPU. */ -if (rdtp->last_accelerate == jiffies) +if (rdp->last_accelerate == jiffies)return ; - rdtp->last_accelerate = jiffies; + rdp->last_accelerate = jiffies;if (rcu_segcblist_pend_cbs (&rdp->cblist)) { rnp = rdp->mynode;raw_spin_lock_rcu_node (rnp);/* irqs already disabled. */
@@ -1769,7 +1768,7 @@ static void print_cpu_stall_fast_no_hz(char *cp, int cpu)unsigned long nlpd = rdtp->nonlazy_posted - rdtp->nonlazy_posted_snap;sprintf (cp,"last_accelerate: %04lx/%04lx, nonlazy_posted: %ld, %c%c" , - rdtp->last_accelerate &0xffff , jiffies &0xffff , + rdp->last_accelerate &0xffff , jiffies &0xffff ,ulong2long (nlpd), rdtp->all_lazy ?'L' :'.' , rdp->tick_nohz_enabled_snap ?'.' :'D' );
Signature · 1 line
2.17.1
PATCH 5/10 rcu: Switch lazy counts to rcu_data structure
In reply to Paul E. McKenneyThis commit removes ->all_lazy, ->nonlazy_posted and ->nonlazy_posted_snap from the rcu_dynticks structure and updates the code to access them from the rcu_data structure.
--- kernel/rcu/tree.h | 7 ------- kernel/rcu/tree_plugin.h | 23 ++++++++++------------- 2 files changed, 10 insertions(+), 20 deletions(-)
kernel/rcu/tree.h +0 -7
@@ -43,13 +43,6 @@ struct rcu_dynticks {atomic_t dynticks;/* Even value for idle, else odd. */ bool rcu_need_heavy_qs;/* GP old, need heavy quiescent state. */ bool rcu_urgent_qs;/* GP old need light quiescent state. */ -#ifdef CONFIG_RCU_FAST_NO_HZ -bool all_lazy;/* Are all CPU's CBs lazy? */ -unsigned long nonlazy_posted; -/* # times non-lazy CBs posted to CPU. */ -unsigned long nonlazy_posted_snap; -/* idle-period nonlazy_posted snapshot. */ -#endif /* #ifdef CONFIG_RCU_FAST_NO_HZ */ };/* Communicate arguments to a workqueue handler. */
kernel/rcu/tree_plugin.h +10 -13
@@ -1634,16 +1634,15 @@ static bool __maybe_unused rcu_try_advance_all_cbs(void)int rcu_needs_cpu (u64 basemono,u64 *nextevt) {struct rcu_data *rdp =this_cpu_ptr (&rcu_data); -struct rcu_dynticks *rdtp =this_cpu_ptr (&rcu_dynticks);unsigned long dj;lockdep_assert_irqs_disabled ();/* Snapshot to detect later posting of non-lazy callback. */ - rdtp->nonlazy_posted_snap = rdtp->nonlazy_posted; + rdp->nonlazy_posted_snap = rdp->nonlazy_posted;/* If no callbacks, RCU doesn't need the CPU. */ -if (!rcu_cpu_has_callbacks (&rdtp->all_lazy)) { +if (!rcu_cpu_has_callbacks (&rdp->all_lazy)) { *nextevt =KTIME_MAX ;return 0 ; }
@@ -1657,7 +1656,7 @@ int rcu_needs_cpu(u64 basemono, u64 *nextevt) rdp->last_accelerate = jiffies;/* Request timer delay depending on laziness, and round. */ -if (!rdtp->all_lazy) { +if (!rdp->all_lazy) { dj =round_up (rcu_idle_gp_delay + jiffies, rcu_idle_gp_delay) - jiffies; }else {
@@ -1681,7 +1680,6 @@ static void rcu_prepare_for_idle(void) {bool needwake;struct rcu_data *rdp =this_cpu_ptr (&rcu_data); -struct rcu_dynticks *rdtp =this_cpu_ptr (&rcu_dynticks);struct rcu_node *rnp;int tne;
@@ -1705,10 +1703,10 @@ static void rcu_prepare_for_idle(void)* callbacks, invoke RCU core for the side-effect of recalculating * idle duration on re-entry to idle. */ -if (rdtp->all_lazy && - rdtp->nonlazy_posted != rdtp->nonlazy_posted_snap) { - rdtp->all_lazy = false; - rdtp->nonlazy_posted_snap = rdtp->nonlazy_posted; +if (rdp->all_lazy && + rdp->nonlazy_posted != rdp->nonlazy_posted_snap) { + rdp->all_lazy = false; + rdp->nonlazy_posted_snap = rdp->nonlazy_posted;invoke_rcu_core ();return ; }
@@ -1754,7 +1752,7 @@ static void rcu_cleanup_after_idle(void)*/ static void rcu_idle_count_callbacks_posted (void ) { -__this_cpu_add (rcu_dynticks.nonlazy_posted,1 ); +__this_cpu_add (rcu_data.nonlazy_posted,1 ); }#endif /* #else #if !defined(CONFIG_RCU_FAST_NO_HZ) */
@@ -1764,13 +1762,12 @@ static void rcu_idle_count_callbacks_posted(void)static void print_cpu_stall_fast_no_hz (char *cp,int cpu) {struct rcu_data *rdp = &per_cpu (rcu_data, cpu); -struct rcu_dynticks *rdtp = &per_cpu (rcu_dynticks, cpu); -unsigned long nlpd = rdtp->nonlazy_posted - rdtp->nonlazy_posted_snap; +unsigned long nlpd = rdp->nonlazy_posted - rdp->nonlazy_posted_snap;sprintf (cp,"last_accelerate: %04lx/%04lx, nonlazy_posted: %ld, %c%c" , rdp->last_accelerate &0xffff , jiffies &0xffff ,ulong2long (nlpd), - rdtp->all_lazy ?'L' :'.' , + rdp->all_lazy ?'L' :'.' , rdp->tick_nohz_enabled_snap ?'.' :'D' ); }
Signature · 1 line
2.17.1
PATCH 6/10 rcu: Switch urgent quiescent-state requests to rcu_data structure
In reply to Paul E. McKenneyThis commit removes ->rcu_need_heavy_qs and ->rcu_urgent_qs from the rcu_dynticks structure and updates the code to access them from the rcu_data structure.
--- kernel/rcu/tree.c | 12 ++++++------ kernel/rcu/tree.h | 2 -- kernel/rcu/tree_exp.h | 2 +- kernel/rcu/tree_plugin.h | 14 +++++++------- 4 files changed, 14 insertions(+), 16 deletions(-)
kernel/rcu/tree.c +6 -6
@@ -362,7 +362,7 @@ static void __maybe_unused rcu_momentary_dyntick_idle(void)struct rcu_dynticks *rdtp =this_cpu_ptr (&rcu_dynticks);int special; -raw_cpu_write (rcu_dynticks.rcu_need_heavy_qs, false); +raw_cpu_write (rcu_data.rcu_need_heavy_qs, false); special =atomic_add_return (2 *RCU_DYNTICK_CTRL_CTR , &rdtp->dynticks);/* It is illegal to call this from idle state. */ WARN_ON_ONCE (!(special &RCU_DYNTICK_CTRL_CTR ));
@@ -927,7 +927,7 @@ void rcu_request_urgent_qs_task(struct task_struct *t) cpu =task_cpu (t);if (!task_curr (t))return ;/* This task is not running on that CPU. */ -smp_store_release (per_cpu_ptr (&rcu_dynticks.rcu_urgent_qs, cpu), true); +smp_store_release (per_cpu_ptr (&rcu_data.rcu_urgent_qs, cpu), true); }#if defined(CONFIG_PROVE_RCU ) && defined(CONFIG_HOTPLUG_CPU )
@@ -1080,8 +1080,8 @@ static int rcu_implicit_dynticks_qs(struct rcu_data *rdp)* is set way high. */ jtsq =READ_ONCE (jiffies_to_sched_qs); - ruqp =per_cpu_ptr (&rcu_dynticks.rcu_urgent_qs, rdp->cpu); - rnhqp = &per_cpu (rcu_dynticks.rcu_need_heavy_qs, rdp->cpu); + ruqp =per_cpu_ptr (&rcu_data.rcu_urgent_qs, rdp->cpu); + rnhqp = &per_cpu (rcu_data.rcu_need_heavy_qs, rdp->cpu);if (!READ_ONCE (*rnhqp) && (time_after (jiffies, rcu_state.gp_start + jtsq *2 ) ||time_after (jiffies, rcu_state.jiffies_resched))) {
@@ -2498,13 +2498,13 @@ void rcu_check_callbacks(int user)trace_rcu_utilization (TPS ("Start scheduler-tick" ));raw_cpu_inc (rcu_data.ticks_this_gp);/* The load-acquire pairs with the store-release setting to true. */ -if (smp_load_acquire (this_cpu_ptr (&rcu_dynticks.rcu_urgent_qs))) { +if (smp_load_acquire (this_cpu_ptr (&rcu_data.rcu_urgent_qs))) {/* Idle and userspace execution already are quiescent states. */ if (!rcu_is_cpu_rrupt_from_idle () && !user) {set_tsk_need_resched (current);set_preempt_need_resched (); } -__this_cpu_write (rcu_dynticks.rcu_urgent_qs, false); +__this_cpu_write (rcu_data.rcu_urgent_qs, false); }rcu_flavor_check_callbacks (user);if (rcu_pending ())
kernel/rcu/tree.h +0 -2
@@ -41,8 +41,6 @@ struct rcu_dynticks {long dynticks_nesting;/* Track process nesting level. */ long dynticks_nmi_nesting;/* Track irq/NMI nesting level. */ atomic_t dynticks;/* Even value for idle, else odd. */ -bool rcu_need_heavy_qs;/* GP old, need heavy quiescent state. */ -bool rcu_urgent_qs;/* GP old need light quiescent state. */ };/* Communicate arguments to a workqueue handler. */
kernel/rcu/tree_exp.h +1 -1
@@ -780,7 +780,7 @@ static void sync_sched_exp_handler(void *unused) }__this_cpu_write (rcu_data.cpu_no_qs.b.exp, true);/* Store .exp before .rcu_urgent_qs. */ -smp_store_release (this_cpu_ptr (&rcu_dynticks.rcu_urgent_qs), true); +smp_store_release (this_cpu_ptr (&rcu_data.rcu_urgent_qs), true);set_tsk_need_resched (current);set_preempt_need_resched (); }
kernel/rcu/tree_plugin.h +7 -7
@@ -967,17 +967,17 @@ void rcu_all_qs(void) {unsigned long flags; -if (!raw_cpu_read (rcu_dynticks.rcu_urgent_qs)) +if (!raw_cpu_read (rcu_data.rcu_urgent_qs))return ;preempt_disable ();/* Load rcu_urgent_qs before other flags. */ -if (!smp_load_acquire (this_cpu_ptr (&rcu_dynticks.rcu_urgent_qs))) { +if (!smp_load_acquire (this_cpu_ptr (&rcu_data.rcu_urgent_qs))) {preempt_enable ();return ; } -this_cpu_write (rcu_dynticks.rcu_urgent_qs, false); +this_cpu_write (rcu_data.rcu_urgent_qs, false);barrier ();/* Avoid RCU read-side critical sections leaking down. */ -if (unlikely (raw_cpu_read (rcu_dynticks.rcu_need_heavy_qs))) { +if (unlikely (raw_cpu_read (rcu_data.rcu_need_heavy_qs))) {local_irq_save (flags);rcu_momentary_dyntick_idle ();local_irq_restore (flags);
@@ -997,10 +997,10 @@ void rcu_note_context_switch(bool preempt)trace_rcu_utilization (TPS ("Start context switch" ));rcu_qs ();/* Load rcu_urgent_qs before other flags. */ -if (!smp_load_acquire (this_cpu_ptr (&rcu_dynticks.rcu_urgent_qs))) +if (!smp_load_acquire (this_cpu_ptr (&rcu_data.rcu_urgent_qs))) goto out; -this_cpu_write (rcu_dynticks.rcu_urgent_qs, false); -if (unlikely (raw_cpu_read (rcu_dynticks.rcu_need_heavy_qs))) +this_cpu_write (rcu_data.rcu_urgent_qs, false); +if (unlikely (raw_cpu_read (rcu_data.rcu_need_heavy_qs)))rcu_momentary_dyntick_idle ();if (!preempt)rcu_tasks_qs (current);
Signature · 1 line
2.17.1
PATCH 7/10 rcu: Switch dyntick nesting counters to rcu_data structure
In reply to Paul E. McKenneyThis commit removes ->dynticks_nesting and ->dynticks_nmi_nesting from the rcu_dynticks structure and updates the code to access them from the rcu_data structure.
--- kernel/rcu/tree.c | 79 +++++++++++++++++++++------------------- kernel/rcu/tree.h | 2 - kernel/rcu/tree_plugin.h | 2 +- 3 files changed, 43 insertions(+), 40 deletions(-)
kernel/rcu/tree.c +42 -37
@@ -73,7 +73,10 @@/* Data structures. */ -static DEFINE_PER_CPU_SHARED_ALIGNED(struct rcu_data, rcu_data); +static DEFINE_PER_CPU_SHARED_ALIGNED(struct rcu_data, rcu_data) = { + .dynticks_nesting =1 , + .dynticks_nmi_nesting =DYNTICK_IRQ_NONIDLE , +};struct rcu_state rcu_state = { .level = { &rcu_state.node[0 ] }, .gp_state =RCU_GP_IDLE ,
@@ -210,8 +213,6 @@ void rcu_softirq_qs(void)#endif static DEFINE_PER_CPU(struct rcu_dynticks, rcu_dynticks) = { - .dynticks_nesting =1 , - .dynticks_nmi_nesting =DYNTICK_IRQ_NONIDLE , .dynticks =ATOMIC_INIT (RCU_DYNTICK_CTRL_CTR ), };
@@ -378,8 +379,8 @@ static void __maybe_unused rcu_momentary_dyntick_idle(void)*/ static int rcu_is_cpu_rrupt_from_idle (void ) { -return __this_cpu_read (rcu_dynticks.dynticks_nesting) <=0 && -__this_cpu_read (rcu_dynticks.dynticks_nmi_nesting) <=1 ; +return __this_cpu_read (rcu_data.dynticks_nesting) <=0 && +__this_cpu_read (rcu_data.dynticks_nmi_nesting) <=1 ; }#define DEFAULT_RCU_BLIMIT 10/* Maximum callbacks per rcu_do_batch. */
@@ -571,27 +572,27 @@ static struct rcu_node *rcu_get_root(void)*/ static void rcu_eqs_enter (bool user) { -struct rcu_data *rdp; +struct rcu_data *rdp =this_cpu_ptr (&rcu_data);struct rcu_dynticks *rdtp; rdtp =this_cpu_ptr (&rcu_dynticks); -WARN_ON_ONCE (rdtp->dynticks_nmi_nesting !=DYNTICK_IRQ_NONIDLE ); -WRITE_ONCE (rdtp->dynticks_nmi_nesting,0 ); +WARN_ON_ONCE (rdp->dynticks_nmi_nesting !=DYNTICK_IRQ_NONIDLE ); +WRITE_ONCE (rdp->dynticks_nmi_nesting,0 );WARN_ON_ONCE (IS_ENABLED (CONFIG_RCU_EQS_DEBUG ) && - rdtp->dynticks_nesting ==0 ); -if (rdtp->dynticks_nesting !=1 ) { - rdtp->dynticks_nesting--; + rdp->dynticks_nesting ==0 ); +if (rdp->dynticks_nesting !=1 ) { + rdp->dynticks_nesting--;return ; }lockdep_assert_irqs_disabled (); -trace_rcu_dyntick (TPS ("Start" ), rdtp->dynticks_nesting,0 , rdtp->dynticks); +trace_rcu_dyntick (TPS ("Start" ), rdp->dynticks_nesting,0 , rdtp->dynticks);WARN_ON_ONCE (IS_ENABLED (CONFIG_RCU_EQS_DEBUG ) && !user && !is_idle_task (current)); rdp =this_cpu_ptr (&rcu_data);do_nocb_deferred_wakeup (rdp);rcu_prepare_for_idle ();rcu_preempt_deferred_qs (current); -WRITE_ONCE (rdtp->dynticks_nesting,0 );/* Avoid irq-access tearing. */ +WRITE_ONCE (rdp->dynticks_nesting,0 );/* Avoid irq-access tearing. */ rcu_dynticks_eqs_enter ();rcu_dynticks_task_enter (); }
@@ -637,7 +638,7 @@ void rcu_user_enter(void)* @irq: Is this call from rcu_irq_exit? * * If we are returning from the outermost NMI handler that interrupted an -* RCU-idle period, update rdtp->dynticks and rdtp->dynticks_nmi_nesting +* RCU-idle period, update rdtp->dynticks and rdp->dynticks_nmi_nesting * to let the RCU grace-period handling know that the CPU is back to * being RCU-idle. *
@@ -646,30 +647,31 @@ void rcu_user_enter(void)*/ static __always_inline void rcu_nmi_exit_common(bool irq) { -struct rcu_dynticks *rdtp =this_cpu_ptr (&rcu_dynticks); +struct rcu_data *rdp =this_cpu_ptr (&rcu_data); +struct rcu_dynticks __maybe_unused *rdtp =this_cpu_ptr (&rcu_dynticks);/* * Check for ->dynticks_nmi_nesting underflow and bad ->dynticks. * (We are exiting an NMI handler, so RCU better be paying attention * to us!) */ -WARN_ON_ONCE (rdtp->dynticks_nmi_nesting <=0 ); +WARN_ON_ONCE (rdp->dynticks_nmi_nesting <=0 );WARN_ON_ONCE (rcu_dynticks_curr_cpu_in_eqs ());/* * If the nesting level is not 1, the CPU wasn't RCU-idle, so * leave it in non-RCU-idle state. */ -if (rdtp->dynticks_nmi_nesting !=1 ) { -trace_rcu_dyntick (TPS ("--=" ), rdtp->dynticks_nmi_nesting, rdtp->dynticks_nmi_nesting -2 , rdtp->dynticks); -WRITE_ONCE (rdtp->dynticks_nmi_nesting,/* No store tearing. */ - rdtp->dynticks_nmi_nesting -2 ); +if (rdp->dynticks_nmi_nesting !=1 ) { +trace_rcu_dyntick (TPS ("--=" ), rdp->dynticks_nmi_nesting, rdp->dynticks_nmi_nesting -2 , rdtp->dynticks); +WRITE_ONCE (rdp->dynticks_nmi_nesting,/* No store tearing. */ + rdp->dynticks_nmi_nesting -2 );return ; }/* This NMI interrupted an RCU-idle CPU, restore RCU-idleness. */ -trace_rcu_dyntick (TPS ("Startirq" ), rdtp->dynticks_nmi_nesting,0 , rdtp->dynticks); -WRITE_ONCE (rdtp->dynticks_nmi_nesting,0 );/* Avoid store tearing. */ +trace_rcu_dyntick (TPS ("Startirq" ), rdp->dynticks_nmi_nesting,0 , rdtp->dynticks); +WRITE_ONCE (rdp->dynticks_nmi_nesting,0 );/* Avoid store tearing. */ if (irq)rcu_prepare_for_idle ();
@@ -738,25 +740,27 @@ void rcu_irq_exit_irqson(void)*/ static void rcu_eqs_exit (bool user) { +struct rcu_data *rdp;struct rcu_dynticks *rdtp;long oldval;lockdep_assert_irqs_disabled (); rdtp =this_cpu_ptr (&rcu_dynticks); - oldval = rdtp->dynticks_nesting; + rdp =this_cpu_ptr (&rcu_data); + oldval = rdp->dynticks_nesting;WARN_ON_ONCE (IS_ENABLED (CONFIG_RCU_EQS_DEBUG ) && oldval <0 );if (oldval) { - rdtp->dynticks_nesting++; + rdp->dynticks_nesting++;return ; }rcu_dynticks_task_exit ();rcu_dynticks_eqs_exit ();rcu_cleanup_after_idle (); -trace_rcu_dyntick (TPS ("End" ), rdtp->dynticks_nesting,1 , rdtp->dynticks); +trace_rcu_dyntick (TPS ("End" ), rdp->dynticks_nesting,1 , rdtp->dynticks);WARN_ON_ONCE (IS_ENABLED (CONFIG_RCU_EQS_DEBUG ) && !user && !is_idle_task (current)); -WRITE_ONCE (rdtp->dynticks_nesting,1 ); -WARN_ON_ONCE (rdtp->dynticks_nmi_nesting); -WRITE_ONCE (rdtp->dynticks_nmi_nesting,DYNTICK_IRQ_NONIDLE ); +WRITE_ONCE (rdp->dynticks_nesting,1 ); +WARN_ON_ONCE (rdp->dynticks_nmi_nesting); +WRITE_ONCE (rdp->dynticks_nmi_nesting,DYNTICK_IRQ_NONIDLE ); }/**
@@ -798,7 +802,7 @@ void rcu_user_exit(void)* @irq: Is this call from rcu_irq_enter? * * If the CPU was idle from RCU's viewpoint, update rdtp->dynticks and -* rdtp->dynticks_nmi_nesting to let the RCU grace-period handling know +* rdp->dynticks_nmi_nesting to let the RCU grace-period handling know * that the CPU is active. This implementation permits nested NMIs, as * long as the nesting level does not overflow an int. (You will probably * run out of stack space first.)
@@ -808,11 +812,12 @@ void rcu_user_exit(void)*/ static __always_inline void rcu_nmi_enter_common(bool irq) { -struct rcu_dynticks *rdtp =this_cpu_ptr (&rcu_dynticks); +struct rcu_data *rdp =this_cpu_ptr (&rcu_data); +struct rcu_dynticks __maybe_unused *rdtp =this_cpu_ptr (&rcu_dynticks);long incby =2 ;/* Complain about underflow. */ -WARN_ON_ONCE (rdtp->dynticks_nmi_nesting <0 ); +WARN_ON_ONCE (rdp->dynticks_nmi_nesting <0 );/* * If idle from RCU viewpoint, atomically increment ->dynticks
@@ -835,10 +840,10 @@ static __always_inline void rcu_nmi_enter_common(bool irq) incby =1 ; }trace_rcu_dyntick (incby ==1 ?TPS ("Endirq" ) :TPS ("++=" ), - rdtp->dynticks_nmi_nesting, - rdtp->dynticks_nmi_nesting + incby, rdtp->dynticks); -WRITE_ONCE (rdtp->dynticks_nmi_nesting,/* Prevent store tearing. */ - rdtp->dynticks_nmi_nesting + incby); + rdp->dynticks_nmi_nesting, + rdp->dynticks_nmi_nesting + incby, rdtp->dynticks); +WRITE_ONCE (rdp->dynticks_nmi_nesting,/* Prevent store tearing. */ + rdp->dynticks_nmi_nesting + incby);barrier (); }
@@ -3193,7 +3198,7 @@ rcu_boot_init_percpu_data(int cpu)/* Set up local state, ensuring consistent view of global state. */ rdp->grpmask =leaf_node_cpu_bit (rdp->mynode, cpu); rdp->dynticks = &per_cpu (rcu_dynticks, cpu); -WARN_ON_ONCE (rdp->dynticks->dynticks_nesting !=1 ); +WARN_ON_ONCE (rdp->dynticks_nesting !=1 );WARN_ON_ONCE (rcu_dynticks_in_eqs (rcu_dynticks_snap (rdp->dynticks))); rdp->rcu_ofl_gp_seq = rcu_state.gp_seq; rdp->rcu_ofl_gp_flags =RCU_GP_CLEANED ;
@@ -3226,7 +3231,7 @@ int rcutree_prepare_cpu(unsigned int cpu)if (rcu_segcblist_empty (&rdp->cblist) &&/* No early-boot CBs? */ !init_nocb_callback_list (rdp))rcu_segcblist_init (&rdp->cblist);/* Re-enable callbacks. */ - rdp->dynticks->dynticks_nesting =1 ;/* CPU not up, no tearing. */ + rdp->dynticks_nesting =1 ;/* CPU not up, no tearing. */ rcu_dynticks_eqs_online ();raw_spin_unlock_rcu_node (rnp);/* irqs remain disabled. */
kernel/rcu/tree.h +0 -2
@@ -38,8 +38,6 @@* Dynticks per-CPU state. */ struct rcu_dynticks { -long dynticks_nesting;/* Track process nesting level. */ -long dynticks_nmi_nesting;/* Track irq/NMI nesting level. */ atomic_t dynticks;/* Even value for idle, else odd. */ };
kernel/rcu/tree_plugin.h +1 -1
@@ -1831,7 +1831,7 @@ static void print_cpu_stall_info(int cpu)"!." [!delta], ticks_value, ticks_title,rcu_dynticks_snap (rdtp) &0xfff , - rdtp->dynticks_nesting, rdtp->dynticks_nmi_nesting, + rdp->dynticks_nesting, rdp->dynticks_nmi_nesting, rdp->softirq_snap,kstat_softirqs_cpu (RCU_SOFTIRQ , cpu),READ_ONCE (rcu_state.n_force_qs) - rcu_state.n_force_qs_gpstart, fast_no_hz);
Signature · 1 line
2.17.1
PATCH 8/10 rcu: Switch ->dynticks to rcu_data structure, remove rcu_dynticks
In reply to Paul E. McKenneyThis commit move ->dynticks from the rcu_dynticks structure to the rcu_data structure, replacing the field of the same name. It also updates the code to access ->dynticks from the rcu_data structure and to use the rcu_data structure rather than following to now-gone ->dynticks field to the now-gone rcu_dynticks structure. While in the area, this commit also fixes up comments.
--- kernel/rcu/tree.c | 92 ++++++++++++++++++---------------------- kernel/rcu/tree.h | 35 ++++++--------- kernel/rcu/tree_exp.h | 6 +-- kernel/rcu/tree_plugin.h | 3 +- 4 files changed, 56 insertions(+), 80 deletions(-)
kernel/rcu/tree.c +41 -51
@@ -73,9 +73,20 @@/* Data structures. */ +/* +* Steal a bit from the bottom of ->dynticks for idle entry/exit +* control. Initially this is for TLB flushing. +*/ +#define RCU_DYNTICK_CTRL_MASK 0x1 +#define RCU_DYNTICK_CTRL_CTR (RCU_DYNTICK_CTRL_MASK + 1) +#ifndef rcu_eqs_special_exit +#define rcu_eqs_special_exit () do { } while (0) +#endif + static DEFINE_PER_CPU_SHARED_ALIGNED(struct rcu_data, rcu_data) = { .dynticks_nesting =1 , .dynticks_nmi_nesting =DYNTICK_IRQ_NONIDLE , + .dynticks =ATOMIC_INIT (RCU_DYNTICK_CTRL_CTR ), };struct rcu_state rcu_state = { .level = { &rcu_state.node[0 ] },
@@ -202,27 +213,13 @@ void rcu_softirq_qs(void)rcu_preempt_deferred_qs (current); } -/* -* Steal a bit from the bottom of ->dynticks for idle entry/exit -* control. Initially this is for TLB flushing. -*/ -#define RCU_DYNTICK_CTRL_MASK 0x1 -#define RCU_DYNTICK_CTRL_CTR (RCU_DYNTICK_CTRL_MASK + 1) -#ifndef rcu_eqs_special_exit -#define rcu_eqs_special_exit () do { } while (0) -#endif - -static DEFINE_PER_CPU(struct rcu_dynticks, rcu_dynticks) = { - .dynticks =ATOMIC_INIT (RCU_DYNTICK_CTRL_CTR ), -}; -/* * Record entry into an extended quiescent state. This is only to be * called when not already in an extended quiescent state. */ static void rcu_dynticks_eqs_enter (void ) { -struct rcu_dynticks *rdtp =this_cpu_ptr (&rcu_dynticks); +struct rcu_data *rdp =this_cpu_ptr (&rcu_data);int seq;/*
@@ -230,7 +227,7 @@ static void rcu_dynticks_eqs_enter(void)* critical sections, and we also must force ordering with the * next idle sojourn. */ - seq =atomic_add_return (RCU_DYNTICK_CTRL_CTR , &rdtp->dynticks); + seq =atomic_add_return (RCU_DYNTICK_CTRL_CTR , &rdp->dynticks);/* Better be in an extended quiescent state! */ WARN_ON_ONCE (IS_ENABLED (CONFIG_RCU_EQS_DEBUG ) && (seq &RCU_DYNTICK_CTRL_CTR ));
@@ -245,7 +242,7 @@ static void rcu_dynticks_eqs_enter(void)*/ static void rcu_dynticks_eqs_exit (void ) { -struct rcu_dynticks *rdtp =this_cpu_ptr (&rcu_dynticks); +struct rcu_data *rdp =this_cpu_ptr (&rcu_data);int seq;/*
@@ -253,11 +250,11 @@ static void rcu_dynticks_eqs_exit(void)* and we also must force ordering with the next RCU read-side * critical section. */ - seq =atomic_add_return (RCU_DYNTICK_CTRL_CTR , &rdtp->dynticks); + seq =atomic_add_return (RCU_DYNTICK_CTRL_CTR , &rdp->dynticks);WARN_ON_ONCE (IS_ENABLED (CONFIG_RCU_EQS_DEBUG ) && !(seq &RCU_DYNTICK_CTRL_CTR ));if (seq &RCU_DYNTICK_CTRL_MASK ) { -atomic_andnot (RCU_DYNTICK_CTRL_MASK , &rdtp->dynticks); +atomic_andnot (RCU_DYNTICK_CTRL_MASK , &rdp->dynticks);smp_mb__after_atomic ();/* _exit after clearing mask. */ /* Prefer duplicate flushes to losing a flush. */ rcu_eqs_special_exit ();
@@ -276,11 +273,11 @@ static void rcu_dynticks_eqs_exit(void)*/ static void rcu_dynticks_eqs_online (void ) { -struct rcu_dynticks *rdtp =this_cpu_ptr (&rcu_dynticks); +struct rcu_data *rdp =this_cpu_ptr (&rcu_data); -if (atomic_read (&rdtp->dynticks) &RCU_DYNTICK_CTRL_CTR ) +if (atomic_read (&rdp->dynticks) &RCU_DYNTICK_CTRL_CTR )return ; -atomic_add (RCU_DYNTICK_CTRL_CTR , &rdtp->dynticks); +atomic_add (RCU_DYNTICK_CTRL_CTR , &rdp->dynticks); }/*
@@ -290,18 +287,18 @@ static void rcu_dynticks_eqs_online(void)*/ bool rcu_dynticks_curr_cpu_in_eqs (void ) { -struct rcu_dynticks *rdtp =this_cpu_ptr (&rcu_dynticks); +struct rcu_data *rdp =this_cpu_ptr (&rcu_data); -return !(atomic_read (&rdtp->dynticks) &RCU_DYNTICK_CTRL_CTR ); +return !(atomic_read (&rdp->dynticks) &RCU_DYNTICK_CTRL_CTR ); }/* * Snapshot the ->dynticks counter with full ordering so as to allow * stable comparison of this counter with past and future snapshots. */ -int rcu_dynticks_snap (struct rcu_dynticks *rdtp) +int rcu_dynticks_snap (struct rcu_data *rdp) { -int snap =atomic_add_return (0 , &rdtp->dynticks); +int snap =atomic_add_return (0 , &rdp->dynticks);return snap & ~RCU_DYNTICK_CTRL_MASK ; }
@@ -316,13 +313,13 @@ static bool rcu_dynticks_in_eqs(int snap) }/* -* Return true if the CPU corresponding to the specified rcu_dynticks +* Return true if the CPU corresponding to the specified rcu_data * structure has spent some time in an extended quiescent state since * rcu_dynticks_snap() returned the specified snapshot. */ -static bool rcu_dynticks_in_eqs_since (struct rcu_dynticks *rdtp,int snap) +static bool rcu_dynticks_in_eqs_since (struct rcu_data *rdp,int snap) { -return snap !=rcu_dynticks_snap (rdtp); +return snap !=rcu_dynticks_snap (rdp); }/*
@@ -336,14 +333,14 @@ bool rcu_eqs_special_set(int cpu) {int old;int new; -struct rcu_dynticks *rdtp = &per_cpu (rcu_dynticks, cpu); +struct rcu_data *rdp = &per_cpu (rcu_data, cpu);do { - old =atomic_read (&rdtp->dynticks); + old =atomic_read (&rdp->dynticks);if (old &RCU_DYNTICK_CTRL_CTR )return false; new = old |RCU_DYNTICK_CTRL_MASK ; - }while (atomic_cmpxchg (&rdtp->dynticks, old, new) != old); + }while (atomic_cmpxchg (&rdp->dynticks, old, new) != old);return true; }
@@ -360,11 +357,11 @@ bool rcu_eqs_special_set(int cpu)*/ static void __maybe_unused rcu_momentary_dyntick_idle (void ) { -struct rcu_dynticks *rdtp =this_cpu_ptr (&rcu_dynticks);int special;raw_cpu_write (rcu_data.rcu_need_heavy_qs, false); - special =atomic_add_return (2 *RCU_DYNTICK_CTRL_CTR , &rdtp->dynticks); + special =atomic_add_return (2 *RCU_DYNTICK_CTRL_CTR , + &this_cpu_ptr (&rcu_data)->dynticks);/* It is illegal to call this from idle state. */ WARN_ON_ONCE (!(special &RCU_DYNTICK_CTRL_CTR ));rcu_preempt_deferred_qs (current);
@@ -573,9 +570,7 @@ static struct rcu_node *rcu_get_root(void)static void rcu_eqs_enter (bool user) {struct rcu_data *rdp =this_cpu_ptr (&rcu_data); -struct rcu_dynticks *rdtp; - rdtp =this_cpu_ptr (&rcu_dynticks);WARN_ON_ONCE (rdp->dynticks_nmi_nesting !=DYNTICK_IRQ_NONIDLE );WRITE_ONCE (rdp->dynticks_nmi_nesting,0 ); WARN_ON_ONCE(IS_ENABLED(CONFIG_RCU_EQS_DEBUG) &&
@@ -586,7 +581,7 @@ static void rcu_eqs_enter(bool user) }lockdep_assert_irqs_disabled (); -trace_rcu_dyntick (TPS ("Start" ), rdp->dynticks_nesting,0 , rdtp->dynticks); +trace_rcu_dyntick (TPS ("Start" ), rdp->dynticks_nesting,0 , rdp->dynticks);WARN_ON_ONCE (IS_ENABLED (CONFIG_RCU_EQS_DEBUG ) && !user && !is_idle_task (current)); rdp =this_cpu_ptr (&rcu_data);do_nocb_deferred_wakeup (rdp);
@@ -638,7 +633,7 @@ void rcu_user_enter(void)* @irq: Is this call from rcu_irq_exit? * * If we are returning from the outermost NMI handler that interrupted an -* RCU-idle period, update rdtp->dynticks and rdp->dynticks_nmi_nesting +* RCU-idle period, update rdp->dynticks and rdp->dynticks_nmi_nesting * to let the RCU grace-period handling know that the CPU is back to * being RCU-idle. *
@@ -648,7 +643,6 @@ void rcu_user_enter(void) static __always_inline void rcu_nmi_exit_common(bool irq) {struct rcu_data *rdp =this_cpu_ptr (&rcu_data); -struct rcu_dynticks __maybe_unused *rdtp =this_cpu_ptr (&rcu_dynticks);/* * Check for ->dynticks_nmi_nesting underflow and bad ->dynticks.
@@ -663,14 +657,14 @@ static __always_inline void rcu_nmi_exit_common(bool irq)* leave it in non-RCU-idle state. */ if (rdp->dynticks_nmi_nesting !=1 ) { -trace_rcu_dyntick (TPS ("--=" ), rdp->dynticks_nmi_nesting, rdp->dynticks_nmi_nesting -2 , rdtp->dynticks); +trace_rcu_dyntick (TPS ("--=" ), rdp->dynticks_nmi_nesting, rdp->dynticks_nmi_nesting -2 , rdp->dynticks);WRITE_ONCE (rdp->dynticks_nmi_nesting,/* No store tearing. */ rdp->dynticks_nmi_nesting -2 );return ; }/* This NMI interrupted an RCU-idle CPU, restore RCU-idleness. */ -trace_rcu_dyntick (TPS ("Startirq" ), rdp->dynticks_nmi_nesting,0 , rdtp->dynticks); +trace_rcu_dyntick (TPS ("Startirq" ), rdp->dynticks_nmi_nesting,0 , rdp->dynticks);WRITE_ONCE (rdp->dynticks_nmi_nesting,0 );/* Avoid store tearing. */ if (irq)
@@ -741,11 +735,9 @@ void rcu_irq_exit_irqson(void)static void rcu_eqs_exit (bool user) {struct rcu_data *rdp; -struct rcu_dynticks *rdtp;long oldval;lockdep_assert_irqs_disabled (); - rdtp =this_cpu_ptr (&rcu_dynticks); rdp =this_cpu_ptr (&rcu_data); oldval = rdp->dynticks_nesting;WARN_ON_ONCE (IS_ENABLED (CONFIG_RCU_EQS_DEBUG ) && oldval <0 );
@@ -756,7 +748,7 @@ static void rcu_eqs_exit(bool user)rcu_dynticks_task_exit ();rcu_dynticks_eqs_exit ();rcu_cleanup_after_idle (); -trace_rcu_dyntick (TPS ("End" ), rdp->dynticks_nesting,1 , rdtp->dynticks); +trace_rcu_dyntick (TPS ("End" ), rdp->dynticks_nesting,1 , rdp->dynticks);WARN_ON_ONCE (IS_ENABLED (CONFIG_RCU_EQS_DEBUG ) && !user && !is_idle_task (current));WRITE_ONCE (rdp->dynticks_nesting,1 );WARN_ON_ONCE (rdp->dynticks_nmi_nesting);
@@ -801,7 +793,7 @@ void rcu_user_exit(void)* rcu_nmi_enter_common - inform RCU of entry to NMI context * @irq: Is this call from rcu_irq_enter? * -* If the CPU was idle from RCU's viewpoint, update rdtp->dynticks and +* If the CPU was idle from RCU's viewpoint, update rdp->dynticks and * rdp->dynticks_nmi_nesting to let the RCU grace-period handling know * that the CPU is active. This implementation permits nested NMIs, as * long as the nesting level does not overflow an int. (You will probably
@@ -813,7 +805,6 @@ void rcu_user_exit(void) static __always_inline void rcu_nmi_enter_common(bool irq) {struct rcu_data *rdp =this_cpu_ptr (&rcu_data); -struct rcu_dynticks __maybe_unused *rdtp =this_cpu_ptr (&rcu_dynticks);long incby =2 ;/* Complain about underflow. */
@@ -841,7 +832,7 @@ static __always_inline void rcu_nmi_enter_common(bool irq) }trace_rcu_dyntick (incby ==1 ?TPS ("Endirq" ) :TPS ("++=" ), rdp->dynticks_nmi_nesting, - rdp->dynticks_nmi_nesting + incby, rdtp->dynticks); + rdp->dynticks_nmi_nesting + incby, rdp->dynticks);WRITE_ONCE (rdp->dynticks_nmi_nesting,/* Prevent store tearing. */ rdp->dynticks_nmi_nesting + incby);barrier ();
@@ -994,7 +985,7 @@ static void rcu_gpnum_ovf(struct rcu_node *rnp, struct rcu_data *rdp)*/ static int dyntick_save_progress_counter (struct rcu_data *rdp) { - rdp->dynticks_snap =rcu_dynticks_snap (rdp->dynticks); + rdp->dynticks_snap =rcu_dynticks_snap (rdp);if (rcu_dynticks_in_eqs (rdp->dynticks_snap)) {trace_rcu_fqs (rcu_state.name, rdp->gp_seq, rdp->cpu,TPS ("dti" ));rcu_gpnum_ovf (rdp->mynode, rdp);
@@ -1045,7 +1036,7 @@ static int rcu_implicit_dynticks_qs(struct rcu_data *rdp)* read-side critical section that started before the beginning * of the current RCU grace period. */ -if (rcu_dynticks_in_eqs_since (rdp->dynticks, rdp->dynticks_snap)) { +if (rcu_dynticks_in_eqs_since (rdp, rdp->dynticks_snap)) {trace_rcu_fqs (rcu_state.name, rdp->gp_seq, rdp->cpu,TPS ("dti" )); rdp->dynticks_fqs++;rcu_gpnum_ovf (rnp, rdp);
@@ -3197,9 +3188,8 @@ rcu_boot_init_percpu_data(int cpu)/* Set up local state, ensuring consistent view of global state. */ rdp->grpmask =leaf_node_cpu_bit (rdp->mynode, cpu); - rdp->dynticks = &per_cpu (rcu_dynticks, cpu);WARN_ON_ONCE (rdp->dynticks_nesting !=1 ); -WARN_ON_ONCE (rcu_dynticks_in_eqs (rcu_dynticks_snap (rdp->dynticks))); +WARN_ON_ONCE (rcu_dynticks_in_eqs (rcu_dynticks_snap (rdp))); rdp->rcu_ofl_gp_seq = rcu_state.gp_seq; rdp->rcu_ofl_gp_flags =RCU_GP_CLEANED ; rdp->rcu_onl_gp_seq = rcu_state.gp_seq;
kernel/rcu/tree.h +12 -23
@@ -34,13 +34,6 @@#include "rcu_segcblist.h" -/* -* Dynticks per-CPU state. -*/ -struct rcu_dynticks { -atomic_t dynticks;/* Even value for idle, else odd. */ -}; -/* Communicate arguments to a workqueue handler. */ struct rcu_exp_work {smp_call_func_t rew_func;
@@ -194,24 +187,20 @@ struct rcu_data {long blimit;/* Upper limit on a processed batch */ /* 3) dynticks interface. */ -struct rcu_dynticks *dynticks;/* Shared per-CPU dynticks state. */ int dynticks_snap;/* Per-GP tracking for dynticks. */ -long dynticks_nesting;/* Track process nesting level. */ -long dynticks_nmi_nesting;/* Track irq/NMI nesting level. */ -// atomic_t dynticks; /* Even value for idle, else odd. */ -bool rcu_need_heavy_qs;/* GP old, need heavy quiescent state. */ -bool rcu_urgent_qs;/* GP old need light quiescent state. */ +long dynticks_nesting;/* Track process nesting level. */ +long dynticks_nmi_nesting;/* Track irq/NMI nesting level. */ +atomic_t dynticks;/* Even value for idle, else odd. */ +bool rcu_need_heavy_qs;/* GP old, so heavy quiescent state! */ +bool rcu_urgent_qs;/* GP old need light quiescent state. */ #ifdef CONFIG_RCU_FAST_NO_HZ -bool all_lazy;/* Are all CPU's CBs lazy? */ -unsigned long nonlazy_posted; -/* # times non-lazy CBs posted to CPU. */ +bool all_lazy;/* Are all CPU's CBs lazy? */ +unsigned long nonlazy_posted;/* # times non-lazy CB posted to CPU. */ unsigned long nonlazy_posted_snap; -/* idle-period nonlazy_posted snapshot. */ -unsigned long last_accelerate; -/* Last jiffy CBs were accelerated. */ -unsigned long last_advance_all; -/* Last jiffy CBs were all advanced. */ -int tick_nohz_enabled_snap;/* Previously seen value from sysfs. */ +/* Nonlazy_posted snapshot. */ +unsigned long last_accelerate;/* Last jiffy CBs were accelerated. */ +unsigned long last_advance_all;/* Last jiffy CBs were all advanced. */ +int tick_nohz_enabled_snap;/* Previously seen value from sysfs. */ #endif /* #ifdef CONFIG_RCU_FAST_NO_HZ */ /* 4) reasons this CPU needed to be kicked by force_quiescent_state */
@@ -426,7 +415,7 @@ extern struct rcu_state rcu_bh_state;extern struct rcu_state rcu_preempt_state;#endif /* #ifdef CONFIG_PREEMPT_RCU */ -int rcu_dynticks_snap (struct rcu_dynticks *rdtp); +int rcu_dynticks_snap (struct rcu_data *rdp);#ifdef CONFIG_RCU_BOOST DECLARE_PER_CPU(unsigned int, rcu_cpu_kthread_status);
kernel/rcu/tree_exp.h +2 -4
@@ -360,14 +360,13 @@ static void sync_rcu_exp_select_node_cpus(struct work_struct *wp)for_each_leaf_node_cpu_mask (rnp, cpu, rnp->expmask) {unsigned long mask =leaf_node_cpu_bit (rnp, cpu);struct rcu_data *rdp =per_cpu_ptr (&rcu_data, cpu); -struct rcu_dynticks *rdtp =per_cpu_ptr (&rcu_dynticks, cpu);int snap;if (raw_smp_processor_id () == cpu || !(rnp->qsmaskinitnext & mask)) { mask_ofl_test |= mask; }else { - snap =rcu_dynticks_snap (rdtp); + snap =rcu_dynticks_snap (rdp);if (rcu_dynticks_in_eqs (snap)) mask_ofl_test |= mask;else
@@ -393,8 +392,7 @@ static void sync_rcu_exp_select_node_cpus(struct work_struct *wp)if (!(mask_ofl_ipi & mask))continue ; retry_ipi: -if (rcu_dynticks_in_eqs_since (rdp->dynticks, - rdp->exp_dynticks_snap)) { +if (rcu_dynticks_in_eqs_since (rdp, rdp->exp_dynticks_snap)) { mask_ofl_test |= mask;continue ; }
kernel/rcu/tree_plugin.h +1 -2
@@ -1802,7 +1802,6 @@ static void print_cpu_stall_info(int cpu)unsigned long delta;char fast_no_hz[72 ];struct rcu_data *rdp =per_cpu_ptr (&rcu_data, cpu); -struct rcu_dynticks *rdtp = rdp->dynticks;char *ticks_title;unsigned long ticks_value;
@@ -1830,7 +1829,7 @@ static void print_cpu_stall_info(int cpu) rdp->rcu_iw_pending ? (int )min (delta,9UL ) +'0' :"!." [!delta], ticks_value, ticks_title, -rcu_dynticks_snap (rdtp) &0xfff , +rcu_dynticks_snap (rdp) &0xfff , rdp->dynticks_nesting, rdp->dynticks_nmi_nesting, rdp->softirq_snap,kstat_softirqs_cpu (RCU_SOFTIRQ , cpu), READ_ONCE(rcu_state.n_force_qs) - rcu_state.n_force_qs_gpstart,
Signature · 1 line
2.17.1
PATCH 9/10 rcu: Remove obsolete ->dynticks_fqs and ->cond_resched_completed
In reply to Paul E. McKenneyThe rcu_data structure's ->dynticks_fqs is incremented but never accesses. Its ->cond_resched_completed field isn't used at all. This commit therefore removes both fields.
--- kernel/rcu/tree.c | 1 - kernel/rcu/tree.h | 12 +++--------- 2 files changed, 3 insertions(+), 10 deletions(-)
kernel/rcu/tree.c +0 -1
@@ -1038,7 +1038,6 @@ static int rcu_implicit_dynticks_qs(struct rcu_data *rdp)*/ if (rcu_dynticks_in_eqs_since (rdp, rdp->dynticks_snap)) {trace_rcu_fqs (rcu_state.name, rdp->gp_seq, rdp->cpu,TPS ("dti" )); - rdp->dynticks_fqs++;rcu_gpnum_ovf (rnp, rdp);return 1 ; }
kernel/rcu/tree.h +3 -9
@@ -203,17 +203,11 @@ struct rcu_data {int tick_nohz_enabled_snap;/* Previously seen value from sysfs. */ #endif /* #ifdef CONFIG_RCU_FAST_NO_HZ */ -/* 4) reasons this CPU needed to be kicked by force_quiescent_state */ -unsigned long dynticks_fqs;/* Kicked due to dynticks idle. */ -unsigned long cond_resched_completed; -/* Grace period that needs help */ -/* from cond_resched(). */ - -/* 5) rcu_barrier(), OOM callbacks, and expediting. */ +/* 4) rcu_barrier(), OOM callbacks, and expediting. */ struct rcu_head barrier_head;int exp_dynticks_snap;/* Double-check need for IPI. */ -/* 6) Callback offloading. */ +/* 5) Callback offloading. */ #ifdef CONFIG_RCU_NOCB_CPU struct rcu_head *nocb_head;/* CBs waiting for kthread. */ struct rcu_head **nocb_tail;
@@ -240,7 +234,7 @@ struct rcu_data {/* Leader CPU takes GP-end wakeups. */ #endif /* #ifdef CONFIG_RCU_NOCB_CPU */ -/* 7) Diagnostic data, including RCU CPU stall warnings. */ +/* 6) Diagnostic data, including RCU CPU stall warnings. */ unsigned int softirq_snap;/* Snapshot of softirq activity. */ /* ->rcu_iw* fields protected by leaf rcu_node ->lock. */ struct irq_work rcu_iw;/* Check for non-irq activity. */
Signature · 1 line
2.17.1
PATCH 10/10 rcu: Convert rcu_state.ofl_lock to raw_spinlock_t
In reply to Paul E. McKenneyFrom: Mike Galbraith <[email protected]>
1e64b15a4b10 ("rcu: Fix grace-period hangs due to race with CPU offline") added spinlock_t ofl_lock to the rcu_state structure, then takes it with preemption disabled during CPU offline, which gives the -rt patchset's sleeping spinlock heartburn.
This commit therefore converts ->ofl_lock to raw_spinlock_t.
--- kernel/rcu/tree.c | 12 ++++++------ kernel/rcu/tree.h | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-)
kernel/rcu/tree.c +6 -6
@@ -97,7 +97,7 @@ struct rcu_state rcu_state = { .abbr = RCU_ABBR, .exp_mutex = __MUTEX_INITIALIZER(rcu_state.exp_mutex), .exp_wake_mutex = __MUTEX_INITIALIZER(rcu_state.exp_wake_mutex), - .ofl_lock = __SPIN_LOCK_UNLOCKED(rcu_state.ofl_lock), + .ofl_lock = __RAW_SPIN_LOCK_UNLOCKED(rcu_state.ofl_lock), };/* Dump rcu_node combining tree at boot to verify correct setup. */
@@ -1775,13 +1775,13 @@ static bool rcu_gp_init(void)*/ rcu_state.gp_state =RCU_GP_ONOFF ;rcu_for_each_leaf_node (rnp) { -spin_lock (&rcu_state.ofl_lock); +raw_spin_lock (&rcu_state.ofl_lock);raw_spin_lock_irq_rcu_node (rnp);if (rnp->qsmaskinit == rnp->qsmaskinitnext && !rnp->wait_blkd_tasks) {/* Nothing to do on this leaf rcu_node structure. */ raw_spin_unlock_irq_rcu_node (rnp); -spin_unlock (&rcu_state.ofl_lock); +raw_spin_unlock (&rcu_state.ofl_lock);continue ; }
@@ -1817,7 +1817,7 @@ static bool rcu_gp_init(void) }raw_spin_unlock_irq_rcu_node (rnp); -spin_unlock (&rcu_state.ofl_lock); +raw_spin_unlock (&rcu_state.ofl_lock); }rcu_gp_slow (gp_preinit_delay);/* Races with CPU hotplug. */
@@ -3376,7 +3376,7 @@ void rcu_report_dead(unsigned int cpu)/* Remove outgoing CPU from mask in the leaf rcu_node structure. */ mask = rdp->grpmask; -spin_lock (&rcu_state.ofl_lock); +raw_spin_lock (&rcu_state.ofl_lock);raw_spin_lock_irqsave_rcu_node (rnp, flags);/* Enforce GP memory-order guarantee. */ rdp->rcu_ofl_gp_seq =READ_ONCE (rcu_state.gp_seq); rdp->rcu_ofl_gp_flags =READ_ONCE (rcu_state.gp_flags);
@@ -3387,7 +3387,7 @@ void rcu_report_dead(unsigned int cpu) } rnp->qsmaskinitnext &= ~mask;raw_spin_unlock_irqrestore_rcu_node (rnp, flags); -spin_unlock (&rcu_state.ofl_lock); +raw_spin_unlock (&rcu_state.ofl_lock);per_cpu (rcu_cpu_started, cpu) =0 ; }
kernel/rcu/tree.h +1 -1
@@ -343,7 +343,7 @@ struct rcu_state {const char *name;/* Name of structure. */ char abbr;/* Abbreviated name. */ -spinlock_t ofl_lock____cacheline_internodealigned_in_smp ; +raw_spinlock_t ofl_lock____cacheline_internodealigned_in_smp ;/* Synchronize offline with */ /* GP pre-initialization. */ };
Signature · 1 line
2.17.1