*** printk.c~ Fri Jun 30 16:24:38 2000 --- printk.c Sun Jul 2 05:20:00 2000 *************** *** 19,32 **** #include #include #include #include #define LOG_BUF_LEN (16384) #define LOG_BUF_MASK (LOG_BUF_LEN-1) - static char buf[1024]; - /* printk's without a loglevel use this.. */ #define DEFAULT_MESSAGE_LOGLEVEL 4 /* KERN_WARNING */ --- 19,31 ---- #include #include #include + #include #include #define LOG_BUF_LEN (16384) #define LOG_BUF_MASK (LOG_BUF_LEN-1) /* printk's without a loglevel use this.. */ #define DEFAULT_MESSAGE_LOGLEVEL 4 /* KERN_WARNING */ *************** *** 253,271 **** asmlinkage int printk(const char *fmt, ...) { va_list args; int i; char *msg, *p, *buf_end; int line_feed; static signed char msg_level = -1; long flags; va_start(args, fmt); i = vsprintf(buf + 3, fmt, args); /* hopefully i < sizeof(buf)-4 */ buf_end = buf + 3 + i; va_end(args); ! spin_lock_irqsave(&console_lock, flags); for (p = buf + 3; p < buf_end; p++) { msg = p; if (msg_level < 0) { --- 252,318 ---- asmlinkage int printk(const char *fmt, ...) { + static spinlock_t printk_buf_lock = SPIN_LOCK_UNLOCKED; + static struct task_struct *printk_buf_holder = 0; + static char printk_buf[1024]; + static atomic_t lost_message = ATOMIC_INIT(0); + va_list args; int i; char *msg, *p, *buf_end; int line_feed; static signed char msg_level = -1; long flags; + char *buf = printk_buf; + + if (!spin_trylock(&printk_buf_lock)) { + /* Couldn't get spinlock... do we already have it? */ + if (printk_buf_holder == current) { + /* We are already in printk... so we would be deadlocking + * mark this as such and we'll print a message later... + */ + atomic_inc(&lost_message); + return 0; + } else { + /* Nope, wait for someone to release it... */ + spin_lock(&printk_buf_lock); + } + } + + /* We are now the proud holders of the printk_buf_lock! :) */ + printk_buf_holder = current; + + if (atomic_read(&lost_message)) { + struct console *c = console_drivers; + int Count = atomic_read(&lost_message); + char dropped[] = + "XX recursive printk's detected, message(s) lost\n"; + /* Small window to lose message... not critical though */ + atomic_set(&lost_message, 0); + + if (Count < 100) { + if (Count > 9) + dropped[0] = (char)(Count / 10); + else + dropped[0] = ' '; + + dropped[1] = Count % 10; + } + + while(c) { + if ((c->flags & CON_ENABLED) && c->write) + c->write(c, dropped, 49); + c = c->next; + } + } va_start(args, fmt); i = vsprintf(buf + 3, fmt, args); /* hopefully i < sizeof(buf)-4 */ buf_end = buf + 3 + i; va_end(args); ! spin_lock_irqsave(&console_lock, flags); + for (p = buf + 3; p < buf_end; p++) { msg = p; if (msg_level < 0) { *************** *** 308,315 **** --- 355,366 ---- if (line_feed) msg_level = -1; } + spin_unlock_irqrestore(&console_lock, flags); wake_up_interruptible(&log_wait); + + spin_unlock(&printk_buf_lock); + return i; }