1 // Simple implementation of cprintf console output for the kernel,
2 // based on printfmt() and the kernel console's cputchar().
5 #include <ros/common.h>
14 /* Recursive lock. Would like to avoid spreading these in the kernel. */
15 static spinlock_t output_lock = SPINLOCK_INITIALIZER_IRQSAVE;
16 static int output_lock_holder = -1; /* core_id. */
17 static int output_lock_count;
21 if (output_lock_holder == core_id_early()) {
25 pcpui_var(core_id_early(), __lock_checking_enabled)--;
26 spin_lock_irqsave(&output_lock);
27 output_lock_holder = core_id_early();
28 output_lock_count = 1;
31 void print_unlock(void)
34 if (output_lock_count)
36 output_lock_holder = -1;
37 spin_unlock_irqsave(&output_lock);
38 pcpui_var(core_id_early(), __lock_checking_enabled)++;
41 /* Regardless of where we are, unlock. This is dangerous, and only used when
42 * you know you will never unwind your stack, such as for a panic. */
43 void print_unlock_force(void)
45 output_lock_holder = -1;
46 output_lock_count = 0;
47 spin_unlock_irqsave(&output_lock);
48 pcpui_var(core_id_early(), __lock_checking_enabled)++;
51 void putch(int ch, int **cnt)
57 // buffered putch to (potentially) speed up printing.
58 // static buffer is safe because output_lock must be held.
59 // ch == -1 flushes the buffer.
60 void buffered_putch(int ch, int **cnt)
62 #define buffered_putch_bufsize 64
63 static char buf[buffered_putch_bufsize];
64 static int buflen = 0;
72 if(ch == -1 || buflen == buffered_putch_bufsize)
79 int vcprintf(const char *fmt, va_list ap)
89 trace_vprintk(fmt, args);
92 // do the buffered printf
93 vprintfmt((void*)buffered_putch, (void*)&cntp, fmt, ap);
95 // write out remaining chars in the buffer
96 buffered_putch(-1,&cntp);
103 int cprintf(const char *fmt, ...)
112 cnt = vcprintf(fmt, ap);