net: tcp: Don't increment snd.nxt
[akaros.git] / kern / src / printf.c
1 // Simple implementation of cprintf console output for the kernel,
2 // based on printfmt() and the kernel console's cputchar().
3
4 #include <arch/arch.h>
5 #include <ros/common.h>
6
7 #include <atomic.h>
8 #include <stdio.h>
9 #include <stdarg.h>
10 #include <smp.h>
11 #include <kprof.h>
12 #include <init.h>
13
14 spinlock_t output_lock = SPINLOCK_INITIALIZER_IRQSAVE;
15
16 void putch(int ch, int **cnt)
17 {
18         cputchar(ch);
19         **cnt = **cnt + 1;
20 }
21
22 // buffered putch to (potentially) speed up printing.
23 // static buffer is safe because output_lock must be held.
24 // ch == -1 flushes the buffer.
25 void buffered_putch(int ch, int **cnt)
26 {
27         #define buffered_putch_bufsize 64
28         static char buf[buffered_putch_bufsize];
29         static int buflen = 0;
30
31         if(ch != -1)
32         {
33                 buf[buflen++] = ch;
34                 **cnt = **cnt + 1;
35         }
36
37         if(ch == -1 || buflen == buffered_putch_bufsize)
38         {
39                 cputbuf(buf,buflen);
40                 buflen = 0;
41         }
42 }
43
44 int vcprintf(const char *fmt, va_list ap)
45 {
46         struct per_cpu_info *pcpui;
47         int cnt = 0;
48         int *cntp = &cnt;
49         volatile int i;
50         int8_t irq_state = 0;
51         va_list args;
52
53         va_copy(args, ap);
54         trace_vprintk(fmt, args);
55         va_end(args);
56
57         /* this ktrap depth stuff is in case the kernel faults in a printfmt call.
58          * we disable the locking if we're in a fault handler so that we don't
59          * deadlock. */
60         if (booting)
61                 pcpui = &per_cpu_info[0];
62         else
63                 pcpui = &per_cpu_info[core_id()];
64         /* lock all output.  this will catch any printfs at line granularity.  when
65          * tracing, we short-circuit the main lock call, so as not to clobber the
66          * results as we print. */
67         if (!ktrap_depth(pcpui)) {
68                 #ifdef CONFIG_TRACE_LOCKS
69                 disable_irqsave(&irq_state);
70                 __spin_lock(&output_lock);
71                 #else
72                 spin_lock_irqsave(&output_lock);
73                 #endif
74         }
75
76         // do the buffered printf
77         vprintfmt((void*)buffered_putch, (void*)&cntp, fmt, ap);
78
79         // write out remaining chars in the buffer
80         buffered_putch(-1,&cntp);
81
82         if (!ktrap_depth(pcpui)) {
83                 #ifdef CONFIG_TRACE_LOCKS
84                 __spin_unlock(&output_lock);
85                 enable_irqsave(&irq_state);
86                 #else
87                 spin_unlock_irqsave(&output_lock);
88                 #endif
89         }
90
91         return cnt;
92 }
93
94 int cprintf(const char *fmt, ...)
95 {
96         va_list ap;
97         int cnt;
98
99         if (!fmt)
100                 return 0;
101
102         va_start(ap, fmt);
103         cnt = vcprintf(fmt, ap);
104         va_end(ap);
105
106         return cnt;
107 }