diff options
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/printk.c | 29 |
1 files changed, 23 insertions, 6 deletions
diff --git a/kernel/printk.c b/kernel/printk.c index 3b74688184a8..9e34ce41beb6 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); |
