Still annotating the kernel
[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 <arch/types.h>
6
7 #include <atomic.h>
8 #include <stdio.h>
9 #include <stdarg.h>
10
11 uint32_t output_lock = 0;
12
13 void putch(int ch, int **cnt)
14 {
15         cputchar(ch);
16         **cnt = **cnt + 1;
17 }
18
19 // buffered putch to (potentially) speed up printing.
20 // static buffer is safe because output_lock must be held.
21 // ch == -1 flushes the buffer.
22 void buffered_putch(int ch, int **cnt)
23 {
24         #define buffered_putch_bufsize 64
25         static char buf[buffered_putch_bufsize];
26         static int buflen = 0;
27
28         if(ch != -1)
29         {
30                 buf[buflen++] = ch;
31                 **cnt = **cnt + 1;
32         }
33
34         if(ch == -1 || buflen == buffered_putch_bufsize)
35         {
36                 cputbuf(buf,buflen);
37                 buflen = 0;
38         }
39 }
40
41 int vcprintf(const char *fmt, va_list ap)
42 {
43         int cnt = 0;
44         int *cntp = &cnt;
45         volatile int i;
46
47         // lock all output.  this will catch any printfs at line granularity
48         spin_lock_irqsave(&output_lock);
49
50         // do the buffered printf
51         vprintfmt(buffered_putch, &cntp, fmt, ap);
52
53         // write out remaining chars in the buffer
54         buffered_putch(-1,&cntp);
55
56         spin_unlock_irqsave(&output_lock);
57
58         return cnt;
59 }
60
61 int cprintf(const char *fmt, ...)
62 {
63         va_list ap;
64         int cnt;
65
66         va_start(ap, fmt);
67         cnt = vcprintf(fmt, ap);
68         va_end(ap);
69
70         return cnt;
71 }