Adds chaninfo()
[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 #ifdef __SHARC__
5 #pragma nosharc
6 #endif
7
8 #include <arch/arch.h>
9 #include <ros/common.h>
10
11 #include <atomic.h>
12 #include <stdio.h>
13 #include <stdarg.h>
14
15 spinlock_t output_lock = SPINLOCK_INITIALIZER_IRQSAVE;
16
17 void putch(int ch, int **cnt)
18 {
19         cputchar(ch);
20         **cnt = **cnt + 1;
21 }
22
23 // buffered putch to (potentially) speed up printing.
24 // static buffer is safe because output_lock must be held.
25 // ch == -1 flushes the buffer.
26 void buffered_putch(int ch, int **cnt)
27 {
28         #define buffered_putch_bufsize 64
29         static char LCKD(&output_lock) (RO buf)[buffered_putch_bufsize];
30         static int LCKD(&output_lock) buflen = 0;
31
32         if(ch != -1)
33         {
34                 buf[buflen++] = ch;
35                 **cnt = **cnt + 1;
36         }
37
38         if(ch == -1 || buflen == buffered_putch_bufsize)
39         {
40                 cputbuf(buf,buflen);
41                 buflen = 0;
42         }
43 }
44
45 int vcprintf(const char *fmt, va_list ap)
46 {
47         int cnt = 0;
48         int *cntp = &cnt;
49         volatile int i;
50
51         /* lock all output.  this will catch any printfs at line granularity.  when
52          * tracing, we short-circuit the main lock call, so as not to clobber the
53          * results as we print. */
54         #ifdef CONFIG_TRACE_LOCKS
55         int8_t irq_state = 0;
56         disable_irqsave(&irq_state);
57         __spin_lock(&output_lock);
58         #else
59         spin_lock_irqsave(&output_lock);
60         #endif
61
62         // do the buffered printf
63         #ifdef __DEPUTY__
64         vprintfmt(buffered_putch, &cntp, fmt, ap);
65         #else
66         vprintfmt((void*)buffered_putch, (void*)&cntp, fmt, ap);
67         #endif
68
69         // write out remaining chars in the buffer
70         buffered_putch(-1,&cntp);
71
72         #ifdef CONFIG_TRACE_LOCKS
73         __spin_unlock(&output_lock);
74         enable_irqsave(&irq_state);
75         #else
76         spin_unlock_irqsave(&output_lock);
77         #endif
78
79         return cnt;
80 }
81
82 int cprintf(const char *fmt, ...)
83 {
84         va_list ap;
85         int cnt;
86
87         if (!fmt)
88                 return 0;
89
90         va_start(ap, fmt);
91         cnt = vcprintf(fmt, ap);
92         va_end(ap);
93
94         return cnt;
95 }