Merge branch 'ivy'
[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 <arch/types.h>
10
11 #include <atomic.h>
12 #include <stdio.h>
13 #include <stdarg.h>
14
15 uint32_t output_lock = 0;
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 buf[buffered_putch_bufsize];
30         static int 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
52         spin_lock_irqsave(&output_lock);
53
54         // do the buffered printf
55         vprintfmt(buffered_putch, &cntp, fmt, ap);
56
57         // write out remaining chars in the buffer
58         buffered_putch(-1,&cntp);
59
60         spin_unlock_irqsave(&output_lock);
61
62         return cnt;
63 }
64
65 int cprintf(const char *fmt, ...)
66 {
67         va_list ap;
68         int cnt;
69
70         va_start(ap, fmt);
71         cnt = vcprintf(fmt, ap);
72         va_end(ap);
73
74         return cnt;
75 }