For rcu_bh in UP, rcu_process_callbacks() == a bh == QS == GP so we can pass rcu_bh-QS and advance GP(and callbacks) in rcu_process_callbacks().
After doing so, rcu_bh_qs() is useless since its work is handled by rcu_process_callbacks(). So we make it as empty-function and raise RCU_SOFTIRQ directly in call_rcu_bh(). Signed-off-by: Lai Jiangshan <[email protected]> --- kernel/rcu/tiny.c | 38 +++++++++++++++++--------------------- 1 files changed, 17 insertions(+), 21 deletions(-) diff --git a/kernel/rcu/tiny.c b/kernel/rcu/tiny.c index 805b6d5..f8e19ac 100644 --- a/kernel/rcu/tiny.c +++ b/kernel/rcu/tiny.c @@ -72,7 +72,7 @@ static void rcu_idle_enter_common(long long newval) current->pid, current->comm, idle->pid, idle->comm); /* must be idle task! */ } - rcu_sched_qs(); /* implies rcu_bh_inc() */ + rcu_sched_qs(); barrier(); rcu_dynticks_nesting = newval; } @@ -186,49 +186,43 @@ EXPORT_SYMBOL(__rcu_is_watching); #endif /* defined(CONFIG_DEBUG_LOCK_ALLOC) || defined(CONFIG_RCU_TRACE) */ /* - * Helper function for rcu_sched_qs() and rcu_bh_qs(). + * Helper function for rcu_sched_ctrlblk and rcu_bh_ctrlblk. * 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); RCU_TRACE(reset_cpu_stall_ticks(rcp)); if (rcp->rcucblist != NULL && rcp->donetail != rcp->curtail) { rcp->donetail = rcp->curtail; + local_irq_restore(flags); return 1; } + local_irq_restore(flags); return 0; } /* - * 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. + * Record an rcu quiescent state. */ void rcu_sched_qs(void) { - unsigned long flags; - - local_irq_save(flags); - if (rcu_qsctr_help(&rcu_sched_ctrlblk) + - rcu_qsctr_help(&rcu_bh_ctrlblk)) + if (rcu_qsctr_help(&rcu_sched_ctrlblk)) raise_softirq(RCU_SOFTIRQ); - local_irq_restore(flags); } /* * Record an rcu_bh quiescent state. + * Do nothing, since this quiescent state is temporary useless until + * RCU_SOFTIRQ, and RCU_SOFTIRQ will really record the quiescent state. */ void rcu_bh_qs(void) { - unsigned long flags; - - local_irq_save(flags); - if (rcu_qsctr_help(&rcu_bh_ctrlblk)) - raise_softirq(RCU_SOFTIRQ); - local_irq_restore(flags); } /* @@ -240,12 +234,10 @@ void rcu_bh_qs(void) void rcu_check_callbacks(int user) { RCU_TRACE(check_cpu_stalls()); - if (user) + if (user) { rcu_sched_qs(); - else if (!in_softirq()) - rcu_bh_qs(); - if (user) rcu_note_voluntary_context_switch(current); + } } /* @@ -303,6 +295,9 @@ static void __rcu_process_callbacks(struct rcu_ctrlblk *rcp) static void rcu_process_callbacks(struct softirq_action *unused) { __rcu_process_callbacks(&rcu_sched_ctrlblk); + + /* Here is quiescent state for rcu_bh */ + rcu_qsctr_help(&rcu_bh_ctrlblk); __rcu_process_callbacks(&rcu_bh_ctrlblk); } @@ -367,6 +362,7 @@ EXPORT_SYMBOL_GPL(call_rcu_sched); void call_rcu_bh(struct rcu_head *head, void (*func)(struct rcu_head *rcu)) { __call_rcu(head, func, &rcu_bh_ctrlblk); + raise_softirq(RCU_SOFTIRQ); } EXPORT_SYMBOL_GPL(call_rcu_bh); -- 1.7.4.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/

