aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorAndrew Morton <akpm@osdl.org>2004-05-24 18:36:46 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2004-05-24 18:36:46 -0700
commitc570d66770cfaf169ba91e43f6243ddbac8efd73 (patch)
tree9afb22d625740c1ca0eff221e3db0268d41c4f32 /kernel
parented8d9961f3c411b5b3ab2a673e66bfc01827a46b (diff)
downloadhistory-c570d66770cfaf169ba91e43f6243ddbac8efd73.tar.gz
[PATCH] Fix the mangled-oops-output-on-SMP problem
From: Ingo Molnar <mingo@elte.hu> printk currently does if (oops_in_progres) bust_printk_locks(); which means that once we oops, the printk locking is 100% ineffective and multiple CPUs make an unreadable mess on a serial console. It's a significant development hassle. Fix that up by only popping locks once per ten seconds. akpm@osdl.org did: - Bump the timeout to 30 seconds - 9600 baud is slow. - Handle jiffy wraps: change the logic so that we only skip the lockbust if the current time is within 30 seconds of the previous lockbusting attempt.
Diffstat (limited to 'kernel')
-rw-r--r--kernel/printk.c29
1 files changed, 23 insertions, 6 deletions
diff --git a/kernel/printk.c b/kernel/printk.c
index 3b74688184a8d4..9e34ce41beb6de 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -472,6 +472,27 @@ static void emit_log_char(char c)
}
/*
+ * Zap console related locks when oopsing. Only zap at most once
+ * every 10 seconds, to leave time for slow consoles to print a
+ * full oops.
+ */
+static void zap_locks(void)
+{
+ static unsigned long oops_timestamp;
+
+ if (time_after_eq(jiffies, oops_timestamp) &&
+ !time_after(jiffies, oops_timestamp + 30*HZ))
+ return;
+
+ oops_timestamp = jiffies;
+
+ /* If a crash is occurring, make sure we can't deadlock */
+ spin_lock_init(&logbuf_lock);
+ /* And make sure that we print immediately */
+ init_MUTEX(&console_sem);
+}
+
+/*
* This is printk. It can be called from any context. We want it to work.
*
* We try to grab the console_sem. If we succeed, it's easy - we log the output and
@@ -493,12 +514,8 @@ asmlinkage int printk(const char *fmt, ...)
static char printk_buf[1024];
static int log_level_unknown = 1;
- if (oops_in_progress) {
- /* If a crash is occurring, make sure we can't deadlock */
- spin_lock_init(&logbuf_lock);
- /* And make sure that we print immediately */
- init_MUTEX(&console_sem);
- }
+ if (unlikely(oops_in_progress))
+ zap_locks();
/* This stops the holder of console_sem just where we want him */
spin_lock_irqsave(&logbuf_lock, flags);