Add uthread_usleep which sleeps in microseconds.
[akaros.git] / user / parlib / debug.c
1 // Implementation of cprintf console output for user processes,
2 // based on printfmt() and the sys_cputs() system call.
3 //
4 // cprintf is a debugging statement, not a generic output statement.
5 // It is very important that it always go to the console, especially when
6 // debugging file descriptor code!
7
8 #include <ros/common.h>
9 #include <parlib.h>
10 #include <stdio.h>
11 #include <spinlock.h>
12
13 // Collect up to BUF_SIZE characters into a buffer
14 // and perform ONE system call to print all of them,
15 // in order to make the lines output to the console atomic
16 // and prevent interrupts from causing context switches
17 // in the middle of a console output line and such.
18 #define BUF_SIZE 256
19 typedef struct debugbuf {
20         size_t  idx;    // current buffer index
21         size_t  cnt;    // total bytes printed so far
22         uint8_t buf[BUF_SIZE];
23 } debugbuf_t;
24
25
26 static void putch(int ch, debugbuf_t **b)
27 {
28         (*b)->buf[(*b)->idx++] = ch;
29         if ((*b)->idx == BUF_SIZE) {
30                 sys_cputs((*b)->buf, (*b)->idx);
31                 (*b)->idx = 0;
32         }
33         (*b)->cnt++;
34 }
35
36 int ros_vdebug(const char *fmt, va_list ap)
37 {
38         debugbuf_t b;
39         debugbuf_t *COUNT(1) bp = &b;
40
41         b.idx = 0;
42         b.cnt = 0;
43         ros_vdebugfmt((void*)putch, (void*)&bp, fmt, ap);
44         sys_cputs(b.buf, b.idx);
45
46         return b.cnt;
47 }
48
49 int ros_debug(const char *fmt, ...)
50 {
51         va_list ap;
52         int cnt;
53
54         va_start(ap, fmt);
55         cnt = ros_vdebug(fmt, ap);
56         va_end(ap);
57
58         return cnt;
59 }
60
61 /* Poor man's Ftrace, won't work well with concurrency. */
62 static const char *blacklist[] = {
63         "whatever",
64 };
65
66 static bool is_blacklisted(const char *s)
67 {
68         for (int i = 0; i < ARRAY_SIZE(blacklist); i++) {
69                 if (!strcmp(blacklist[i], s))
70                         return TRUE;
71         }
72         return FALSE;
73 }
74
75 static int tab_depth = 0;
76 static bool print = TRUE;
77
78 void reset_print_func_depth(void)
79 {
80         tab_depth = 0;
81 }
82
83 void toggle_print_func(void)
84 {
85         print = !print;
86         printf("Func entry/exit printing is now %sabled\n", print ? "en" : "dis");
87 }
88
89 static spinlock_t lock = {0};
90
91 void __print_func_entry(const char *func, const char *file)
92 {
93         if (!print)
94                 return;
95         if (is_blacklisted(func))
96                 return;
97         spinlock_lock(&lock);
98         printd("Vcore %2d", vcore_id());        /* helps with multicore output */
99         for (int i = 0; i < tab_depth; i++)
100                 printf("\t");
101         printf("%s() in %s\n", func, file);
102         spinlock_unlock(&lock);
103         tab_depth++;
104 }
105
106 void __print_func_exit(const char *func, const char *file)
107 {
108         if (!print)
109                 return;
110         if (is_blacklisted(func))
111                 return;
112         tab_depth--;
113         spinlock_lock(&lock);
114         printd("Vcore %2d", vcore_id());
115         for (int i = 0; i < tab_depth; i++)
116                 printf("\t");
117         printf("---- %s()\n", func);
118         spinlock_unlock(&lock);
119 }