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