| Subject: printk: Make rt aware |
| From: Thomas Gleixner <tglx@linutronix.de> |
| Date: Wed, 19 Sep 2012 14:50:37 +0200 |
| |
| 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> |
| --- |
| kernel/printk/printk.c | 19 ++++++++++++++++++- |
| 1 file changed, 18 insertions(+), 1 deletion(-) |
| |
| --- a/kernel/printk/printk.c |
| +++ b/kernel/printk/printk.c |
| @@ -1630,6 +1630,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; |
| @@ -1645,6 +1646,7 @@ static void call_console_drivers(const c |
| else |
| con->write(con, text, len); |
| } |
| + migrate_enable(); |
| } |
| |
| int printk_delay_msec __read_mostly; |
| @@ -1827,12 +1829,22 @@ asmlinkage int vprintk_emit(int facility |
| |
| /* If called from the scheduler, we can not call up(). */ |
| if (!in_sched) { |
| + int may_trylock = 1; |
| + |
| +#ifdef CONFIG_PREEMPT_RT_FULL |
| + /* |
| + * 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 |
| /* |
| * 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()) |
| + if (may_trylock && console_trylock()) |
| console_unlock(); |
| } |
| |
| @@ -2283,10 +2295,15 @@ void console_unlock(void) |
| console_seq++; |
| raw_spin_unlock(&logbuf_lock); |
| |
| +#ifdef CONFIG_PREEMPT_RT_FULL |
| + printk_safe_exit_irqrestore(flags); |
| + call_console_drivers(ext_text, ext_len, text, len); |
| +#else |
| stop_critical_timings(); /* don't trace print latency */ |
| call_console_drivers(ext_text, ext_len, text, len); |
| start_critical_timings(); |
| printk_safe_exit_irqrestore(flags); |
| +#endif |
| |
| if (do_cond_resched) |
| cond_resched(); |