The initrd now works.
[akaros.git] / user / parlib / panic.c
1 #include <parlib/arch/arch.h>
2 #include <parlib/stdio.h>
3 #include <parlib/assert.h>
4 #include <parlib/ros_debug.h>
5 #include <stdarg.h>
6 #include <stdlib.h>
7
8 static void __attribute__((constructor)) parlib_stdio_init(void)
9 {
10         if (__in_fake_parlib())
11                 return;
12         /* This isn't ideal, since it might affect some stdout streams where our
13          * parent tried to do something else.  Note that isatty() always returns
14          * TRUE, due to how we fake tcgetattr(), and that doesn't affect whatever
15          * our shells are doing to set us up. */
16         setlinebuf(stdout);
17 }
18
19 static void __attribute__((noreturn)) fatal_backtrace(void)
20 {
21         /* This will cause the kernel to print out a backtrace to the console.
22          * Short of reading /proc/self/maps or other stuff, userspace would have a
23          * hard time backtracing itself. */
24         breakpoint();
25         abort();
26 }
27
28 void _panic(const char *file, int line, const char *fmt, ...)
29 {
30         char buf[128];
31         int ret = 0;
32         va_list ap;
33
34         va_start(ap, fmt);
35         ret += snprintf(buf + ret, sizeof(buf) - ret,
36                         "[user] panic: PID %d, vcore %d, %s:%d: ",
37                         getpid(), vcore_id(), __FILE__, __LINE__);
38         /* ignore errors (ret < 0) by setting ret to be at least 0 */
39         ret = MAX(ret, 0);
40         ret += vsnprintf(buf + ret, sizeof(buf) - ret, fmt, ap);
41         ret = MAX(ret, 0);
42         ret += snprintf(buf + ret, sizeof(buf) - ret, "\n");
43         ret = MAX(ret, 0);
44         write(2, buf, ret);
45         fatal_backtrace();
46 }
47
48 void _assert_failed(const char *file, int line, const char *msg)
49 {
50         fprintf(stderr, "[user] %s:%d, vcore %d, Assertion failed: %s\n", file,
51                 line, vcore_id(), msg);
52         fatal_backtrace();
53 }