From: Tim Bird <tim.bird@am.sony.com>
To: Steven Rostedt <rostedt@goodmis.org>
Cc: Daniel Walker <dwalker@mvista.com>,
LKML <linux-kernel@vger.kernel.org>, Ingo Molnar <mingo@elte.hu>,
Linus Torvalds <torvalds@linux-foundation.org>,
Andrew Morton <akpm@linux-foundation.org>,
Peter Zijlstra <a.p.zijlstra@chello.nl>,
Christoph Hellwig <hch@infradead.org>,
Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>,
Gregory Haskins <ghaskins@novell.com>,
Arnaldo Carvalho de Melo <acme@ghostprotocols.net>,
Thomas Gleixner <tglx@linutronix.de>,
Sam Ravnborg <sam@ravnborg.org>,
"Frank Ch. Eigler" <fche@redhat.com>,
Jan Kiszka <jan.kiszka@siemens.com>,
John Stultz <johnstul@us.ibm.com>,
Arjan van de Ven <arjan@infradead.org>,
Steven Rostedt <srostedt@redhat.com>
Subject: [PATCH] defer printks in irqs
Date: Thu, 24 Jan 2008 14:42:28 -0800 [thread overview]
Message-ID: <47991454.50603@am.sony.com> (raw)
In-Reply-To: <Pine.LNX.4.58.0801231315500.6127@gandalf.stny.rr.com>
Steven Rostedt wrote:
> Tim, could you send me your "postponed print" patches. That sounds like
> something the -rt patch could use.
Sure. See below.
This patch changes the way the printk code processes output to the
console buffer. On some platforms, especially those with a serial
console, the way printk output the messages to console caused significant
interrupt-off periods. This code introduces two config options to
improve that handling.
Without this change, test code run on a 178 MHZ ARM platform
showed an interrupt off period for a particularly long printk message
of 24 milliseconds. With this patch applied, and the options set
to 'Y', the same message only had an interrupt-off period of
482 microseconds.
Portions of this (some parts that reorder locking and irq management
primitives) were taken from the RT-preempt patch.
The patch does several things:
1. It moves the location of the irqrestore operations in the
printk code, so that the console writing can occur with interrupts enabled
2. It changes the code so that characters are written to the console
one-at-a-time. The serial console code holds interrupts disabled for the
duration of its output to the serial port. To decrease the interrupt-off
time, only a small amount of data is written at a time. (This could be tuned
by writing chunks larger than 1 character at a time, but the current solution
was easiest, and gives the lowest interrupt-off times.)
3. The printk code was changed so that if it is entered with interrupts
disabled, it does not output to console immediately. Rather, a workqueue
routine is scheduled to process the console output later (when interrupts
are enabled).
4. An init-time routine was created, to prevent trying to schedule the
workqueue routine too early in the system boot sequence.
Here's the patch:
Signed-off-by: Tim Bird tim.bird@am.sony.com
---
kernel/printk.c | 92 85 + 7 - 0 !
lib/Kconfig.debug | 42 42 + 0 - 0 !
2 files changed, 127 insertions(+), 7 deletions(-)
Index: linux-2.6.24-rc8/kernel/printk.c
===================================================================
--- linux-2.6.24-rc8.orig/kernel/printk.c
+++ linux-2.6.24-rc8/kernel/printk.c
@@ -33,11 +33,14 @@
#include <linux/bootmem.h>
#include <linux/syscalls.h>
#include <linux/jiffies.h>
+#include <linux/workqueue.h>
#include <asm/uaccess.h>
#define __LOG_BUF_LEN (1 << CONFIG_LOG_BUF_SHIFT)
+#define PRINTK_BUF_SIZE 1024
+
/* printk's without a loglevel use this.. */
#define DEFAULT_MESSAGE_LOGLEVEL 4 /* KERN_WARNING */
@@ -47,6 +50,10 @@
DECLARE_WAIT_QUEUE_HEAD(log_wait);
+static void printk_console_flush(struct work_struct *ignored);
+static int have_callable_console(void);
+static DECLARE_WORK(printk_console_work, printk_console_flush);
+
int console_printk[4] = {
DEFAULT_CONSOLE_LOGLEVEL, /* console_loglevel */
DEFAULT_MESSAGE_LOGLEVEL, /* default_message_loglevel */
@@ -220,6 +227,43 @@ static inline void boot_delay_msec(void)
#endif
/*
+ * We can't schedule printk console flushing during early boot.
+ * This flag holds it off until after we've initialized some
+ * important stuff.
+ */
+static int pcf_ok = 0;
+
+static int __init init_printk_console_flush(void)
+{
+ pcf_ok = 1;
+ return 0;
+}
+__initcall(init_printk_console_flush);
+
+void printk_console_flush(struct work_struct *ignored)
+{
+ unsigned long flags;
+ int chars_to_flush;
+
+ spin_lock_irqsave(&logbuf_lock, flags);
+ chars_to_flush = log_end - con_start;
+ spin_unlock_irqrestore(&logbuf_lock, flags);
+
+ if (chars_to_flush) {
+ acquire_console_sem();
+
+ if ((cpu_online(smp_processor_id()) ||
+ have_callable_console())) {
+ console_may_schedule = 0;
+ release_console_sem();
+ } else {
+ console_locked = 0;
+ up(&console_sem);
+ }
+ }
+}
+
+/*
* Return the number of unread characters in the log buffer.
*/
int log_buf_get_len(void)
@@ -436,8 +480,16 @@ static void __call_console_drivers(unsig
for (con = console_drivers; con; con = con->next) {
if ((con->flags & CON_ENABLED) && con->write &&
(cpu_online(smp_processor_id()) ||
- (con->flags & CON_ANYTIME)))
+ (con->flags & CON_ANYTIME))) {
+#ifdef CONFIG_PRINTK_SHORT_IRQ_DISABLE
+ int i;
+ for(i=0; i<end-start; i++) {
+ con->write(con, &LOG_BUF(start+i), 1);
+ }
+#else
con->write(con, &LOG_BUF(start), end - start);
+#endif
+ }
}
}
@@ -633,8 +685,9 @@ asmlinkage int vprintk(const char *fmt,
unsigned long flags;
int printed_len;
char *p;
- static char printk_buf[1024];
+ static char printk_buf[PRINTK_BUF_SIZE];
static int log_level_unknown = 1;
+ int defer;
boot_delay_msec();
@@ -649,6 +702,7 @@ asmlinkage int vprintk(const char *fmt,
lockdep_off();
spin_lock(&logbuf_lock);
printk_cpu = smp_processor_id();
+ preempt_enable();
/* Emit the output into the temporary buffer */
printed_len = vscnprintf(printk_buf, sizeof(printk_buf), fmt, args);
@@ -718,6 +772,19 @@ asmlinkage int vprintk(const char *fmt,
console_locked = 1;
printk_cpu = UINT_MAX;
spin_unlock(&logbuf_lock);
+ lockdep_on();
+ local_irq_restore(flags);
+
+ defer = 0;
+#ifdef CONFIG_PRINTK_DEFER_IN_IRQ
+ /*
+ * If we're in an interrupt and it's not an emergency,
+ * don't emit to console just yet.
+ */
+ if ((irqs_disabled() || in_interrupt()) && !oops_in_progress) {
+ defer = 1;
+ }
+#endif
/*
* Console drivers may assume that per-cpu resources have
@@ -725,7 +792,8 @@ asmlinkage int vprintk(const char *fmt,
* being able to cope (CON_ANYTIME) don't call them until
* this CPU is officially up.
*/
- if (cpu_online(smp_processor_id()) || have_callable_console()) {
+ if (!defer && (cpu_online(smp_processor_id()) ||
+ have_callable_console())) {
console_may_schedule = 0;
release_console_sem();
} else {
@@ -733,8 +801,6 @@ asmlinkage int vprintk(const char *fmt,
console_locked = 0;
up(&console_sem);
}
- lockdep_on();
- raw_local_irq_restore(flags);
} else {
/*
* Someone else owns the drivers. We drop the spinlock, which
@@ -747,7 +813,11 @@ asmlinkage int vprintk(const char *fmt,
raw_local_irq_restore(flags);
}
- preempt_enable();
+ /* didn't flush console all the way yet? - schedule for later */
+ if ((log_end - con_start) && pcf_ok) {
+ schedule_work(&printk_console_work);
+ }
+
return printed_len;
}
EXPORT_SYMBOL(printk);
@@ -971,13 +1041,21 @@ void release_console_sem(void)
_con_start = con_start;
_log_end = log_end;
con_start = log_end; /* Flush */
+
+#ifdef CONFIG_PRINTK_SHORT_IRQ_DISABLE
+ /* allow irqs during console out */
+ spin_unlock_irqrestore(&logbuf_lock, flags);
+ call_console_drivers(_con_start, _log_end);
+#else
spin_unlock(&logbuf_lock);
call_console_drivers(_con_start, _log_end);
local_irq_restore(flags);
+#endif
}
console_locked = 0;
- up(&console_sem);
spin_unlock_irqrestore(&logbuf_lock, flags);
+ up(&console_sem);
+
if (wake_klogd)
wake_up_klogd();
}
Index: linux-2.6.24-rc8/lib/Kconfig.debug
===================================================================
--- linux-2.6.24-rc8.orig/lib/Kconfig.debug
+++ linux-2.6.24-rc8/lib/Kconfig.debug
@@ -17,6 +17,48 @@ config ENABLE_WARN_DEPRECATED
Disable this to suppress the "warning: 'foo' is deprecated
(declared at kernel/power/somefile.c:1234)" messages.
+config PRINTK_SHORT_IRQ_DISABLE
+ bool "Enable interrupts for shorter times during printk output"
+ default n
+ depends on PRINTK
+ help
+ Selecting this option will cause the kernel to write the
+ contents of the printk buffer to the console with interrupts
+ enabled, and in small increments.
+
+ With the default setting of 'n', the kernel attempts to
+ send printk messages to the console with interrupts disabled,
+ and it sends the entire contents of the printk buffer in one go.
+
+ For some consoles (notably the serial console, which is commonly
+ used in embedded products), this results in long interrupt-off
+ periods.
+
+ Users interested in good real-time scheduling should set this
+ to 'y'.
+
+config PRINTK_DEFER_IN_IRQ
+ bool "Defer writing printk output to console during interrupts"
+ default n
+ depends on PRINTK && PRINTK_SHORT_IRQ_DISABLE
+ help
+ Selecting this option will cause the kernel to hold off writing
+ printk messages to the console until interrupts are enabled.
+ On some systems, printk buffer and console handling can take
+ a long time. If done with interrupts off for the entire duration
+ of the operation, this results in long interrupt-off periods.
+
+ With the default setting of 'n', the kernel attempts to
+ send printk messages to the console whether it is in interrupt
+ context or not.
+
+ With a setting of 'y', when printk is called with interrupts
+ disabled, the messages are buffered in the kernel's
+ log buffer until later. If you are debugging the kernel
+ with printks in interrupt routines, you should set this
+ to 'n'. Users interested in good real-time scheduling
+ should set this to 'y'.
+
config ENABLE_MUST_CHECK
bool "Enable __must_check logic"
default y
next prev parent reply other threads:[~2008-01-24 22:37 UTC|newest]
Thread overview: 54+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-01-23 16:02 [PATCH 00/20 -v5] mcount and latency tracing utility -v5 Steven Rostedt
2008-01-23 16:02 ` [PATCH 01/20 -v5] printk - dont wakeup klogd with interrupts disabled Steven Rostedt
2008-01-23 17:06 ` Daniel Walker
2008-01-23 17:25 ` Mathieu Desnoyers
2008-01-23 17:49 ` Tim Bird
2008-01-24 10:35 ` Pavel Machek
2008-01-23 17:27 ` Steven Rostedt
2008-01-23 17:32 ` Mathieu Desnoyers
2008-01-23 17:43 ` Daniel Walker
2008-01-23 18:18 ` Steven Rostedt
2008-01-23 18:28 ` Daniel Walker
2008-01-23 18:43 ` Steven Rostedt
2008-01-23 18:50 ` Daniel Walker
2008-01-23 19:59 ` Daniel Walker
2008-01-24 22:42 ` Tim Bird [this message]
2008-01-24 22:48 ` [PATCH] defer printks in irqs Peter Zijlstra
2008-01-24 23:23 ` Tim Bird
2008-01-27 6:01 ` Andrew Morton
2008-01-28 21:14 ` Tim Bird
2008-01-24 10:36 ` [PATCH 01/20 -v5] printk - dont wakeup klogd with interrupts disabled Pavel Machek
2008-01-23 16:02 ` [PATCH 02/20 -v5] Add basic support for gcc profiler instrumentation Steven Rostedt
2008-01-23 16:02 ` [PATCH 03/20 -v5] Annotate core code that should not be traced Steven Rostedt
2008-01-23 16:02 ` [PATCH 04/20 -v5] x86_64: notrace annotations Steven Rostedt
2008-01-23 16:02 ` [PATCH 05/20 -v5] add notrace annotations to vsyscall Steven Rostedt
2008-01-23 16:02 ` [PATCH 06/20 -v5] add notrace annotations for NMI routines Steven Rostedt
2008-01-23 21:31 ` Mathieu Desnoyers
2008-01-23 21:58 ` Steven Rostedt
2008-01-26 5:25 ` Steven Rostedt
2008-01-28 11:51 ` Jan Kiszka
2008-01-28 12:15 ` Steven Rostedt
2008-01-23 16:02 ` [PATCH 07/20 -v5] handle accurate time keeping over long delays Steven Rostedt
2008-01-23 16:02 ` [PATCH 08/20 -v5] initialize the clock source to jiffies clock Steven Rostedt
2008-01-23 16:40 ` Tim Bird
2008-01-23 16:02 ` [PATCH 09/20 -v5] add get_monotonic_cycles Steven Rostedt
2008-01-23 16:02 ` [PATCH 10/20 -v5] add notrace annotations to timing events Steven Rostedt
2008-01-23 16:02 ` [PATCH 11/20 -v5] mcount based trace in the form of a header file library Steven Rostedt
2008-01-23 16:02 ` [PATCH 12/20 -v5] Add context switch marker to sched.c Steven Rostedt
2008-01-23 16:02 ` [PATCH 13/20 -v5] Make the task State char-string visible to all Steven Rostedt
2008-01-23 16:02 ` [PATCH 14/20 -v5] Add tracing of context switches Steven Rostedt
2008-01-23 16:02 ` [PATCH 15/20 -v5] Generic command line storage Steven Rostedt
2008-01-23 16:02 ` [PATCH 16/20 -v5] trace generic call to schedule switch Steven Rostedt
2008-01-23 16:02 ` [PATCH 17/20 -v5] Add marker in try_to_wake_up Steven Rostedt
2008-01-23 16:02 ` [PATCH 18/20 -v5] mcount tracer for wakeup latency timings Steven Rostedt
2008-01-23 16:02 ` [PATCH 19/20 -v5] Trace irq disabled critical timings Steven Rostedt
2008-01-23 16:53 ` Steven Rostedt
2008-01-23 17:11 ` Steven Rostedt
2008-01-23 17:27 ` Frank Ch. Eigler
2008-01-23 17:45 ` Steven Rostedt
2008-01-23 17:54 ` Mathieu Desnoyers
2008-01-23 17:58 ` Peter Zijlstra
2008-01-23 18:25 ` Frank Ch. Eigler
2008-01-23 18:48 ` Steven Rostedt
2008-01-23 21:29 ` Mathieu Desnoyers
2008-01-23 16:02 ` [PATCH 20/20 -v5] trace preempt off " Steven Rostedt
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=47991454.50603@am.sony.com \
--to=tim.bird@am.sony.com \
--cc=a.p.zijlstra@chello.nl \
--cc=acme@ghostprotocols.net \
--cc=akpm@linux-foundation.org \
--cc=arjan@infradead.org \
--cc=dwalker@mvista.com \
--cc=fche@redhat.com \
--cc=ghaskins@novell.com \
--cc=hch@infradead.org \
--cc=jan.kiszka@siemens.com \
--cc=johnstul@us.ibm.com \
--cc=linux-kernel@vger.kernel.org \
--cc=mathieu.desnoyers@polymtl.ca \
--cc=mingo@elte.hu \
--cc=rostedt@goodmis.org \
--cc=sam@ravnborg.org \
--cc=srostedt@redhat.com \
--cc=tglx@linutronix.de \
--cc=torvalds@linux-foundation.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).