| 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 | 36 +++++++++++++++++++++++++++++++++--- |
| 1 file changed, 33 insertions(+), 3 deletions(-) |
| |
| --- a/kernel/printk/printk.c |
| +++ b/kernel/printk/printk.c |
| @@ -1606,6 +1606,7 @@ SYSCALL_DEFINE3(syslog, int, type, char |
| return do_syslog(type, buf, len, SYSLOG_FROM_READER); |
| } |
| |
| +#ifndef CONFIG_PREEMPT_RT_FULL |
| /* |
| * 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. |
| @@ -1746,6 +1747,15 @@ static int console_trylock_spinning(void |
| return 1; |
| } |
| |
| +#else |
| + |
| +static int console_trylock_spinning(void) |
| +{ |
| + return console_trylock(); |
| +} |
| + |
| +#endif |
| + |
| /* |
| * Call the console drivers, asking them to write out |
| * log_buf[start] to log_buf[end - 1]. |
| @@ -1761,6 +1771,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; |
| @@ -1776,6 +1787,7 @@ static void call_console_drivers(const c |
| else |
| con->write(con, text, len); |
| } |
| + migrate_enable(); |
| } |
| |
| int printk_delay_msec __read_mostly; |
| @@ -1958,20 +1970,31 @@ 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 |
| + |
| /* |
| * 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(); |
| } |
| |
| return printed_len; |
| @@ -2429,6 +2452,10 @@ 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 |
| /* |
| * While actively printing out messages, if another printk() |
| * were to occur on another CPU, it may wait for this one to |
| @@ -2447,6 +2474,7 @@ void console_unlock(void) |
| } |
| |
| printk_safe_exit_irqrestore(flags); |
| +#endif |
| |
| if (do_cond_resched) |
| cond_resched(); |
| @@ -2476,7 +2504,9 @@ void console_unlock(void) |
| if (retry && console_trylock()) |
| goto again; |
| |
| +#ifndef CONFIG_PREEMPT_RT_FULL |
| out: |
| +#endif |
| if (wake_klogd) |
| wake_up_klogd(); |
| } |