rcu: patches queued for 2.6.35
Subsystems (2)
cover rcu: patches queued for 2.6.35
Hello!
RFC preview of RCU patches queued for 2.6.35:
1. substitute set_need_resched for sending resched IPIs
This reduces OS jitter.
2. make dead code really dead
3. move some code from macro to function
Cleanups from Lai Jiangshan.
4. ignore offline CPUs in last non dyntick idle CPU check
Fix to my CONFIG_RCU_FAST_NO_HZ code to handle offline and non-existent CPUs, also from Lai Jiangshan.
5. fix bogus CONFIG_PROVE_LOCKING in comments to reality
6. fix now bogus rcu_scheduler_active comments
Comment fixups.
7. shrink rcutiny by making synchronize_rcu_bh be inline
Shrink TINY_RCU some more.
8. rename rcutiny rcu_ctrlblk to rcu_sched_ctrlblk
First step towards TINY_PREEMPTIBLE_RCU.
9. refactor RCU's context switch handling
Reduce the number of needless softirqs.
10. slim down rcutiny by removing rcu_scheduler_active and friends
More shrinkage for TINY_RCU
Thanx, Paul
b/include/linux/rcupdate.h | 15 ++++++----- b/include/linux/rcutiny.h | 12 ++++++++- b/include/linux/rcutree.h | 2 + b/include/linux/srcu.h | 4 +-- b/kernel/rcupdate.c | 19 -------------- b/kernel/rcutiny.c | 9 +----- b/kernel/rcutiny_plugin.h | 39 ++++++++++++++++++++++++++++++ b/kernel/rcutree.c | 10 +++++++ b/kernel/rcutree_plugin.h | 2 - b/kernel/sched.c | 2 - b/kernel/softirq.c | 2 - include/linux/rcupdate.h | 12 +++------ include/linux/rcutiny.h | 17 +++++++++++++ include/linux/rcutree.h | 4 +++ kernel/rcutiny.c | 20 ++++++++++----- kernel/rcutree.c | 58 ++++++++++++++++++++++++++++++++------------- kernel/rcutree_plugin.h | 11 +++++--- 17 files changed, 166 insertions(+), 72 deletions(-)
RFC PATCH 1/10 rcu: substitute set_need_resched for sending resched IPIs
This patch adds a check to __rcu_pending() that does a local set_need_resched() if the current CPU is holding up the current grace period and if force_quiescent_state() will be called soon. The goal is to reduce the probability that force_quiescent_state() will need to do smp_send_reschedule(), which sends an IPI and is therefore more expensive on most architectures.
--- kernel/rcutree.c | 10 ++++++++++ 1 files changed, 10 insertions(+), 0 deletions(-)
kernel/rcutree.c +10 -0
@@ -1499,6 +1499,16 @@ static int __rcu_pending(struct rcu_state *rsp, struct rcu_data *rdp)/* Is the RCU core waiting for a quiescent state from this CPU? */ if (rdp->qs_pending) { + +/* +* If force_quiescent_state() coming soon and this CPU +* needs a quiescent state, and this is either RCU-sched +* or RCU-bh, force a local reschedule. +*/ +if (!rdp->preemptable && +ULONG_CMP_LT (ACCESS_ONCE (rsp->jiffies_force_qs) -1 , + jiffies)) +set_need_resched (); rdp->n_rp_qs_pending++;return 1 ; }
Signature · 1 line
1.7.0
RFC PATCH 2/10 rcu: make dead code really dead
In reply to Paul E. McKenneyFrom: Lai Jiangshan <[email protected]>
cleanup: make dead code really dead
--- kernel/rcutree.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-)
kernel/rcutree.c +2 -2
@@ -1236,11 +1236,11 @@ static void force_quiescent_state(struct rcu_state *rsp, int relaxed)break ;/* grace period idle or initializing, ignore. */ case RCU_SAVE_DYNTICK : - -raw_spin_unlock (&rnp->lock);/* irqs remain disabled */ if (RCU_SIGNAL_INIT !=RCU_SAVE_DYNTICK )break ;/* So gcc recognizes the dead code. */ +raw_spin_unlock (&rnp->lock);/* irqs remain disabled */ +/* Record dyntick-idle state. */ force_qs_rnp (rsp, dyntick_save_progress_counter);raw_spin_lock (&rnp->lock);/* irqs already disabled */
Signature · 1 line
1.7.0
Re: [PATCH RFC tip/core/rcu 02/10] rcu: make dead code really dead
Quoted 3 lines · * Paul E. McKenney ([email protected]) wrote:
From: Lai Jiangshan <[email protected]>
cleanup: make dead code really dead
Is it just me or this spinlock change is more than just a cleanup ? Or maybe it just needs a much more descriptive changelog.
Thanks,
Mathieu
Quoted 28 lines
Signed-off-by Lai Jiangshan <[email protected]>Signed-off-by Paul E. McKenney <[email protected]>--- kernel/rcutree.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-)kernel/rcutree.c +2
-2@@ -1236,11 +1236,11 @@ static void force_quiescent_state(struct rcu_state *rsp, int relaxed)break ;/* grace period idle or initializing, ignore. */ case RCU_SAVE_DYNTICK : - -raw_spin_unlock (&rnp->lock);/* irqs remain disabled */ if (RCU_SIGNAL_INIT !=RCU_SAVE_DYNTICK )break ;/* So gcc recognizes the dead code. */ +raw_spin_unlock (&rnp->lock);/* irqs remain disabled */ +/* Record dyntick-idle state. */ force_qs_rnp (rsp, dyntick_save_progress_counter);raw_spin_lock (&rnp->lock);/* irqs already disabled */ Signature · 1 line
1.7.0
Signature · 4 lines
Mathieu Desnoyers Operating System Efficiency R&D Consultant EfficiOS Inc. http://www.efficios.com
Re: [PATCH RFC tip/core/rcu 02/10] rcu: make dead code really dead
Quoted 7 lines · Mathieu Desnoyers
Quoted 3 lines · * Paul E. McKenney ([email protected]) wrote:
From: Lai Jiangshan <[email protected]>
cleanup: make dead code really dead
Is it just me or this spinlock change is more than just a cleanup ? Or maybe it just needs a much more descriptive changelog.
Just a cleanup. In the case where the "break" could be executed, control will never reach the RCU_SAVE_DYNTICK leg of the switch statement.
That said, yes, if control -could- reach the RCU_SAVE_DYNTICK when this "break" statement was executed, we would have had a locking problem. But as it is, this change just makes the dead code really all be dead so that gcc knows not to produce the corresponding binary.
Thanx, Paul
Quoted 38 lines
Thanks,
Mathieu
Quoted 28 lines
Signed-off-by Lai Jiangshan <[email protected]>Signed-off-by Paul E. McKenney <[email protected]>--- kernel/rcutree.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-)kernel/rcutree.c +2
-2@@ -1236,11 +1236,11 @@ static void force_quiescent_state(struct rcu_state *rsp, int relaxed)break ;/* grace period idle or initializing, ignore. */ case RCU_SAVE_DYNTICK : - -raw_spin_unlock (&rnp->lock);/* irqs remain disabled */ if (RCU_SIGNAL_INIT !=RCU_SAVE_DYNTICK )break ;/* So gcc recognizes the dead code. */ +raw_spin_unlock (&rnp->lock);/* irqs remain disabled */ +/* Record dyntick-idle state. */ force_qs_rnp (rsp, dyntick_save_progress_counter);raw_spin_lock (&rnp->lock);/* irqs already disabled */ Signature · 1 line
1.7.0Signature · 4 lines
Mathieu Desnoyers Operating System Efficiency R&D Consultant EfficiOS Inc. http://www.efficios.com
RFC PATCH 3/10 rcu: move some code from macro to function
In reply to Paul E. McKenneyFrom: Lai Jiangshan <[email protected]>
Shrink the RCU_INIT_FLAVOR() macro by moving all but the initialization of the ->rda[] array to rcu_init_one(). The call to rcu_init_one() can then be moved to the end of the RCU_INIT_FLAVOR() macro, which is required because rcu_boot_init_percpu_data(), which is now called from rcu_init_one(), depends on the initialization of the ->rda[] array.
--- kernel/rcutree.c | 18 +++++++++--------- 1 files changed, 9 insertions(+), 9 deletions(-)
kernel/rcutree.c +9 -9
@@ -1859,6 +1859,14 @@ static void __init rcu_init_one(struct rcu_state *rsp)INIT_LIST_HEAD (&rnp->blocked_tasks[3 ]); } } + + rnp = rsp->level[NUM_RCU_LVLS -1 ]; +for_each_possible_cpu (i) { +if (i > rnp->grphi) + rnp++; + rsp->rda[i]->mynode = rnp; +rcu_boot_init_percpu_data (i, rsp); + } }/*
@@ -1869,19 +1877,11 @@ static void __init rcu_init_one(struct rcu_state *rsp)#define RCU_INIT_FLAVOR (rsp, rcu_data) \ do { \ int i; \ - int j; \ - struct rcu_node *rnp; \ \ - rcu_init_one(rsp); \ - rnp = (rsp)->level[NUM_RCU_LVLS - 1]; \ - j = 0; \ for_each_possible_cpu(i) { \ - if (i > rnp[j].grphi) \ - j++; \ - per_cpu(rcu_data, i).mynode = &rnp[j]; \ (rsp)->rda[i] = &per_cpu(rcu_data, i); \ - rcu_boot_init_percpu_data(i, rsp); \ } \ + rcu_init_one(rsp); \ } while (0)void __init rcu_init (void )
Signature · 1 line
1.7.0
RFC PATCH 4/10 rcu: ignore offline CPUs in last non-dyntick-idle CPU check
In reply to Paul E. McKenneyFrom: Lai Jiangshan <[email protected]>
Offline CPUs are not in nohz_cpu_mask, but can be ignored when checking for the last non-dyntick-idle CPU. This patch therefore only checks online CPUs for not being dyntick idle, allowing fast entry into full-system dyntick-idle state even when there are some offline CPUs.
--- kernel/rcutree_plugin.h | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
kernel/rcutree_plugin.h +1 -1
@@ -1016,7 +1016,7 @@ int rcu_needs_cpu(int cpu)/* Don't bother unless we are the last non-dyntick-idle CPU. */ for_each_cpu_not (thatcpu, nohz_cpu_mask) -if (thatcpu != cpu) { +if (cpu_online (thatcpu) && thatcpu != cpu) {per_cpu (rcu_dyntick_drain, cpu) =0 ;per_cpu (rcu_dyntick_holdoff, cpu) = jiffies -1 ;return rcu_needs_cpu_quick_check (cpu);
Signature · 1 line
1.7.0
RFC PATCH 5/10 rcu: Fix bogus CONFIG_PROVE_LOCKING in comments to reflect reality.
In reply to Paul E. McKenneyIt is CONFIG_DEBUG_LOCK_ALLOC rather than CONFIG_PROVE_LOCKING, so fix it.
--- include/linux/rcupdate.h | 15 ++++++++------- include/linux/srcu.h | 4 ++-- 2 files changed, 10 insertions(+), 9 deletions(-)
include/linux/rcupdate.h +8 -7
@@ -109,8 +109,8 @@ static inline int debug_lockdep_rcu_enabled(void)/** * rcu_read_lock_held - might we be in RCU read-side critical section? * -* If CONFIG_PROVE_LOCKING is selected and enabled, returns nonzero iff in -* an RCU read-side critical section. In absence of CONFIG_PROVE_LOCKING, +* If CONFIG_DEBUG_LOCK_ALLOC is selected, returns nonzero iff in an RCU +* read-side critical section. In absence of CONFIG_DEBUG_LOCK_ALLOC, * this assumes we are in an RCU read-side critical section unless it can * prove otherwise. *
@@ -132,11 +132,12 @@ extern int rcu_read_lock_bh_held(void);/** * rcu_read_lock_sched_held - might we be in RCU-sched read-side critical section? * -* If CONFIG_PROVE_LOCKING is selected and enabled, returns nonzero iff in an -* RCU-sched read-side critical section. In absence of CONFIG_PROVE_LOCKING, -* this assumes we are in an RCU-sched read-side critical section unless it -* can prove otherwise. Note that disabling of preemption (including -* disabling irqs) counts as an RCU-sched read-side critical section. +* If CONFIG_DEBUG_LOCK_ALLOC is selected, returns nonzero iff in an +* RCU-sched read-side critical section. In absence of +* CONFIG_DEBUG_LOCK_ALLOC, this assumes we are in an RCU-sched read-side +* critical section unless it can prove otherwise. Note that disabling +* of preemption (including disabling irqs) counts as an RCU-sched +* read-side critical section. * * Check rcu_scheduler_active to prevent false positives during boot. */
include/linux/srcu.h +2 -2
@@ -84,8 +84,8 @@ long srcu_batches_completed(struct srcu_struct *sp);/** * srcu_read_lock_held - might we be in SRCU read-side critical section? * -* If CONFIG_PROVE_LOCKING is selected and enabled, returns nonzero iff in -* an SRCU read-side critical section. In absence of CONFIG_PROVE_LOCKING, +* If CONFIG_DEBUG_LOCK_ALLOC is selected, returns nonzero iff in an SRCU +* read-side critical section. In absence of CONFIG_DEBUG_LOCK_ALLOC, * this assumes we are in an SRCU read-side critical section unless it can * prove otherwise. */
Signature · 1 line
1.7.0
RFC PATCH 6/10 rcu: fix now-bogus rcu_scheduler_active comments.
In reply to Paul E. McKenneyThe rcu_scheduler_active check has been wrapped into the new debug_lockdep_rcu_enabled() function, so update the comments to reflect this new reality.
--- include/linux/rcupdate.h | 6 ++++-- 1 files changed, 4 insertions(+), 2 deletions(-)
include/linux/rcupdate.h +4 -2
@@ -114,7 +114,8 @@ static inline int debug_lockdep_rcu_enabled(void)* this assumes we are in an RCU read-side critical section unless it can * prove otherwise. * -* Check rcu_scheduler_active to prevent false positives during boot. +* Check debug_lockdep_rcu_enabled() to prevent false positives during boot +* and while lockdep is disabled. */ static inline int rcu_read_lock_held (void ) {
@@ -139,7 +140,8 @@ extern int rcu_read_lock_bh_held(void);* of preemption (including disabling irqs) counts as an RCU-sched * read-side critical section. * -* Check rcu_scheduler_active to prevent false positives during boot. +* Check debug_lockdep_rcu_enabled() to prevent false positives during boot +* and while lockdep is disabled. */ #ifdef CONFIG_PREEMPT static inline int rcu_read_lock_sched_held (void )
Signature · 1 line
1.7.0
RFC PATCH 7/10 rcu: shrink rcutiny by making synchronize_rcu_bh() be inline
In reply to Paul E. McKenneyBecause synchronize_rcu_bh() is identical to synchronize_sched(), make the former a static inline invoking the latter, saving the overhead of an EXPORT_SYMBOL_GPL() and the duplicate code.
--- include/linux/rcupdate.h | 2 -- include/linux/rcutiny.h | 12 +++++++++++- include/linux/rcutree.h | 2 ++ kernel/rcutiny.c | 9 ++------- 4 files changed, 15 insertions(+), 10 deletions(-)
include/linux/rcupdate.h +0 -2
@@ -56,8 +56,6 @@ struct rcu_head { };/* Exported common interfaces */ -extern void synchronize_rcu_bh (void ); -extern void synchronize_sched (void );extern void rcu_barrier (void );extern void rcu_barrier_bh (void );extern void rcu_barrier_sched (void );
include/linux/rcutiny.h +11 -1
@@ -74,7 +74,17 @@ static inline void rcu_sched_force_quiescent_state(void) { } -#define synchronize_rcu synchronize_sched +extern void synchronize_sched (void ); + +static inline void synchronize_rcu (void ) +{ +synchronize_sched (); +} + +static inline void synchronize_rcu_bh (void ) +{ +synchronize_sched (); +}static inline void synchronize_rcu_expedited (void ) {
include/linux/rcutree.h +2 -0
@@ -86,6 +86,8 @@ static inline void __rcu_read_unlock_bh(void)extern void call_rcu_sched (struct rcu_head *head,void (*func)(struct rcu_head *rcu)); +extern void synchronize_rcu_bh (void ); +extern void synchronize_sched (void );extern void synchronize_rcu_expedited (void );static inline void synchronize_rcu_bh_expedited (void )
kernel/rcutiny.c +2 -7
@@ -187,7 +187,8 @@ static void rcu_process_callbacks(struct softirq_action *unused)* * Cool, huh? (Due to Josh Triplett.) * -* But we want to make this a static inline later. +* But we want to make this a static inline later. The cond_resched() +* currently makes this problematic. */ void synchronize_sched (void ) {
@@ -195,12 +196,6 @@ void synchronize_sched(void) }EXPORT_SYMBOL_GPL (synchronize_sched); -void synchronize_rcu_bh (void ) -{ -synchronize_sched (); -} -EXPORT_SYMBOL_GPL (synchronize_rcu_bh); -/* * Helper function for call_rcu() and call_rcu_bh(). */
Signature · 1 line
1.7.0
RFC PATCH 8/10 rcu: rename rcutiny rcu_ctrlblk to rcu_sched_ctrlblk
In reply to Paul E. McKenneyMake naming line up in preparation for CONFIG_TINY_PREEMPT_RCU.
--- kernel/rcutiny.c | 13 +++++++------ 1 files changed, 7 insertions(+), 6 deletions(-)
kernel/rcutiny.c +7 -6
@@ -44,9 +44,9 @@ struct rcu_ctrlblk { };/* Definition for rcupdate control block. */ -static struct rcu_ctrlblk rcu_ctrlblk = { - .donetail = &rcu_ctrlblk.rcucblist, - .curtail = &rcu_ctrlblk.rcucblist, +static struct rcu_ctrlblk rcu_sched_ctrlblk = { + .donetail = &rcu_sched_ctrlblk.rcucblist, + .curtail = &rcu_sched_ctrlblk.rcucblist, };static struct rcu_ctrlblk rcu_bh_ctrlblk = {
@@ -108,7 +108,8 @@ static int rcu_qsctr_help(struct rcu_ctrlblk *rcp)*/ void rcu_sched_qs (int cpu) { -if (rcu_qsctr_help (&rcu_ctrlblk) +rcu_qsctr_help (&rcu_bh_ctrlblk)) +if (rcu_qsctr_help (&rcu_sched_ctrlblk) + +rcu_qsctr_help (&rcu_bh_ctrlblk))raise_softirq (RCU_SOFTIRQ ); }
@@ -173,7 +174,7 @@ static void __rcu_process_callbacks(struct rcu_ctrlblk *rcp)*/ static void rcu_process_callbacks (struct softirq_action *unused) { -__rcu_process_callbacks (&rcu_ctrlblk); +__rcu_process_callbacks (&rcu_sched_ctrlblk);__rcu_process_callbacks (&rcu_bh_ctrlblk); }
@@ -221,7 +222,7 @@ static void __call_rcu(struct rcu_head *head,*/ void call_rcu (struct rcu_head *head,void (*func)(struct rcu_head *rcu)) { -__call_rcu (head, func, &rcu_ctrlblk); +__call_rcu (head, func, &rcu_sched_ctrlblk); }EXPORT_SYMBOL_GPL (call_rcu);
Signature · 1 line
1.7.0
RFC PATCH 9/10 rcu: refactor RCU's context-switch handling
In reply to Paul E. McKenneyThe addition of preemptible RCU to treercu resulted in a bit of confusion and inefficiency surrounding the handling of context switches for RCU-sched and for RCU-preempt. For RCU-sched, a context switch is a quiescent state, pure and simple, just like it always has been. For RCU-preempt, a context switch is in no way a quiescent state, but special handling is required when a task blocks in an RCU read-side critical section.
However, the callout from the scheduler and the outer loop in ksoftirqd still calls something named rcu_sched_qs(), whose name is no longer accurate. Furthermore, when rcu_check_callbacks() notes an RCU-sched quiescent state, it ends up unnecessarily (though harmlessly, aside from the performance hit) enqueuing the current task if it happens to be running in an RCU-preempt read-side critical section. This not only increases the maximum latency of scheduler_tick(), it also needlessly increases the overhead of the next outermost rcu_read_unlock() invocation.
This patch addresses this situation by separating the notion of RCU's context-switch handling from that of RCU-sched's quiescent states. The context-switch handling is covered by rcu_note_context_switch() in general and by rcu_preempt_note_context_switch() for preemptible RCU. This permits rcu_sched_qs() to handle quiescent states and only quiescent states. It also reduces the maximum latency of scheduler_tick(), though probably by much less than a microsecond. Finally, it means that tasks within preemptible-RCU read-side critical sections avoid incurring the overhead of queuing unless there really is a context switch.
--- include/linux/rcutiny.h | 4 ++++ include/linux/rcutree.h | 1 + kernel/rcutree.c | 17 ++++++++++++----- kernel/rcutree_plugin.h | 11 +++++++---- kernel/sched.c | 2 +- kernel/softirq.c | 2 +- 6 files changed, 26 insertions(+), 11 deletions(-)
include/linux/rcutiny.h +4 -0
@@ -29,6 +29,10 @@void rcu_sched_qs (int cpu);void rcu_bh_qs (int cpu); +static inline void rcu_note_context_switch (int cpu) +{ +rcu_sched_qs (cpu); +}#define __rcu_read_lock () preempt_disable()#define __rcu_read_unlock () preempt_enable()
include/linux/rcutree.h +1 -0
@@ -34,6 +34,7 @@ struct notifier_block;extern void rcu_sched_qs (int cpu);extern void rcu_bh_qs (int cpu); +extern void rcu_note_context_switch (int cpu);extern int rcu_needs_cpu (int cpu);extern int rcu_expedited_torture_stats (char *page);
kernel/rcutree.c +12 -5
@@ -97,25 +97,32 @@ static int rcu_gp_in_progress(struct rcu_state *rsp)*/ void rcu_sched_qs (int cpu) { -struct rcu_data *rdp; +struct rcu_data *rdp = &per_cpu (rcu_sched_data, cpu); - rdp = &per_cpu (rcu_sched_data, cpu); rdp->passed_quiesc_completed = rdp->gpnum -1 ;barrier (); rdp->passed_quiesc =1 ; -rcu_preempt_note_context_switch (cpu); }void rcu_bh_qs (int cpu) { -struct rcu_data *rdp; +struct rcu_data *rdp = &per_cpu (rcu_bh_data, cpu); - rdp = &per_cpu (rcu_bh_data, cpu); rdp->passed_quiesc_completed = rdp->gpnum -1 ;barrier (); rdp->passed_quiesc =1 ; } +/* +* Note a context switch. This is a quiescent state for RCU-sched, +* and requires special handling for preemptible RCU. +*/ +void rcu_note_context_switch (int cpu) +{ +rcu_sched_qs (cpu); +rcu_preempt_note_context_switch (cpu); +} +#ifdef CONFIG_NO_HZ DEFINE_PER_CPU(struct rcu_dynticks, rcu_dynticks) = { .dynticks_nesting = 1,
kernel/rcutree_plugin.h +7 -4
@@ -75,13 +75,19 @@ EXPORT_SYMBOL_GPL(rcu_force_quiescent_state);* that this just means that the task currently running on the CPU is * not in a quiescent state. There might be any number of tasks blocked * while in an RCU read-side critical section. +* +* Unlike the other rcu_*_qs() functions, callers to this function +* must disable irqs in order to protect the assignment to +* ->rcu_read_unlock_special. */ static void rcu_preempt_qs (int cpu) {struct rcu_data *rdp = &per_cpu (rcu_preempt_data, cpu); + rdp->passed_quiesc_completed = rdp->gpnum -1 ;barrier (); rdp->passed_quiesc =1 ; + current->rcu_read_unlock_special &= ~RCU_READ_UNLOCK_NEED_QS ; }/*
@@ -144,9 +150,8 @@ static void rcu_preempt_note_context_switch(int cpu)* grace period, then the fact that the task has been enqueued * means that we continue to block the current grace period. */ -rcu_preempt_qs (cpu);local_irq_save (flags); - t->rcu_read_unlock_special &= ~RCU_READ_UNLOCK_NEED_QS ; +rcu_preempt_qs (cpu);local_irq_restore (flags); }
@@ -236,7 +241,6 @@ static void rcu_read_unlock_special(struct task_struct *t)*/ special = t->rcu_read_unlock_special;if (special &RCU_READ_UNLOCK_NEED_QS ) { - t->rcu_read_unlock_special &= ~RCU_READ_UNLOCK_NEED_QS ;rcu_preempt_qs (smp_processor_id ()); }
@@ -473,7 +477,6 @@ static void rcu_preempt_check_callbacks(int cpu)struct task_struct *t = current;if (t->rcu_read_lock_nesting ==0 ) { - t->rcu_read_unlock_special &= ~RCU_READ_UNLOCK_NEED_QS ;rcu_preempt_qs (cpu);return ; }
kernel/sched.c +1 -1
@@ -3695,7 +3695,7 @@ need_resched:preempt_disable (); cpu =smp_processor_id (); rq =cpu_rq (cpu); -rcu_sched_qs (cpu); +rcu_note_context_switch (cpu); prev = rq->curr; switch_count = &prev->nivcsw;
kernel/softirq.c +1 -1
@@ -716,7 +716,7 @@ static int run_ksoftirqd(void * __bind_cpu)preempt_enable_no_resched ();cond_resched ();preempt_disable (); -rcu_sched_qs ((long )__bind_cpu); +rcu_note_context_switch ((long )__bind_cpu); }preempt_enable ();set_current_state (TASK_INTERRUPTIBLE );
Signature · 1 line
1.7.0
RFC PATCH 10/10 rcu: slim down rcutiny by removing rcu_scheduler_active and friends
In reply to Paul E. McKenneyTINY_RCU does not need rcu_scheduler_active unless CONFIG_DEBUG_LOCK_ALLOC. So conditionally compile rcu_scheduler_active in order to slim down rcutiny a bit more. Also gets rid of an EXPORT_SYMBOL_GPL, which is responsible for most of the slimming.
--- include/linux/rcupdate.h | 4 +--- include/linux/rcutiny.h | 13 +++++++++++++ include/linux/rcutree.h | 3 +++ kernel/rcupdate.c | 19 ------------------- kernel/rcutiny.c | 7 +++++++ kernel/rcutiny_plugin.h | 39 +++++++++++++++++++++++++++++++++++++++ kernel/rcutree.c | 19 +++++++++++++++++++ 7 files changed, 82 insertions(+), 22 deletions(-) create mode 100644 kernel/rcutiny_plugin.h
include/linux/rcupdate.h +1 -3
@@ -64,8 +64,6 @@ extern int sched_expedited_torture_stats(char *page);/* Internal to kernel */ extern void rcu_init (void ); -extern int rcu_scheduler_active; -extern void rcu_scheduler_starting (void );#if defined(CONFIG_TREE_RCU ) || defined(CONFIG_TREE_PREEMPT_RCU )#include <linux/rcutree.h>
@@ -181,7 +179,7 @@ static inline int rcu_read_lock_bh_held(void)#ifdef CONFIG_PREEMPT static inline int rcu_read_lock_sched_held (void ) { -return !rcu_scheduler_active ||preempt_count () !=0 ||irqs_disabled (); +return preempt_count () !=0 ||irqs_disabled (); }#else /* #ifdef CONFIG_PREEMPT */ static inline int rcu_read_lock_sched_held (void )
include/linux/rcutiny.h +13 -0
@@ -128,4 +128,17 @@ static inline int rcu_preempt_depth(void) return 0; } +#ifdef CONFIG_DEBUG_LOCK_ALLOC + +extern int rcu_scheduler_active__read_mostly ; +extern void rcu_scheduler_starting (void ); + +#else /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */ + +static inline void rcu_scheduler_starting (void ) +{ +} + +#endif /* #else #ifdef CONFIG_DEBUG_LOCK_ALLOC */ +#endif /* __LINUX_RCUTINY_H */
include/linux/rcutree.h +3 -0
@@ -123,4 +123,7 @@ static inline int rcu_blocking_is_gp(void) return num_online_cpus() == 1; } +extern void rcu_scheduler_starting (void ); +extern int rcu_scheduler_active__read_mostly ; +#endif /* __LINUX_RCUTREE_H */
kernel/rcupdate.c +0 -19
@@ -44,7 +44,6 @@#include <linux/cpu.h> #include <linux/mutex.h> #include <linux/module.h> -#include <linux/kernel_stat.h> #include <linux/hardirq.h> #ifdef CONFIG_DEBUG_LOCK_ALLOC
@@ -64,9 +63,6 @@ struct lockdep_map rcu_sched_lock_map =EXPORT_SYMBOL_GPL (rcu_sched_lock_map);#endif -int rcu_scheduler_active__read_mostly ; -EXPORT_SYMBOL_GPL (rcu_scheduler_active); -#ifdef CONFIG_DEBUG_LOCK_ALLOC /**
@@ -90,21 +86,6 @@ EXPORT_SYMBOL_GPL(rcu_read_lock_bh_held);#endif /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */ /* -* This function is invoked towards the end of the scheduler's initialization -* process. Before this is called, the idle task might contain -* RCU read-side critical sections (during which time, this idle -* task is booting the system). After this function is called, the -* idle tasks are prohibited from containing RCU read-side critical -* sections. -*/ -void rcu_scheduler_starting (void ) -{ -WARN_ON (num_online_cpus () !=1 ); -WARN_ON (nr_context_switches () >0 ); - rcu_scheduler_active =1 ; -} - -/* * Awaken the corresponding synchronize_rcu() instance now that a * grace period has elapsed. */
kernel/rcutiny.c +7 -0
@@ -54,6 +54,11 @@ static struct rcu_ctrlblk rcu_bh_ctrlblk = { .curtail = &rcu_bh_ctrlblk.rcucblist, }; +#ifdef CONFIG_DEBUG_LOCK_ALLOC +int rcu_scheduler_active__read_mostly ; +EXPORT_SYMBOL_GPL (rcu_scheduler_active); +#endif /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */ +#ifdef CONFIG_NO_HZ static long rcu_dynticks_nesting =1 ;
@@ -276,3 +281,5 @@ void __init rcu_init(void) {open_softirq (RCU_SOFTIRQ , rcu_process_callbacks); } + +#include "rcutiny_plugin.h"
kernel/rcutiny_plugin.h new file +39 -0
@@ -0,0 +1,39 @@ +/* +* Read-Copy Update mechanism for mutual exclusion (tree-based version) +* Internal non-public definitions that provide either classic +* or preemptable semantics. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +* Copyright IBM Corporation, 2009 +* +* Author: Paul E. McKenney <[email protected]> +*/ + +#ifdef CONFIG_DEBUG_LOCK_ALLOC + +#include <linux/kernel_stat.h> + +/* +* During boot, we forgive RCU lockdep issues. After this function is +* invoked, we start taking RCU lockdep issues seriously. +*/ +void rcu_scheduler_starting (void ) +{ +WARN_ON (nr_context_switches () >0 ); + rcu_scheduler_active =1 ; +} + +#endif /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */
kernel/rcutree.c +19 -0
@@ -46,6 +46,7 @@#include <linux/cpu.h> #include <linux/mutex.h> #include <linux/time.h> +#include <linux/kernel_stat.h> #include "rcutree.h"
@@ -80,6 +81,9 @@ DEFINE_PER_CPU(struct rcu_data, rcu_sched_data);struct rcu_state rcu_bh_state =RCU_STATE_INITIALIZER (rcu_bh_state); DEFINE_PER_CPU(struct rcu_data, rcu_bh_data); +int rcu_scheduler_active__read_mostly ; +EXPORT_SYMBOL_GPL (rcu_scheduler_active); +/* * 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
@@ -1784,6 +1788,21 @@ static int __cpuinit rcu_cpu_notify(struct notifier_block *self, }/* +* This function is invoked towards the end of the scheduler's initialization +* process. Before this is called, the idle task might contain +* RCU read-side critical sections (during which time, this idle +* task is booting the system). After this function is called, the +* idle tasks are prohibited from containing RCU read-side critical +* sections. This function also enables RCU lockdep checking. +*/ +void rcu_scheduler_starting (void ) +{ +WARN_ON (num_online_cpus () !=1 ); +WARN_ON (nr_context_switches () >0 ); + rcu_scheduler_active =1 ; +} + +/* * Compute the per-level fanout, either using the exact fanout specified * or balancing the tree, depending on CONFIG_RCU_FANOUT_EXACT. */
Signature · 1 line
1.7.0