kconfig: use pkg-config for ncurses detection
[akaros.git] / user / parlib / debug.c
1 #include <parlib/common.h>
2 #include <parlib/assert.h>
3 #include <parlib/stdio.h>
4 #include <parlib/parlib.h>
5 #include <unistd.h>
6 #include <parlib/spinlock.h>
7 #include <ros/common.h>
8 #include <sys/types.h>
9 #include <sys/stat.h>
10 #include <fcntl.h>
11
12 /* This is called from glibc in delicate places, like signal handlers.  We might
13  * as well just write any valid output to FD 2. */
14 int akaros_printf(const char *format, ...)
15 {
16         char buf[128];
17         va_list ap;
18         int ret;
19
20         va_start(ap, format);
21         ret = vsnprintf(buf, sizeof(buf), format, ap);
22         va_end(ap);
23         if (ret < 0)
24                 return ret;
25         write(2, buf, MIN(sizeof(buf), ret));
26         return ret;
27 }
28
29 /* Poor man's Ftrace, won't work well with concurrency. */
30 static const char *blacklist[] = {
31         "whatever",
32 };
33
34 static bool is_blacklisted(const char *s)
35 {
36         for (int i = 0; i < COUNT_OF(blacklist); i++) {
37                 if (!strcmp(blacklist[i], s))
38                         return TRUE;
39         }
40         return FALSE;
41 }
42
43 static int tab_depth = 0;
44 static bool print = TRUE;
45
46 void reset_print_func_depth(void)
47 {
48         tab_depth = 0;
49 }
50
51 void toggle_print_func(void)
52 {
53         print = !print;
54         printf("Func entry/exit printing is now %sabled\n", print ? "en" :
55                "dis");
56 }
57
58 static spinlock_t lock = {0};
59
60 void __print_func_entry(const char *func, const char *file)
61 {
62         if (!print)
63                 return;
64         if (is_blacklisted(func))
65                 return;
66         spinlock_lock(&lock);
67         printd("Vcore %2d", vcore_id()); /* helps with multicore output */
68         for (int i = 0; i < tab_depth; i++)
69                 printf("\t");
70         printf("%s() in %s\n", func, file);
71         spinlock_unlock(&lock);
72         tab_depth++;
73 }
74
75 void __print_func_exit(const char *func, const char *file)
76 {
77         if (!print)
78                 return;
79         if (is_blacklisted(func))
80                 return;
81         tab_depth--;
82         spinlock_lock(&lock);
83         printd("Vcore %2d", vcore_id());
84         for (int i = 0; i < tab_depth; i++)
85                 printf("\t");
86         printf("---- %s()\n", func);
87         spinlock_unlock(&lock);
88 }
89
90 static int kptrace;
91
92 static void trace_init(void *arg)
93 {
94         kptrace = open("#kprof/kptrace", O_WRITE);
95         if (kptrace < 0)
96                 perror("Unable to open kptrace!\n");
97 }
98
99 int trace_printf(const char *fmt, ...)
100 {
101         va_list args;
102         char buf[128];
103         int amt;
104         static parlib_once_t once = PARLIB_ONCE_INIT;
105
106         parlib_run_once(&once, trace_init, NULL);
107         if (kptrace < 0)
108                 return 0;
109         amt = snprintf(buf, sizeof(buf), "PID %d: ", getpid());
110         /* amt could be > sizeof, if we truncated. */
111         amt = MIN(amt, sizeof(buf));
112         va_start(args, fmt);
113         /* amt == sizeof is OK here */
114         amt += vsnprintf(buf + amt, sizeof(buf) - amt, fmt, args);
115         va_end(args);
116         amt = MIN(amt, sizeof(buf));
117         write(kptrace, buf, amt);
118         return amt;
119 }