From: Jeremy Fitzhardinge <jeremy@goop.org>
To: Ingo Molnar <mingo@elte.hu>
Cc: Prarit Bhargava <prarit@redhat.com>,
virtualization@lists.osdl.org,
Andrew Morton <akpm@linux-foundation.org>,
Linux Kernel <linux-kernel@vger.kernel.org>,
Eric Dumazet <dada1@cosmosbay.com>
Subject: [patch 4/4] Add global disable/enable for softlockup watchdog
Date: Tue, 27 Mar 2007 14:49:23 -0700 [thread overview]
Message-ID: <20070327215828.171904908@goop.org> (raw)
In-Reply-To: 20070327214919.800272641@goop.org
[-- Attachment #1: softlockup-global-enable.patch --]
[-- Type: text/plain, Size: 7487 bytes --]
Some machine-wide activities can cause spurious softlockup watchdog
warnings, so add a mechanism to allow the watchdog to be disabled.
The most obvious activity is suspend/resume, but long sysrq output can
also stall the system long enough to cause problems.
Signed-off-by: Jeremy Fitzhardinge <jeremy@xensource.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Prarit Bhargava <prarit@redhat.com>
Cc: Chris Lalancette <clalance@redhat.com>
Cc: Eric Dumazet <dada1@cosmosbay.com>
---
drivers/char/sysrq.c | 8 +++++
include/linux/sched.h | 10 ++++++
kernel/panic.c | 3 +-
kernel/power/swsusp.c | 3 +-
kernel/softlockup.c | 72 ++++++++++++++++++++++++++++++++++++++++++-------
kernel/timer.c | 4 ++
6 files changed, 87 insertions(+), 13 deletions(-)
===================================================================
--- a/drivers/char/sysrq.c
+++ b/drivers/char/sysrq.c
@@ -211,7 +211,11 @@ static struct sysrq_key_op sysrq_showreg
static void sysrq_handle_showstate(int key, struct tty_struct *tty)
{
+ softlockup_global_disable(); /* may take a while */
+
show_state();
+
+ softlockup_global_enable();
}
static struct sysrq_key_op sysrq_showstate_op = {
.handler = sysrq_handle_showstate,
@@ -222,7 +226,11 @@ static struct sysrq_key_op sysrq_showsta
static void sysrq_handle_showstate_blocked(int key, struct tty_struct *tty)
{
+ softlockup_global_disable(); /* may take a while */
+
show_state_filter(TASK_UNINTERRUPTIBLE);
+
+ softlockup_global_enable();
}
static struct sysrq_key_op sysrq_showstate_blocked_op = {
.handler = sysrq_handle_showstate_blocked,
===================================================================
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -243,6 +243,10 @@ extern int softlockup_disable(void);
extern int softlockup_disable(void);
extern void softlockup_enable(int state);
+/* Disable/re-enable softlockup watchdog on all CPUs */
+extern void softlockup_global_disable(void);
+extern void softlockup_global_enable(void);
+
extern void spawn_softlockup_task(void);
extern void touch_softlockup_watchdog(void);
#else
@@ -263,6 +267,12 @@ static inline void softlockup_enable(int
static inline void softlockup_enable(int state)
{
preempt_enable();
+}
+static inline void softlockup_global_enable(void)
+{
+}
+static inline void softlockup_global_disable(void)
+{
}
static inline void spawn_softlockup_task(void)
{
===================================================================
--- a/kernel/panic.c
+++ b/kernel/panic.c
@@ -131,8 +131,9 @@ NORET_TYPE void panic(const char * fmt,
disabled_wait(caller);
#endif
local_irq_enable();
+ softlockup_global_disable();
+
for (i = 0;;) {
- touch_softlockup_watchdog();
i += panic_blink(i);
mdelay(1);
i++;
===================================================================
--- a/kernel/power/swsusp.c
+++ b/kernel/power/swsusp.c
@@ -289,6 +289,7 @@ int swsusp_suspend(void)
* that suspended with irqs off ... no overall powerup.
*/
device_power_up();
+ softlockup_global_disable();
Enable_irqs:
local_irq_enable();
return error;
@@ -323,7 +324,7 @@ int swsusp_resume(void)
*/
swsusp_free();
restore_processor_state();
- touch_softlockup_watchdog();
+ softlockup_global_enable();
device_power_up();
local_irq_enable();
return error;
===================================================================
--- a/kernel/softlockup.c
+++ b/kernel/softlockup.c
@@ -17,10 +17,21 @@
static DEFINE_SPINLOCK(print_lock);
+/*
+ * Since sched_clock() is inherently per-cpu, its not possible to
+ * update another CPU's timestamp. To deal with this, we add an extra
+ * state meaning "enabled, but timestamp needs update".
+ */
+enum state {
+ SL_OFF = 0, /* disabled */
+ SL_UPDATE, /* enabled, but timestamp old */
+ SL_ON, /* enabled */
+};
+
static DEFINE_PER_CPU(unsigned long, touch_timestamp);
static DEFINE_PER_CPU(unsigned long, print_timestamp);
static DEFINE_PER_CPU(struct task_struct *, watchdog_task);
-static DEFINE_PER_CPU(int, enabled);
+static DEFINE_PER_CPU(enum state, softlock_state);
static int did_panic = 0;
@@ -48,7 +59,12 @@ static unsigned long get_timestamp(void)
void inline touch_softlockup_watchdog(void)
{
+ if (__raw_get_cpu_var(softlock_state) == SL_OFF)
+ return;
+
__raw_get_cpu_var(touch_timestamp) = get_timestamp();
+ barrier();
+ __raw_get_cpu_var(softlock_state) = SL_ON;
}
EXPORT_SYMBOL(touch_softlockup_watchdog);
@@ -58,7 +74,7 @@ EXPORT_SYMBOL(touch_softlockup_watchdog)
*/
void inline softlockup_tick_disable(void)
{
- __get_cpu_var(enabled) = 0;
+ __get_cpu_var(softlock_state) = SL_OFF;
}
/*
@@ -73,7 +89,7 @@ int softlockup_disable(void)
preempt_disable();
- ret = __get_cpu_var(enabled);
+ ret = __get_cpu_var(softlock_state) == SL_OFF;
softlockup_tick_disable();
return ret;
@@ -86,7 +102,7 @@ EXPORT_SYMBOL(softlockup_disable);
*/
void inline softlockup_tick_enable(void)
{
- __get_cpu_var(enabled) = 1;
+ __get_cpu_var(softlock_state) = SL_UPDATE;
}
/*
@@ -96,15 +112,41 @@ void softlockup_enable(int state)
void softlockup_enable(int state)
{
if (state) {
- touch_softlockup_watchdog();
- /* update timestamp before enable */
- barrier();
softlockup_tick_enable();
+ touch_softlockup_watchdog();
}
preempt_enable();
}
EXPORT_SYMBOL(softlockup_enable);
+
+/*
+ * Disable softlockup watchdog on all CPUs. This is useful for
+ * globally disruptive activities, like suspend/resume or large sysrq
+ * debug outputs.
+ */
+void softlockup_global_disable()
+{
+ unsigned cpu;
+
+ for_each_online_cpu(cpu)
+ per_cpu(softlock_state, cpu) = SL_OFF;
+}
+EXPORT_SYMBOL(softlockup_global_disable);
+
+/*
+ * Globally re-enable soft lockups. This will obviously interfere
+ * with any CPU's local softlockup disable, but with luck that won't
+ * matter.
+ */
+void softlockup_global_enable()
+{
+ unsigned cpu;
+
+ for_each_online_cpu(cpu)
+ per_cpu(softlock_state, cpu) = SL_UPDATE;
+}
+EXPORT_SYMBOL(softlockup_global_enable);
/*
* This callback runs from the timer interrupt, and checks
@@ -117,9 +159,19 @@ void softlockup_tick(void)
unsigned long print_timestamp;
unsigned long now;
- /* return if not enabled */
- if (!__get_cpu_var(enabled))
- return;
+ switch(__get_cpu_var(softlock_state)) {
+ case SL_OFF:
+ /* not enabled */
+ return;
+
+ case SL_UPDATE:
+ /* update timestamp */
+ touch_softlockup_watchdog();
+ return;
+
+ case SL_ON:
+ break;
+ }
print_timestamp = __get_cpu_var(print_timestamp);
===================================================================
--- a/kernel/timer.c
+++ b/kernel/timer.c
@@ -1011,7 +1011,7 @@ static int timekeeping_resume(struct sys
timekeeping_suspended = 0;
write_sequnlock_irqrestore(&xtime_lock, flags);
- touch_softlockup_watchdog();
+ softlockup_global_enable();
clockevents_notify(CLOCK_EVT_NOTIFY_RESUME, NULL);
@@ -1029,6 +1029,8 @@ static int timekeeping_suspend(struct sy
timekeeping_suspended = 1;
timekeeping_suspend_time = read_persistent_clock();
write_sequnlock_irqrestore(&xtime_lock, flags);
+
+ softlockup_global_disable();
clockevents_notify(CLOCK_EVT_NOTIFY_SUSPEND, NULL);
--
prev parent reply other threads:[~2007-03-27 21:49 UTC|newest]
Thread overview: 33+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-03-27 21:49 [patch 0/4] Revised softlockup watchdog improvement patches Jeremy Fitzhardinge
2007-03-27 21:49 ` [patch 1/4] Ignore stolen time in the softlockup watchdog Jeremy Fitzhardinge
2007-04-24 6:49 ` Andrew Morton
2007-04-24 6:58 ` Jeremy Fitzhardinge
2007-04-24 7:09 ` Andrew Morton
2007-04-24 17:51 ` Jeremy Fitzhardinge
2007-04-24 17:57 ` Andrew Morton
2007-04-24 18:16 ` Jeremy Fitzhardinge
2007-04-24 18:32 ` Andrew Morton
2007-04-24 20:00 ` Jeremy Fitzhardinge
2007-04-24 20:14 ` Andrew Morton
2007-04-24 20:46 ` Jeremy Fitzhardinge
2007-04-24 20:24 ` Jeremy Fitzhardinge
2007-04-24 20:33 ` Andrew Morton
2007-04-24 20:48 ` Jeremy Fitzhardinge
2007-04-24 20:52 ` Daniel Walker
2007-04-24 20:59 ` Ingo Molnar
2007-04-24 21:01 ` Daniel Walker
2007-04-24 21:14 ` Andrew Morton
2007-04-24 21:20 ` Andi Kleen
2007-04-24 21:33 ` Daniel Walker
2007-03-27 21:49 ` [patch 2/4] percpu enable flag for " Jeremy Fitzhardinge
2007-03-27 21:49 ` [patch 3/4] Locally disable the softlockup watchdog rather than touching it Jeremy Fitzhardinge
2007-03-28 13:33 ` Prarit Bhargava
2007-03-28 13:50 ` Andi Kleen
2007-03-28 14:00 ` Prarit Bhargava
2007-03-28 14:09 ` Andi Kleen
2007-03-28 14:13 ` Prarit Bhargava
2007-03-28 14:44 ` Jeremy Fitzhardinge
2007-03-28 14:51 ` Prarit Bhargava
2007-03-28 15:22 ` Jeremy Fitzhardinge
2007-03-28 15:27 ` Prarit Bhargava
2007-03-27 21:49 ` Jeremy Fitzhardinge [this message]
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=20070327215828.171904908@goop.org \
--to=jeremy@goop.org \
--cc=akpm@linux-foundation.org \
--cc=dada1@cosmosbay.com \
--cc=linux-kernel@vger.kernel.org \
--cc=mingo@elte.hu \
--cc=prarit@redhat.com \
--cc=virtualization@lists.osdl.org \
/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;
as well as URLs for NNTP newsgroup(s).