From: Andrew Morton <akpm@osdl.org>
To: Stephen Rothwell <sfr@canb.auug.org.au>
Cc: paulmck@us.ibm.com, linux-kernel@vger.kernel.org,
Zwane Mwaikambo <zwane@holomorphy.com>
Subject: Re: Fw: [RFC] Strange code in cpu_idle()
Date: Sun, 5 Dec 2004 23:20:07 -0800 [thread overview]
Message-ID: <20041205232007.7edc4a78.akpm@osdl.org> (raw)
In-Reply-To: <20041206111634.44d6d29c.sfr@canb.auug.org.au>
Stephen Rothwell <sfr@canb.auug.org.au> wrote:
>
> > OK, I believe I found the other end of this:
> >
> > static void __exit apm_exit(void)
> > {
> > int error;
> >
> > if (set_pm_idle) {
> > pm_idle = original_pm_idle;
> > /*
> > * We are about to unload the current idle thread pm callback
> > * (pm_idle), Wait for all processors to update cached/local
> > * copies of pm_idle before proceeding.
> > */
> > synchronize_kernel();
> > }
> >
> > Unfortunately, the idle loop is a quiescent state, so it is
> > possible for synchronize_kernel() to return before the idle threads
> > have returned. So I don't believe RCU is useful here. One other
> > approach would be to keep a cpu mask, in which apm_exit() sets all
> > bits, and pm_idle() clears its CPU's bit only if it is set.
> > Then apm_exit() could wait for all CPU's bits to clear.
> >
> > There is probably a better way to do this, but that is what comes
> > to mind immediately.
> >
> > Thoughts?
>
> None, sorry :-)
>
> I don't even remember that piece of code going in (I certainly didn't
> write it), though I can see what it was trying to do.
It came in via the below patch. I guess we need to find a different way to
fix this problem.
# This is a BitKeeper generated diff -Nru style patch.
#
# ChangeSet
# 2004/09/17 12:09:12-07:00 zwane@linuxpower.ca
# [PATCH] Close race with preempt and modular pm_idle callbacks
#
# The following patch from Shaohua Li fixes a race with preempt enabled when
# a module containing a pm_idle callback is unloaded. Cached values in local
# variables need to be protected as RCU critical sections so that the
# synchronize_kernel() call in the unload path waits for all processors.
# There original bugzilla entry can be found at
#
# Shaohua, i had to make a small change (variable declaration after code in
# code block) so that it compiles with geriatric compilers such as the ones
# Andrew is attached to ;)
#
# http://bugzilla.kernel.org/show_bug.cgi?id=1716
#
# Signed-off-by: Li Shaohua <shaohua.li@intel.com>
# Signed-off-by: Zwane Mwaikambo <zwane@linuxpower.ca>
# Signed-off-by: Andrew Morton <akpm@osdl.org>
# Signed-off-by: Linus Torvalds <torvalds@osdl.org>
#
# drivers/acpi/processor.c
# 2004/09/17 00:07:02-07:00 zwane@linuxpower.ca +5 -0
# Close race with preempt and modular pm_idle callbacks
#
# arch/x86_64/kernel/process.c
# 2004/09/17 00:07:02-07:00 zwane@linuxpower.ca +13 -4
# Close race with preempt and modular pm_idle callbacks
#
# arch/ia64/kernel/process.c
# 2004/09/17 00:07:02-07:00 zwane@linuxpower.ca +12 -4
# Close race with preempt and modular pm_idle callbacks
#
# arch/i386/kernel/process.c
# 2004/09/17 00:07:02-07:00 zwane@linuxpower.ca +9 -1
# Close race with preempt and modular pm_idle callbacks
#
# arch/i386/kernel/apm.c
# 2004/09/17 00:07:02-07:00 zwane@linuxpower.ca +8 -1
# Close race with preempt and modular pm_idle callbacks
#
diff -Nru a/arch/i386/kernel/apm.c b/arch/i386/kernel/apm.c
--- a/arch/i386/kernel/apm.c 2004-12-05 23:18:08 -08:00
+++ b/arch/i386/kernel/apm.c 2004-12-05 23:18:08 -08:00
@@ -2362,8 +2362,15 @@
{
int error;
- if (set_pm_idle)
+ if (set_pm_idle) {
pm_idle = original_pm_idle;
+ /*
+ * We are about to unload the current idle thread pm callback
+ * (pm_idle), Wait for all processors to update cached/local
+ * copies of pm_idle before proceeding.
+ */
+ synchronize_kernel();
+ }
if (((apm_info.bios.flags & APM_BIOS_DISENGAGED) == 0)
&& (apm_info.connection_version > 0x0100)) {
error = apm_engage_power_management(APM_DEVICE_ALL, 0);
diff -Nru a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c
--- a/arch/i386/kernel/process.c 2004-12-05 23:18:08 -08:00
+++ b/arch/i386/kernel/process.c 2004-12-05 23:18:08 -08:00
@@ -142,13 +142,21 @@
/* endless idle loop with no priority at all */
while (1) {
while (!need_resched()) {
- void (*idle)(void) = pm_idle;
+ void (*idle)(void);
+ /*
+ * Mark this as an RCU critical section so that
+ * synchronize_kernel() in the unload path waits
+ * for our completion.
+ */
+ rcu_read_lock();
+ idle = pm_idle;
if (!idle)
idle = default_idle;
irq_stat[smp_processor_id()].idle_timestamp = jiffies;
idle();
+ rcu_read_unlock();
}
schedule();
}
diff -Nru a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c
--- a/arch/ia64/kernel/process.c 2004-12-05 23:18:08 -08:00
+++ b/arch/ia64/kernel/process.c 2004-12-05 23:18:08 -08:00
@@ -228,18 +228,26 @@
/* endless idle loop with no priority at all */
while (1) {
- void (*idle)(void) = pm_idle;
- if (!idle)
- idle = default_idle;
-
#ifdef CONFIG_SMP
if (!need_resched())
min_xtp();
#endif
while (!need_resched()) {
+ void (*idle)(void);
+
if (mark_idle)
(*mark_idle)(1);
+ /*
+ * Mark this as an RCU critical section so that
+ * synchronize_kernel() in the unload path waits
+ * for our completion.
+ */
+ rcu_read_lock();
+ idle = pm_idle;
+ if (!idle)
+ idle = default_idle;
(*idle)();
+ rcu_read_unlock();
}
if (mark_idle)
diff -Nru a/arch/x86_64/kernel/process.c b/arch/x86_64/kernel/process.c
--- a/arch/x86_64/kernel/process.c 2004-12-05 23:18:08 -08:00
+++ b/arch/x86_64/kernel/process.c 2004-12-05 23:18:08 -08:00
@@ -130,11 +130,20 @@
{
/* endless idle loop with no priority at all */
while (1) {
- void (*idle)(void) = pm_idle;
- if (!idle)
- idle = default_idle;
- while (!need_resched())
+ while (!need_resched()) {
+ void (*idle)(void);
+ /*
+ * Mark this as an RCU critical section so that
+ * synchronize_kernel() in the unload path waits
+ * for our completion.
+ */
+ rcu_read_lock();
+ idle = pm_idle;
+ if (!idle)
+ idle = default_idle;
idle();
+ rcu_read_unlock();
+ }
schedule();
}
}
diff -Nru a/drivers/acpi/processor.c b/drivers/acpi/processor.c
--- a/drivers/acpi/processor.c 2004-12-05 23:18:08 -08:00
+++ b/drivers/acpi/processor.c 2004-12-05 23:18:08 -08:00
@@ -2419,6 +2419,11 @@
/* Unregister the idle handler when processor #0 is removed. */
if (pr->id == 0) {
pm_idle = pm_idle_save;
+ /*
+ * We are about to unload the current idle thread pm callback
+ * (pm_idle), Wait for all processors to update cached/local
+ * copies of pm_idle before proceeding.
+ */
synchronize_kernel();
}
next prev parent reply other threads:[~2004-12-06 7:21 UTC|newest]
Thread overview: 32+ messages / expand[flat|nested] mbox.gz Atom feed top
2004-12-05 0:45 Fw: [RFC] Strange code in cpu_idle() Paul E. McKenney
2004-12-06 0:16 ` Stephen Rothwell
2004-12-06 6:46 ` Stephen Rothwell
2004-12-06 10:00 ` Zwane Mwaikambo
2004-12-06 7:20 ` Andrew Morton [this message]
2004-12-06 9:38 ` Zwane Mwaikambo
2004-12-06 16:04 ` Paul E. McKenney
2004-12-06 16:47 ` Zwane Mwaikambo
2004-12-06 19:22 ` Paul E. McKenney
2004-12-11 15:07 ` Zwane Mwaikambo
2004-12-12 4:54 ` [PATCH] Remove RCU abuse " Zwane Mwaikambo
2004-12-12 5:06 ` Zwane Mwaikambo
2004-12-12 5:49 ` Zwane Mwaikambo
2004-12-13 6:13 ` Andrew Morton
2004-12-13 6:22 ` Zwane Mwaikambo
2004-12-13 6:32 ` Andrew Morton
2004-12-13 7:09 ` Zwane Mwaikambo
2004-12-13 6:41 ` Andrew Morton
2004-12-13 7:13 ` Zwane Mwaikambo
2004-12-19 2:40 ` Nish Aravamudan
2004-12-20 0:59 ` Zwane Mwaikambo
2004-12-20 1:15 ` Nick Piggin
2004-12-20 1:44 ` Zwane Mwaikambo
2004-12-20 1:56 ` Nick Piggin
2004-12-20 2:10 ` Zwane Mwaikambo
2004-12-20 2:30 ` Nish Aravamudan
2004-12-20 18:27 ` Nishanth Aravamudan
2004-12-20 22:57 ` Zwane Mwaikambo
2004-12-20 23:15 ` Andrew Morton
2004-12-20 23:16 ` Zwane Mwaikambo
2004-12-20 23:26 ` Nishanth Aravamudan
2004-12-20 2:26 ` Nish Aravamudan
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20041205232007.7edc4a78.akpm@osdl.org \
--to=akpm@osdl.org \
--cc=linux-kernel@vger.kernel.org \
--cc=paulmck@us.ibm.com \
--cc=sfr@canb.auug.org.au \
--cc=zwane@holomorphy.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.