Re: linux-next 20111025: warnings in rcu_idle_exit_common()/rcu_idle_enter_common()

Paul E. McKenney
2011-11-02T14:58:45Z

On Wed, Nov 02, 2011 at 12:32:12AM +0800, Wu Fengguang wrote:
> > Hmmmm... Please see below for a diagnostic patch that prints out who
> > the kernel believes the idle thread is. Could you please give this
> > a go?
>
> Sure. Here it goes :)

And here is a possible fix. Could you please test it?

Thanx, Paul

------------------------------------------------------------------------

rcu: Fix idle-task checks

RCU has traditionally relied on idle_cpu() to determine whether a given
CPU is running in the context of an idle task, but recent changes have
invalidated this approach. This commit therefore switches from idle_cpu
to "current->pid != 0".

Suggested-by: Carsten Emde <C.Emde@osadl.org>
Signed-off-by: Paul E. McKenney <paul.mckenney@linaro.org>
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>

diff --git a/kernel/rcutiny.c b/kernel/rcutiny.c
index f4e7bc3..35f8a07 100644
--- a/kernel/rcutiny.c
+++ b/kernel/rcutiny.c
@@ -65,7 +65,7 @@ static void rcu_idle_enter_common(long long oldval)
return;
}
RCU_TRACE(trace_rcu_dyntick("Start", oldval, rcu_dynticks_nesting));
- if (!idle_cpu(smp_processor_id())) {
+ if (current->pid != 0) {
struct task_struct *idle = idle_task(smp_processor_id());

RCU_TRACE(trace_rcu_dyntick("Error on entry: not idle task",
@@ -119,7 +119,7 @@ static void rcu_idle_exit_common(long long oldval)
return;
}
RCU_TRACE(trace_rcu_dyntick("End", oldval, rcu_dynticks_nesting));
- if (!idle_cpu(smp_processor_id())) {
+ if (!current->pid != 0) {
struct task_struct *idle = idle_task(smp_processor_id());

RCU_TRACE(trace_rcu_dyntick("Error on exit: not idle task",
diff --git a/kernel/rcutree.c b/kernel/rcutree.c
index 3d7b474..414af68 100644
--- a/kernel/rcutree.c
+++ b/kernel/rcutree.c
@@ -355,7 +355,7 @@ static void rcu_idle_enter_common(struct rcu_dynticks *rdtp, long long oldval)
return;
}
trace_rcu_dyntick("Start", oldval, rdtp->dynticks_nesting);
- if (!idle_cpu(smp_processor_id())) {
+ if (current->pid != 0) {
struct task_struct *idle = idle_task(smp_processor_id());

trace_rcu_dyntick("Error on entry: not idle task",
@@ -449,7 +449,7 @@ static void rcu_idle_exit_common(struct rcu_dynticks *rdtp, long long oldval)
smp_mb__after_atomic_inc(); /* See above. */
WARN_ON_ONCE(!(atomic_read(&rdtp->dynticks) & 0x1));
trace_rcu_dyntick("End", oldval, rdtp->dynticks_nesting);
- if (!idle_cpu(smp_processor_id())) {
+ if (current->pid != 0) {
struct task_struct *idle = idle_task(smp_processor_id());

trace_rcu_dyntick("Error on exit: not idle task",