Fixes VFS open bug
[akaros.git] / kern / src / printf.c
index 110add4..43b6d01 100644 (file)
@@ -1,32 +1,80 @@
 // Simple implementation of cprintf console output for the kernel,
 // based on printfmt() and the kernel console's cputchar().
 
-#ifdef __DEPUTY__
-#pragma nodeputy
+#ifdef __SHARC__
+#pragma nosharc
 #endif
 
-#include <arch/types.h>
-#include <arch/atomic.h>
+#include <arch/arch.h>
+#include <ros/common.h>
+
+#include <atomic.h>
 #include <stdio.h>
 #include <stdarg.h>
 
-uint32_t output_lock = 0;
+spinlock_t output_lock = SPINLOCK_INITIALIZER_IRQSAVE;
 
-static void putch(int ch, int **cnt)
+void putch(int ch, int **cnt)
 {
        cputchar(ch);
        **cnt = **cnt + 1;
 }
 
+// buffered putch to (potentially) speed up printing.
+// static buffer is safe because output_lock must be held.
+// ch == -1 flushes the buffer.
+void buffered_putch(int ch, int **cnt)
+{
+       #define buffered_putch_bufsize 64
+       static char LCKD(&output_lock) (RO buf)[buffered_putch_bufsize];
+       static int LCKD(&output_lock) buflen = 0;
+
+       if(ch != -1)
+       {
+               buf[buflen++] = ch;
+               **cnt = **cnt + 1;
+       }
+
+       if(ch == -1 || buflen == buffered_putch_bufsize)
+       {
+               cputbuf(buf,buflen);
+               buflen = 0;
+       }
+}
+
 int vcprintf(const char *fmt, va_list ap)
 {
        int cnt = 0;
        int *cntp = &cnt;
+       volatile int i;
 
-       // lock all output.  this will catch any printfs at line granularity
+       /* lock all output.  this will catch any printfs at line granularity.  when
+        * tracing, we short-circuit the main lock call, so as not to clobber the
+        * results as we print. */
+       #ifdef CONFIG_TRACE_LOCKS
+       int8_t irq_state = 0;
+       disable_irqsave(&irq_state);
+       __spin_lock(&output_lock);
+       #else
        spin_lock_irqsave(&output_lock);
-       vprintfmt((void*)putch, (void**)&cntp, fmt, ap);
+       #endif
+
+       // do the buffered printf
+       #ifdef __DEPUTY__
+       vprintfmt(buffered_putch, &cntp, fmt, ap);
+       #else
+       vprintfmt((void*)buffered_putch, (void*)&cntp, fmt, ap);
+       #endif
+
+       // write out remaining chars in the buffer
+       buffered_putch(-1,&cntp);
+
+       #ifdef CONFIG_TRACE_LOCKS
+       __spin_unlock(&output_lock);
+       enable_irqsave(&irq_state);
+       #else
        spin_unlock_irqsave(&output_lock);
+       #endif
 
        return cnt;
 }
@@ -36,6 +84,9 @@ int cprintf(const char *fmt, ...)
        va_list ap;
        int cnt;
 
+       if (!fmt)
+               return 0;
+
        va_start(ap, fmt);
        cnt = vcprintf(fmt, ap);
        va_end(ap);