From: Thomas Gleixner <tglx@linutronix.de>
Date: Wed, 19 Sep 2012 14:50:37 +0200
Subject: [PATCH 206/329] printk: Make rt aware
Patch-mainline: Not yet, still being discussed upstream
References: bsc#1174146
Drop the lock before calling the console driver and do not disable
interrupts while printing to a serial console.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Petr Mladek <pmladek@suse.com>
---
kernel/printk/printk.c | 69 +++++++++++++++++++++++++++++++++++--------------
1 file changed, 50 insertions(+), 19 deletions(-)
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -247,10 +247,12 @@ static void __up_console_sem(unsigned lo
}
#define up_console_sem() __up_console_sem(_RET_IP_)
+#ifndef CONFIG_PREEMPT_RT
static bool panic_in_progress(void)
{
return unlikely(atomic_read(&panic_cpu) != PANIC_CPU_INVALID);
}
+#endif
/*
* This is used for debugging the mess that is the VT code by
@@ -1659,6 +1661,7 @@ SYSCALL_DEFINE3(syslog, int, type, char
return do_syslog(type, buf, len, SYSLOG_FROM_READER);
}
+#ifndef CONFIG_PREEMPT_RT
/*
* Special console_lock variants that help to reduce the risk of soft-lockups.
* They allow to pass console_lock to another printk() call using a busy wait.
@@ -1675,22 +1678,6 @@ static struct task_struct *console_owner
static bool console_waiter;
/**
- * printk_bust_locks - forcibly reset all printk-related locks
- *
- * This function can be used after CPUs were stopped using NMI.
- * It is especially useful in kdump_nmi_shootdown_cpus() that
- * uses NMI but it does not modify the online CPU mask.
- */
-void printk_bust_locks(void)
-{
- debug_locks_off();
- raw_spin_lock_init(&logbuf_lock);
- raw_spin_lock_init(&console_owner_lock);
- console_owner = NULL;
- console_waiter = false;
-}
-
-/**
* console_lock_spinning_enable - mark beginning of code where another
* thread might safely busy wait
*
@@ -1825,6 +1812,33 @@ static int console_trylock_spinning(void
return 1;
}
+#else
+
+static int console_trylock_spinning(void)
+{
+ return console_trylock();
+}
+
+#endif
+
+/**
+ * printk_bust_locks - forcibly reset all printk-related locks
+ *
+ * This function can be used after CPUs were stopped using NMI.
+ * It is especially useful in kdump_nmi_shootdown_cpus() that
+ * uses NMI but it does not modify the online CPU mask.
+ */
+void printk_bust_locks(void)
+{
+ debug_locks_off();
+ raw_spin_lock_init(&logbuf_lock);
+#ifndef CONFIG_PREEMPT_RT
+ raw_spin_lock_init(&console_owner_lock);
+ console_owner = NULL;
+ console_waiter = false;
+#endif
+}
+
/*
* Call the console drivers, asking them to write out
* log_buf[start] to log_buf[end - 1].
@@ -1840,6 +1854,7 @@ static void call_console_drivers(const c
if (!console_drivers)
return;
+ migrate_disable();
for_each_console(con) {
if (exclusive_console && con != exclusive_console)
continue;
@@ -1855,6 +1870,7 @@ static void call_console_drivers(const c
else
con->write(con, text, len);
}
+ migrate_enable();
}
int printk_delay_msec __read_mostly;
@@ -2075,20 +2091,30 @@ asmlinkage int vprintk_emit(int facility
/* Offload printing to a schedulable context. */
defer_console_output();
} else {
+ int may_trylock = 1;
+
+#ifdef CONFIG_PREEMPT_RT
+ /*
+ * we can't take a sleeping lock with IRQs or preeption disabled
+ * so we can't print in these contexts
+ */
+ if (!(preempt_count() == 0 && !irqs_disabled()))
+ may_trylock = 0;
+#endif
/*
* Disable preemption to avoid being preempted while
* holding console_sem which would prevent anyone
* from printing to console
*/
- preempt_disable();
+ migrate_disable();
/*
* Try to acquire and then immediately release the
* console semaphore. The release will print out
* buffers and wake up /dev/kmsg and syslog() users.
*/
- if (console_trylock_spinning())
+ if (may_trylock && console_trylock_spinning())
console_unlock();
- preempt_enable();
+ migrate_enable();
}
}
@@ -2583,6 +2609,10 @@ skip:
console_seq++;
raw_spin_unlock(&logbuf_lock);
+#ifdef CONFIG_PREEMPT_RT
+ printk_safe_exit_irqrestore(flags);
+ call_console_drivers(ext_text, ext_len, text, len);
+#else
/*
* While actively printing out messages, if another printk()
* were to occur on another CPU, it may wait for this one to
@@ -2601,6 +2631,7 @@ skip:
}
printk_safe_exit_irqrestore(flags);
+#endif
if (do_cond_resched)
cond_resched();