
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.


---

 25-akpm/kernel/printk.c |   28 ++++++++++++++++++++++------
 1 files changed, 22 insertions(+), 6 deletions(-)

diff -puN kernel/printk.c~mangled-printk-oops-output-fix kernel/printk.c
--- 25/kernel/printk.c~mangled-printk-oops-output-fix	Thu May 20 15:59:39 2004
+++ 25-akpm/kernel/printk.c	Thu May 20 15:59:39 2004
@@ -55,6 +55,9 @@ EXPORT_SYMBOL(console_printk);
 
 int oops_in_progress;
 
+/* zap spinlocks only once: */
+unsigned long oops_timestamp;
+
 /*
  * console_sem protects the console_drivers list, and also
  * provides serialisation for access to the entire console
@@ -472,6 +475,23 @@ 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 inline void zap_locks(void)
+{
+	if (!time_after(jiffies, oops_timestamp + 10*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 +513,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);

_
