akaros/user/parlib/debug.c
<<
>>
Prefs
   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. */
  14int 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. */
  30static const char *blacklist[] = {
  31        "whatever",
  32};
  33
  34static 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
  43static int tab_depth = 0;
  44static bool print = TRUE;
  45
  46void reset_print_func_depth(void)
  47{
  48        tab_depth = 0;
  49}
  50
  51void toggle_print_func(void)
  52{
  53        print = !print;
  54        printf("Func entry/exit printing is now %sabled\n", print ? "en" :
  55               "dis");
  56}
  57
  58static spinlock_t lock = {0};
  59
  60void __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
  75void __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
  90static int kptrace;
  91
  92static 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
  99int 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}
 120