net: tcp: Fix up the receive window
[akaros.git] / kern / src / printf.c
index e870dca..6e54a04 100644 (file)
@@ -2,13 +2,16 @@
 // based on printfmt() and the kernel console's cputchar().
 
 #include <arch/arch.h>
-#include <arch/types.h>
+#include <ros/common.h>
 
 #include <atomic.h>
 #include <stdio.h>
 #include <stdarg.h>
+#include <smp.h>
+#include <kprof.h>
+#include <init.h>
 
-uint32_t output_lock = 0;
+spinlock_t output_lock = SPINLOCK_INITIALIZER_IRQSAVE;
 
 void putch(int ch, int **cnt)
 {
@@ -40,20 +43,50 @@ void buffered_putch(int ch, int **cnt)
 
 int vcprintf(const char *fmt, va_list ap)
 {
+       struct per_cpu_info *pcpui;
        int cnt = 0;
        int *cntp = &cnt;
        volatile int i;
-
-       // lock all output.  this will catch any printfs at line granularity
-       spin_lock_irqsave(&output_lock);
+       int8_t irq_state = 0;
+       va_list args;
+
+       va_copy(args, ap);
+       trace_vprintk(fmt, args);
+       va_end(args);
+
+       /* this ktrap depth stuff is in case the kernel faults in a printfmt call.
+        * we disable the locking if we're in a fault handler so that we don't
+        * deadlock. */
+       if (booting)
+               pcpui = &per_cpu_info[0];
+       else
+               pcpui = &per_cpu_info[core_id()];
+       /* 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. */
+       if (!ktrap_depth(pcpui)) {
+               #ifdef CONFIG_TRACE_LOCKS
+               disable_irqsave(&irq_state);
+               __spin_lock(&output_lock);
+               #else
+               spin_lock_irqsave(&output_lock);
+               #endif
+       }
 
        // do the buffered printf
-       vprintfmt(buffered_putch, &cntp, fmt, ap);
+       vprintfmt((void*)buffered_putch, (void*)&cntp, fmt, ap);
 
        // write out remaining chars in the buffer
        buffered_putch(-1,&cntp);
 
-       spin_unlock_irqsave(&output_lock);
+       if (!ktrap_depth(pcpui)) {
+               #ifdef CONFIG_TRACE_LOCKS
+               __spin_unlock(&output_lock);
+               enable_irqsave(&irq_state);
+               #else
+               spin_unlock_irqsave(&output_lock);
+               #endif
+       }
 
        return cnt;
 }
@@ -63,6 +96,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);