parlib: Make parlib printfs safe
authorBarret Rhoden <brho@cs.berkeley.edu>
Tue, 25 Apr 2017 17:40:38 +0000 (13:40 -0400)
committerBarret Rhoden <brho@cs.berkeley.edu>
Wed, 3 May 2017 16:13:02 +0000 (12:13 -0400)
You can't call glibc's printf from certain contexts: notably vcore context
or when a uthread disabled notifications.  If you do, you'll grab a mutex
in glibc (the IO lock, which is changing in an upcoming patch), and we'll
panic - you can't block in those contexts.

But there's no need to manually call __vc_ctx_fprintf() - we can catch it
with a macro.  Yes, it's nasty.  And it works for both printf() and
fprintf(), but only for stdout and stderr streams.

Also, for this to work, any code that could be called from vcore context
should include parlib/stdio.h, not stdio.h.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
tests/hello.c
user/parlib/include/parlib/ros_debug.h
user/parlib/include/parlib/stdio.h
user/parlib/panic.c
user/parlib/x86/vcore.c

index 73da4f2..53618ac 100644 (file)
@@ -1,5 +1,5 @@
 #include <stdlib.h>
-#include <stdio.h>
+#include <parlib/stdio.h>
 #include <parlib/parlib.h>
 #include <unistd.h>
 #include <signal.h>
index 412ce9d..f86b999 100644 (file)
@@ -2,24 +2,10 @@
 
 #include <parlib/common.h>
 #include <parlib/parlib.h>
-#include <parlib/vcore.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <stdio.h>
+#include <parlib/stdio.h>
 
 __BEGIN_DECLS
 
-#define debug_printf(...) {                                                    \
-       char buf[128];                                                             \
-       int ret = snprintf(buf, sizeof(buf), __VA_ARGS__);                         \
-       write(2, buf, ret);                                                        \
-}
-
-#define I_AM_HERE debug_printf("PID %d, vcore %d is in %s() at %s:%d\n",       \
-                               getpid(), vcore_id(), __FUNCTION__, __FILE__,   \
-                               __LINE__);
-
 void trace_printf(const char *fmt, ...);
 
 /* For a poor-mans function tracer (can add these with spatch) */
index 0166c00..572b473 100644 (file)
@@ -8,6 +8,11 @@
 
 #include <stdio.h>
 #include <stdarg.h>
+#include <parlib/vcore.h>
+#include <parlib/uthread.h>
+#include <parlib/assert.h>
+#include <sys/types.h>
+#include <unistd.h>
 
 __BEGIN_DECLS
 
@@ -22,4 +27,55 @@ int akaros_printf(const char *format, ...);
 #define printd(args...) {}
 #endif
 
+/* Technically, this is also used by uthreads with notifs disabled. */
+#define __vc_ctx_fprintf(f_stream, ...)                                        \
+do {                                                                           \
+       char buf[128];                                                             \
+       int ret, fd;                                                               \
+                                                                                  \
+       if (f_stream == stdout)                                                    \
+               fd = 1;                                                                \
+       else if (f_stream == stderr)                                               \
+               fd = 2;                                                                \
+       else                                                                       \
+               panic("__vc_ctx tried to fprintf to non-std stream!");                 \
+       ret = snprintf(buf, sizeof(buf), __VA_ARGS__);                             \
+       write(fd, buf, ret);                                                       \
+} while (0)
+
+static inline bool __safe_to_printf(void)
+{
+       if (in_vcore_context())
+               return FALSE;
+       if (current_uthread) {
+               if (current_uthread->notif_disabled_depth)
+                       return FALSE;
+               if (current_uthread->flags & UTHREAD_DONT_MIGRATE)
+                       return FALSE;
+       }
+       return TRUE;
+}
+
+#define fprintf(f, ...)                                                        \
+do {                                                                           \
+       if (__safe_to_printf())                                                    \
+               fprintf(f, __VA_ARGS__);                                               \
+       else                                                                       \
+               __vc_ctx_fprintf(f, __VA_ARGS__);                                      \
+} while (0)
+
+
+#define printf(...)                                                            \
+do {                                                                           \
+       if (__safe_to_printf())                                                    \
+               printf(__VA_ARGS__);                                                   \
+       else                                                                       \
+               __vc_ctx_fprintf(stdout, __VA_ARGS__);                                 \
+} while (0)
+
+#define I_AM_HERE __vc_ctx_fprintf(stderr,                                     \
+                                   "PID %d, vcore %d is in %s() at %s:%d\n",   \
+                                   getpid(), vcore_id(), __FUNCTION__,         \
+                                   __FILE__, __LINE__)
+
 __END_DECLS
index bcee774..ecac76c 100644 (file)
@@ -1,9 +1,9 @@
 #include <parlib/arch/arch.h>
-#include <stdio.h>
-#include <stdarg.h>
+#include <parlib/stdio.h>
 #include <parlib/assert.h>
-#include <stdlib.h>
 #include <parlib/ros_debug.h>
+#include <stdarg.h>
+#include <stdlib.h>
 
 static void __attribute__((constructor)) parlib_stdio_init(void)
 {
@@ -45,7 +45,7 @@ void _panic(const char *file, int line, const char *fmt, ...)
 
 void _assert_failed(const char *file, int line, const char *msg)
 {
-       debug_printf("[user] %s:%d, vcore %d, Assertion failed: %s\n", file, line,
-                    vcore_id(), msg);
+       fprintf(stderr, "[user] %s:%d, vcore %d, Assertion failed: %s\n", file,
+               line, vcore_id(), msg);
        fatal_backtrace();
 }
index a56e79e..32243d4 100644 (file)
@@ -395,7 +395,7 @@ void print_user_context(struct user_context *ctx)
                fprintf_vm_tf(stdout, &ctx->tf.vm_tf);
                break;
        default:
-               printf("Unknown context type %d\n", ctx->type);
+               fprintf(stderr, "Unknown context type %d\n", ctx->type);
        }
 }