mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
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();
 	}
 


  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 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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

Powered by JetHome