|
From: James S. <jsi...@us...> - 2001-12-26 17:28:16
|
Update of /cvsroot/linuxconsole/ruby/linux/kernel
In directory usw-pr-cvs1:/tmp/cvs-serv5113/kernel
Modified Files:
printk.c
Log Message:
Synced to 2.5.0. Don't use. The default 2.5.0 has a nasty bug in it.
Index: printk.c
===================================================================
RCS file: /cvsroot/linuxconsole/ruby/linux/kernel/printk.c,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -d -r1.22 -r1.23
--- printk.c 2001/12/23 04:59:46 1.22
+++ printk.c 2001/12/26 17:28:12 1.23
@@ -14,9 +14,6 @@
* man...@co...
* Rewrote bits to get rid of console_lock
* 01Mar01 Andrew Morton <an...@uo...>
- * Added finer grain locking for the console system. Also made it more
- * VT independent.
- * 11-28-2001 James Simmons <jsi...@tr...>
*/
#include <linux/mm.h>
@@ -27,10 +24,18 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/interrupt.h> /* For in_interrupt() */
+#include <linux/config.h>
#include <asm/uaccess.h>
+#ifdef CONFIG_MULTIQUAD
+#define LOG_BUF_LEN (65536)
+#elif defined(CONFIG_SMP)
+#define LOG_BUF_LEN (32768)
+#else
#define LOG_BUF_LEN (16384) /* This must be a power of two */
+#endif
+
#define LOG_BUF_MASK (LOG_BUF_LEN-1)
/* printk's without a loglevel use this.. */
@@ -51,9 +56,11 @@
int oops_in_progress;
/*
- * console_lock protects the console_drivers list
+ * console_sem protects the console_drivers list, and also
+ * provides serialisation for access to the entire console
+ * driver system.
*/
-static spinlock_t console_lock = SPIN_LOCK_UNLOCKED;
+static DECLARE_MUTEX(console_sem);
struct console *console_drivers;
/*
@@ -78,6 +85,9 @@
struct console_cmdline console_cmdline[MAX_CMDLINECONSOLES];
static int preferred_console = -1;
+/* Flag: console code may call schedule() */
+static int console_may_schedule;
+
/*
* Setup a list of consoles. Called from init/main.c
*/
@@ -284,29 +294,28 @@
/*
* Call the console drivers on a range of log_buf
*/
-static void __call_console_drivers(struct console *con, unsigned long start, unsigned long end)
+static void __call_console_drivers(unsigned long start, unsigned long end)
{
- /* Make sure that we print immediately */
- if (oops_in_progress)
- init_MUTEX(&con->lock);
+ struct console *con;
- down(&con->lock);
- con->write(con, &LOG_BUF(start), end - start);
- up(&con->lock);
+ for (con = console_drivers; con; con = con->next) {
+ if ((con->flags & CON_ENABLED) && con->write)
+ con->write(con, &LOG_BUF(start), end - start);
+ }
}
/*
* Write out chars from start to end - 1 inclusive
*/
-static void _call_console_drivers(struct console *con, unsigned long start, unsigned long end, int msg_log_level)
+static void _call_console_drivers(unsigned long start, unsigned long end, int msg_log_level)
{
- if (msg_log_level < console_loglevel && con && start != end) {
+ if (msg_log_level < console_loglevel && console_drivers && start != end) {
if ((start & LOG_BUF_MASK) > (end & LOG_BUF_MASK)) {
/* wrapped write */
- __call_console_drivers(con, start & LOG_BUF_MASK, LOG_BUF_LEN);
- __call_console_drivers(con, 0, end & LOG_BUF_MASK);
+ __call_console_drivers(start & LOG_BUF_MASK, LOG_BUF_LEN);
+ __call_console_drivers(0, end & LOG_BUF_MASK);
} else {
- __call_console_drivers(con, start, end);
+ __call_console_drivers(start, end);
}
}
}
@@ -316,7 +325,7 @@
* log_buf[start] to log_buf[end - 1].
* The console_sem must be held.
*/
-static void call_console_drivers(struct console *con, unsigned long start, unsigned long end)
+static void call_console_drivers(unsigned long start, unsigned long end)
{
unsigned long cur_index, start_print;
static int msg_level = -1;
@@ -352,14 +361,14 @@
*/
msg_level = default_message_loglevel;
}
- _call_console_drivers(con, start_print, cur_index, msg_level);
+ _call_console_drivers(start_print, cur_index, msg_level);
msg_level = -1;
start_print = cur_index;
break;
}
}
}
- _call_console_drivers(con, start_print, end, msg_level);
+ _call_console_drivers(start_print, end, msg_level);
}
static void emit_log_char(char c)
@@ -389,42 +398,33 @@
*/
asmlinkage int printk(const char *fmt, ...)
{
- static struct {
- char buf[1024];
- unsigned long semi_random;
- } printk_buf;
- static int log_level_unknown = 1;
- unsigned long sr_copy;
- unsigned long flags;
- struct console *con;
- int printed_len;
- va_list args;
- char *p;
+ va_list args;
+ unsigned long flags;
+ int printed_len;
+ char *p;
+ 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);
- spin_lock_init(&console_lock);
+ /* And make sure that we print immediately */
+ init_MUTEX(&console_sem);
}
/* This stops the holder of console_sem just where we want him */
spin_lock_irqsave(&logbuf_lock, flags);
/* Emit the output into the temporary buffer */
- printk_buf.semi_random += jiffies;
- sr_copy = printk_buf.semi_random;
va_start(args, fmt);
- printed_len = vsnprintf(printk_buf.buf, sizeof(printk_buf.buf), fmt, args);
+ printed_len = vsnprintf(printk_buf, sizeof(printk_buf), fmt, args);
va_end(args);
- if (sr_copy != printk_buf.semi_random)
- panic("buffer overrun in printk()");
-
/*
* Copy the output into log_buf. If the caller didn't provide
* appropriate log level tags, we insert them here
*/
- for (p = printk_buf.buf; *p; p++) {
+ for (p = printk_buf; *p; p++) {
if (log_level_unknown) {
if (p[0] != '<' || p[1] < '0' || p[1] > '7' || p[2] != '>') {
emit_log_char('<');
@@ -437,22 +437,23 @@
if (*p == '\n')
log_level_unknown = 1;
}
- spin_unlock_irqrestore(&logbuf_lock, flags);
- spin_lock(&console_lock);
- for (con = console_drivers; con; con = con->next) {
+ if (!down_trylock(&console_sem)) {
/*
- * We own the drivers list. We can drop the lock and
- * let release_console_sem() print the text
+ * We own the drivers. We can drop the spinlock and let
+ * release_console_sem() print the text
*/
- spin_unlock(&console_lock);
- if ((con->flags & CON_ENABLED) && con->write) {
- if (!down_trylock(&con->lock))
- release_console_sem(con->device(con));
- }
- spin_lock(&console_lock);
+ spin_unlock_irqrestore(&logbuf_lock, flags);
+ console_may_schedule = 0;
+ release_console_sem();
+ } else {
+ /*
+ * Someone else owns the drivers. We drop the spinlock, which
+ * allows the semaphore holder to proceed and to call the
+ * console drivers with the output which we just produced.
+ */
+ spin_unlock_irqrestore(&logbuf_lock, flags);
}
- spin_unlock(&console_lock);
return printed_len;
}
EXPORT_SYMBOL(printk);
@@ -461,41 +462,24 @@
* acquire_console_sem - lock the console system for exclusive use.
*
* Acquires a semaphore which guarantees that the caller has
- * exclusive access to a console system.
+ * exclusive access to the console system and the console_drivers list.
*
* Can sleep, returns nothing.
*/
-void acquire_console_sem(kdev_t device)
+void acquire_console_sem(void)
{
- struct console *con;
-
if (in_interrupt())
BUG();
-
- spin_lock(&console_lock);
- /* Look for new messages */
- for (con = console_drivers; con; con = con->next) {
- if (con->device(con) == device)
- break;
- }
- spin_unlock(&console_lock);
-
- if (con) {
- down(&con->lock);
- //driver->may_schedule = 1;
- }
+ down(&console_sem);
+ console_may_schedule = 1;
}
EXPORT_SYMBOL(acquire_console_sem);
/**
* release_console_sem - unlock the console system
*
- * Releases the semaphore which the caller holds that is shared between
- * the TTY and console system. This function is the most complex. It can
- * be called by a driver that only has a console i.e lp console and no
- * tty, the tty system that has no console associated with it, or the final
- * type which is hardware driven by both a console driver and tty driver.
- * We have to handle all 3 cases.
+ * Releases the semaphore which the caller holds on the console system
+ * and the console driver list.
*
* While the semaphore was held, console output may have been buffered
* by printk(). If this is the case, release_console_sem() emits
@@ -505,48 +489,28 @@
*
* release_console_sem() may be called from any context.
*/
-void release_console_sem(kdev_t device)
+void release_console_sem(void)
{
- struct tty_driver *driver = get_tty_driver(device);
+ unsigned long flags;
unsigned long _con_start, _log_end;
unsigned long must_wake_klogd = 0;
- unsigned long flags;
- struct console *con;
- if (driver && driver->console)
- con = driver->console;
- else {
- spin_lock(&console_lock);
- for (con = console_drivers; con; con = con->next) {
- if (con->device(con) == device)
- break;
- }
- spin_unlock(&console_lock);
- }
-
- if (con) {
- for ( ; ; ) {
- spin_lock_irqsave(&logbuf_lock, flags);
- must_wake_klogd |= log_start - log_end;
- if (con_start == log_end)
- break; /* Nothing to print */
- _con_start = con_start;
- _log_end = log_end;
- con_start = log_end; /* Flush */
- spin_unlock_irqrestore(&logbuf_lock, flags);
- call_console_drivers(con, _con_start, _log_end);
- }
+ for ( ; ; ) {
+ spin_lock_irqsave(&logbuf_lock, flags);
+ must_wake_klogd |= log_start - log_end;
+ if (con_start == log_end)
+ break; /* Nothing to print */
+ _con_start = con_start;
+ _log_end = log_end;
+ con_start = log_end; /* Flush */
spin_unlock_irqrestore(&logbuf_lock, flags);
- if (must_wake_klogd && !oops_in_progress)
- wake_up_interruptible(&log_wait);
- up(&con->lock);
- return;
- }
-
- if (driver) {
- driver->may_schedule = 0;
- up(driver->tty_lock);
+ call_console_drivers(_con_start, _log_end);
}
+ console_may_schedule = 0;
+ up(&console_sem);
+ spin_unlock_irqrestore(&logbuf_lock, flags);
+ if (must_wake_klogd && !oops_in_progress)
+ wake_up_interruptible(&log_wait);
}
/** console_conditional_schedule - yield the CPU if required
@@ -557,9 +521,9 @@
*
* Must be called within acquire_console_sem().
*/
-void console_conditional_schedule(struct tty_driver *driver)
+void console_conditional_schedule(void)
{
- if (driver->may_schedule && current->need_resched) {
+ if (console_may_schedule && current->need_resched) {
set_current_state(TASK_RUNNING);
schedule();
}
@@ -571,6 +535,18 @@
}
EXPORT_SYMBOL(console_print);
+void console_unblank(void)
+{
+ struct console *c;
+
+ acquire_console_sem();
+ for (c = console_drivers; c != NULL; c = c->next)
+ if ((c->flags & CON_ENABLED) && c->unblank)
+ c->unblank();
+ release_console_sem();
+}
+EXPORT_SYMBOL(console_unblank);
+
/*
* The console driver calls this routine during kernel initialization
* to register the console printing procedure with printk() and to
@@ -579,8 +555,8 @@
*/
void register_console(struct console * console)
{
+ int i;
unsigned long flags;
- int i;
/*
* See if we want to use this console driver. If we
@@ -626,7 +602,7 @@
* Put this console in the list - keep the
* preferred driver at the head of the list.
*/
- spin_lock(&console_lock);
+ acquire_console_sem();
if ((console->flags & CON_CONSDEV) || console_drivers == NULL) {
console->next = console_drivers;
console_drivers = console;
@@ -634,19 +610,15 @@
console->next = console_drivers->next;
console_drivers->next = console;
}
- spin_unlock(&console_lock);
-
- init_MUTEX(&console->lock);
-
if (console->flags & CON_PRINTBUFFER) {
/*
- * release_console_sem() will print out the buffered messages for us.
+ * release_cosole_sem() will print out the buffered messages for us.
*/
spin_lock_irqsave(&logbuf_lock, flags);
con_start = log_start;
spin_unlock_irqrestore(&logbuf_lock, flags);
}
- release_console_sem(console->device(console));
+ release_console_sem();
}
EXPORT_SYMBOL(register_console);
@@ -655,9 +627,7 @@
struct console *a,*b;
int res = 1;
- release_console_sem(console->device(console));
-
- spin_lock(&console_lock);
+ acquire_console_sem();
if (console_drivers == console) {
console_drivers=console->next;
res = 0;
@@ -679,7 +649,8 @@
if (console_drivers == NULL)
preferred_console = -1;
- spin_unlock(&console_lock);
+
+ release_console_sem();
return res;
}
EXPORT_SYMBOL(unregister_console);
|