Add a kernel log buffer
authorRonald G. Minnich <rminnich@google.com>
Mon, 13 Jan 2014 21:56:47 +0000 (13:56 -0800)
committerBarret Rhoden <brho@cs.berkeley.edu>
Fri, 17 Jan 2014 23:49:35 +0000 (15:49 -0800)
This is handy when your laptop keeps overrunning your screen.

cat '#c/kmesg' > '#r/xyz' to put it somewhere.

If you just cat it, it never ends. Sorry. I tried.

Signed-off-by: Ronald G. Minnich <rminnich@google.com>
kern/arch/x86/console.c
kern/drivers/dev/cons.c

index 2522a89..879522b 100644 (file)
@@ -645,6 +645,7 @@ int cons_get_any_char(void)
 /* output a character to all console outputs (monitor and all serials) */
 void cons_putc(int c)
 {
+       void logbuf(int c);
        #ifdef CONFIG_TRACE_LOCKS
        int8_t irq_state = 0;
        disable_irqsave(&irq_state);
@@ -658,6 +659,7 @@ void cons_putc(int c)
        #endif
        //lpt_putc(c);  /* very slow on the nehalem */
        cga_putc(c);
+       logbuf(c);
 
        #ifdef CONFIG_TRACE_LOCKS
        __spin_unlock(&console_lock);
index 858a555..8248780 100644 (file)
@@ -842,6 +842,24 @@ consclose(struct chan *c)
        }
 }
 
+/* we do it this way to avoid the many fun deadlock opportunities
+ * we keep hitting. And, if you don't suck it
+ * out soon enough, you lost it. No real effort to ensure goodness
+ * here as it can get called anywhere. Barret will fix it.
+ */
+static uint8_t logbuffer[1<<20];
+static int index = 0;
+static struct queue *logqueue = NULL;
+static int reading_kmesg = 0;
+void logbuf(int c)
+{
+       if (reading_kmesg)
+               return;
+       if (index > 1<<20)
+               return;
+       logbuffer[index++] = c;
+}
+
 static long
 consread(struct chan *c, void *buf, long n, int64_t offset)
 {
@@ -971,10 +989,23 @@ consread(struct chan *c, void *buf, long n, int64_t offset)
                kfree(p);
                poperror();
                return n;
-#if 0
        case Qklog:
-               return qread(klogq, buf, n);
-
+               //return qread(klogq, buf, n);  
+               /* the queue gives us some elasticity for log reading. */
+               if (! logqueue)
+                       logqueue = qopen(1<<20, 0, 0, 0);
+               if (logqueue){
+                       int ret;
+                       /* atomic sets/gets are not that important in this case. */
+                       reading_kmesg = 1;
+                       qwrite(logqueue, logbuffer, index);
+                       index = 0;
+                       ret = qread(logqueue, buf, n);
+                       reading_kmesg = 0;
+                       return ret;
+               }
+               break;
+#if 0
        case Qkprint:
                rlock(&(&kprintq)->rwlock);
                if(waserror()){