Enabled /prof/kptrace collection of anything which goes into cprintf
[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
13 spinlock_t output_lock = SPINLOCK_INITIALIZER_IRQSAVE;
14
15 void putch(int ch, int **cnt)
16 {
17         cputchar(ch);
18         **cnt = **cnt + 1;
19 }
20
21 // buffered putch to (potentially) speed up printing.
22 // static buffer is safe because output_lock must be held.
23 // ch == -1 flushes the buffer.
24 void buffered_putch(int ch, int **cnt)
25 {
26         #define buffered_putch_bufsize 64
27         static char buf[buffered_putch_bufsize];
28         static int buflen = 0;
29
30         if(ch != -1)
31         {
32                 buf[buflen++] = ch;
33                 **cnt = **cnt + 1;
34         }
35
36         if(ch == -1 || buflen == buffered_putch_bufsize)
37         {
38                 cputbuf(buf,buflen);
39                 buflen = 0;
40         }
41 }
42
43 int vcprintf(const char *fmt, va_list ap)
44 {
45         struct per_cpu_info *pcpui;
46         extern int booting;
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(false, 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 }