Fix virtio net handling of the header.
[akaros.git] / user / parlib / signal.c
index dacc1c3..12b1d49 100644 (file)
  *     only thing we do is allow the registration of signal handlers. 
  *     - Check each function for further notes.  */
 
-#include <signal.h>
-#include <stdio.h>
+// Needed for sigmask functions...
+#define _GNU_SOURCE
 
-#include <parlib.h>
-#include <event.h>
+#include <stdio.h>
+#include <parlib/parlib.h>
+#include <parlib/signal.h>
+#include <parlib/uthread.h>
+#include <parlib/event.h>
 #include <errno.h>
-#include <assert.h>
+#include <parlib/assert.h>
 #include <ros/procinfo.h>
 #include <ros/syscall.h>
 #include <sys/mman.h>
-#include <vcore.h> /* for print_user_context() */
-#include <waitfreelist.h>
-
-/* This is list of sigactions associated with each posix signal. */
-static struct sigaction sigactions[_NSIG - 1];
-
-/* This is a wait-free-list used to hold the data necessary to execute signal
- * handlers inside a 2LS. We are able to store them in a wfl because all
- * sigdata structs are created equal, and reuse is encouraged as uthreads
- * ask for them on demand. */
-static struct wfl sigdata_list;
-#define SIGNAL_STACK_SIZE (2*PGSIZE + sizeof(struct sigdata))
-
-/* These are the default handlers for each posix signal.  They are listed in
- * SIGNAL(7) of the Linux Programmer's Manual.  We run them as default
- * sigactions, instead of the older handlers, so that we have access to the
- * faulting context.
- *
- * Exit codes are set as suggested in the following link.  I wish I could find
- * the definitive source, but this will have to do for now.
- * http://unix.stackexchange.com/questions/99112/default-exit-code-when-process-is-terminated
- * */
-static void default_term_handler(int signr, siginfo_t *info, void *ctx)
-{
-       ros_syscall(SYS_proc_destroy, __procinfo.pid, signr, 0, 0, 0, 0);
-}
+#include <parlib/stdio.h>
+
+/* Forward declare our signal_ops functions. */
+static int __sigaltstack(__const struct sigaltstack *__restrict __ss,
+                         struct sigaltstack *__restrict __oss);
+static int __siginterrupt(int __sig, int __interrupt);
+static int __sigpending(sigset_t *__set);
+static int __sigprocmask(int __how, __const sigset_t *__restrict __set,
+                         sigset_t *__restrict __oset);
+static int __sigqueue(__pid_t __pid, int __sig, __const union sigval __val);
+static int __sigreturn(struct sigcontext *__scp);
+static int __sigstack(struct sigstack *__ss, struct sigstack *__oss);
+static int __sigsuspend(__const sigset_t *__set);
+static int __sigtimedwait(__const sigset_t *__restrict __set,
+                          siginfo_t *__restrict __info,
+                          __const struct timespec *__restrict __timeout);
+static int __sigwait(__const sigset_t *__restrict __set, int *__restrict __sig);
+static int __sigwaitinfo(__const sigset_t *__restrict __set,
+                         siginfo_t *__restrict __info);
+static int __sigself(int signo);
+
+/* The default definition of signal_ops (similar to sched_ops in uthread.c) */
+struct signal_ops default_signal_ops = {
+       .sigaltstack = __sigaltstack,
+       .siginterrupt = __siginterrupt,
+       .sigpending = __sigpending,
+       .sigprocmask = __sigprocmask,
+       .sigqueue = __sigqueue,
+       .sigreturn = __sigreturn,
+       .sigstack = __sigstack,
+       .sigsuspend = __sigsuspend,
+       .sigtimedwait = __sigtimedwait,
+       .sigwait = __sigwait,
+       .sigwaitinfo = __sigwaitinfo,
+       .sigself = __sigself
+};
 
-static void default_core_handler(int signr, siginfo_t *info, void *ctx)
+/* This is the catch all akaros event->posix signal handler.  All posix signals
+ * are received in a single akaros event type.  They are then dispatched from
+ * this function to their proper posix signal handler */
+static void handle_event(struct event_msg *ev_msg, unsigned int ev_type,
+                         void *data)
 {
-       fprintf(stderr, "Segmentation Fault (sorry, no core dump yet)\n");
-       print_user_context((struct user_context*)ctx);
-       if (info) {
-               /* ghetto, we don't have access to the PF err, since we only have a few
-                * fields available in siginfo (e.g. there's no si_trapno). */
-               fprintf(stderr, "Fault type %d at addr %p\n", info->si_errno,
-                       info->si_addr);
+       int sig_nr;
+       struct siginfo info = {0};
+       info.si_code = SI_USER;
+       struct user_context fake_uctx;
+
+       assert(ev_msg);
+       sig_nr = ev_msg->ev_arg1;
+       /* We're handling a process-wide signal, but signal handlers will want a
+        * user context.  They operate on the model that some thread got the signal,
+        * but that didn't happen on Akaros.  If we happen to have a current
+        * uthread, we can use that - perhaps that's what the user wants.  If not,
+        * we'll build a fake one representing our current call stack. */
+       if (current_uthread) {
+               trigger_posix_signal(sig_nr, &info, get_cur_uth_ctx());
        } else {
-               fprintf(stderr, "No fault info\n");
+               init_user_ctx(&fake_uctx, (uintptr_t)handle_event, get_stack_pointer());
+               trigger_posix_signal(sig_nr, &info, &fake_uctx);
        }
-       default_term_handler((1 << 7) + signr, info, ctx);
 }
 
-static void default_stop_handler(int signr, siginfo_t *info, void *ctx)
+/* Called from uthread_slim_init() */
+void init_posix_signals(void)
 {
-       fprintf(stderr, "Stop signal received!  No support to stop yet though!\n");
+       struct event_queue *posix_sig_ev_q;
+
+       signal_ops = &default_signal_ops;
+       register_ev_handler(EV_POSIX_SIGNAL, handle_event, 0);
+       posix_sig_ev_q = get_eventq(EV_MBOX_UCQ);
+       assert(posix_sig_ev_q);
+       posix_sig_ev_q->ev_flags = EVENT_IPI | EVENT_INDIR | EVENT_SPAM_INDIR |
+                                  EVENT_WAKEUP;
+       register_kevent_q(posix_sig_ev_q, EV_POSIX_SIGNAL);
 }
 
-static void default_cont_handler(int signr, siginfo_t *info, void *ctx)
+/* Swap the contents of two user contexts (not just their pointers). */
+static void swap_user_contexts(struct user_context *c1, struct user_context *c2)
 {
-       fprintf(stderr, "Cont signal received!  No support to cont yet though!\n");
-}
+       struct user_context temp_ctx;
 
-typedef void (*__sigacthandler_t)(int, siginfo_t *, void *);
-#define SIGACT_ERR     ((__sigacthandler_t) -1)        /* Error return.  */
-#define SIGACT_DFL     ((__sigacthandler_t) 0)         /* Default action.  */
-#define SIGACT_IGN     ((__sigacthandler_t) 1)         /* Ignore signal.  */
-
-static __sigacthandler_t default_handlers[] = {
-       [SIGHUP]    = default_term_handler, 
-       [SIGINT]    = default_term_handler, 
-       [SIGQUIT]   = default_core_handler, 
-       [SIGILL]    = default_core_handler, 
-       [SIGTRAP]   = default_core_handler, 
-       [SIGABRT]   = default_core_handler, 
-       [SIGIOT]    = default_core_handler, 
-       [SIGBUS]    = default_core_handler, 
-       [SIGFPE]    = default_core_handler, 
-       [SIGKILL]   = default_term_handler, 
-       [SIGUSR1]   = default_term_handler, 
-       [SIGSEGV]   = default_core_handler, 
-       [SIGUSR2]   = default_term_handler, 
-       [SIGPIPE]   = default_term_handler, 
-       [SIGALRM]   = default_term_handler, 
-       [SIGTERM]   = default_term_handler, 
-       [SIGSTKFLT] = default_term_handler, 
-       [SIGCHLD]   = SIGACT_IGN,
-       [SIGCONT]   = default_cont_handler, 
-       [SIGSTOP]   = default_stop_handler, 
-       [SIGTSTP]   = default_stop_handler, 
-       [SIGTTIN]   = default_stop_handler, 
-       [SIGTTOU]   = default_stop_handler, 
-       [SIGURG]    = default_term_handler, 
-       [SIGXCPU]   = SIGACT_IGN,
-       [SIGXFSZ]   = default_core_handler, 
-       [SIGVTALRM] = default_term_handler, 
-       [SIGPROF]   = default_term_handler, 
-       [SIGWINCH]  = SIGACT_IGN,
-       [SIGIO]     = default_term_handler, 
-       [SIGPWR]    = SIGACT_IGN,
-       [SIGSYS]    = default_core_handler
-};
+       temp_ctx = *c1;
+       *c1 = *c2;
+       *c2 = temp_ctx;
+}
 
-/* This function allocates a sigdata struct for use when running signal
- * handlers inside a 2LS. The sigdata struct returned is pre-initialized with
- * the 'stack' field pointing to a valid stack.  Space is allocated for both
- * the sigdata struct and the stack in a single mmap call.  The sigdata struct
- * just sits at the bottom of the stack, and its 'stack' field points just
- * above it.  */
-struct sigdata *alloc_sigdata()
+/* Helper for checking a stack pointer.  It's possible the context we're
+ * injecting signals into is complete garbage, so using the SP is a little
+ * dangerous. */
+static bool stack_ptr_is_sane(uintptr_t sp)
 {
-       struct sigdata *data = wfl_remove(&sigdata_list);
-       if (data == NULL) {
-               void *stack = mmap(0, SIGNAL_STACK_SIZE,
-                                  PROT_READ|PROT_WRITE|PROT_EXEC,
-                                  MAP_POPULATE|MAP_ANONYMOUS, -1, 0);
-               assert(stack != MAP_FAILED);
-               data = stack + SIGNAL_STACK_SIZE - sizeof(struct sigdata);
-               data->stack = data;
-       }
-       return data;
+       if ((sp < PGSIZE) || (sp > ULIM))
+               return FALSE;
+       return TRUE;
 }
 
-/* This function frees a previously allocated sigdata struct. */
-void free_sigdata(struct sigdata *sigdata)
+static bool uth_is_handling_sigs(struct uthread *uth)
 {
-       wfl_insert(&sigdata_list, sigdata);
+       return uth->sigstate.data ? TRUE : FALSE;
 }
 
-/* This is the akaros posix signal trigger.  Signals are dispatched from
- * this function to their proper posix signal handler */
-void trigger_posix_signal(int sig_nr, struct siginfo *info, void *aux)
+/* Prep a uthread to run a signal handler.  The original context of the uthread
+ * is saved on its stack, and a new context is set up to run the signal handler
+ * the next time the uthread is run. */
+static void __prep_sighandler(struct uthread *uthread,
+                              void (*entry)(void),
+                              struct siginfo *info)
 {
-       struct sigaction *action;
-       if (sig_nr > _NSIG - 1 || sig_nr < 0)
-               return;
-       action = &sigactions[sig_nr];
-       /* Would like a switch/case here, but they are pointers.  We can also get
-        * away with this check early since sa_handler and sa_sigaction are macros
-        * referencing the same union.  The man page isn't specific about whether or
-        * not you need to care about SA_SIGINFO when sending DFL/ERR/IGN. */
-       if (action->sa_handler == SIG_ERR)
-               return;
-       if (action->sa_handler == SIG_IGN)
-               return;
-       if (action->sa_handler == SIG_DFL) {
-               if (default_handlers[sig_nr] != SIGACT_IGN)
-                       default_handlers[sig_nr](sig_nr, info, aux);
-               return;
-       }
-
-       if (action->sa_flags & SA_SIGINFO) {
-               /* If NULL info struct passed in, construct our own */
-               struct siginfo s = {0};
-               if (info == NULL)
-                       info = &s;
-               /* Make sure the caller either already set singo in the info struct, or
-                * if they didn't, make sure it has been zeroed out (i.e. not just some
-                * garbage on the stack. */
-               assert(info->si_signo == sig_nr || info->si_signo == 0);
-               info->si_signo = sig_nr;
-               /* TODO: consider info->pid and whatnot */
-               /* We assume that this function follows the proper calling convention
-                * (i.e. it wasn't written in some crazy assembly function that
-                * trashes all its registers, i.e GO's default runtime handler) */
-               action->sa_sigaction(sig_nr, info, aux);
+       uintptr_t stack;
+       struct user_context *ctx;
+
+       if (uthread->flags & UTHREAD_SAVED) {
+               ctx = &uthread->u_ctx;
+               stack = get_user_ctx_stack(ctx) - sizeof(struct sigdata);
+               assert(stack_ptr_is_sane(stack));
+               uthread->sigstate.data = (struct sigdata*)stack;
+               if (uthread->flags & UTHREAD_FPSAVED) {
+                       uthread->sigstate.data->as = uthread->as;
+                       uthread->flags &= ~UTHREAD_FPSAVED;
+               }
        } else {
-               action->sa_handler(sig_nr);
+               assert(current_uthread == uthread);
+               ctx = &vcpd_of(vcore_id())->uthread_ctx;
+               stack = get_user_ctx_stack(ctx) - sizeof(struct sigdata);
+               assert(stack_ptr_is_sane(stack));
+               uthread->sigstate.data = (struct sigdata*)stack;
+               save_fp_state(&uthread->sigstate.data->as);
        }
+       if (info != NULL)
+               uthread->sigstate.data->info = *info;
+
+       init_user_ctx(&uthread->sigstate.data->u_ctx, (uintptr_t)entry, stack);
+       swap_user_contexts(ctx, &uthread->sigstate.data->u_ctx);
 }
 
-/* This is the catch all akaros event->posix signal handler.  All posix signals
- * are received in a single akaros event type.  They are then dispatched from
- * this function to their proper posix signal handler */
-static void handle_event(struct event_msg *ev_msg, unsigned int ev_type,
-                         void *data)
+/* Restore the context saved as the result of running a signal handler on a
+ * uthread. This context will execute the next time the uthread is run. */
+static void __restore_after_sighandler(struct uthread *uthread)
 {
-       int sig_nr;
-       struct siginfo info = {0};
-       info.si_code = SI_USER;
+       uthread->u_ctx = uthread->sigstate.data->u_ctx;
+       uthread->flags |= UTHREAD_SAVED;
+       switch (uthread->u_ctx.type) {
+       case ROS_HW_CTX:
+       case ROS_VM_CTX:
+               uthread->as = uthread->sigstate.data->as;
+               uthread->flags |= UTHREAD_FPSAVED;
+               break;
+       }
+       uthread->sigstate.data = NULL;
+}
 
-       assert(ev_msg);
-       sig_nr = ev_msg->ev_arg1;
-       trigger_posix_signal(sig_nr, &info, 0);
+/* Callback when yielding a pthread after upon completion of a sighandler.  We
+ * didn't save the current context on yeild, but that's ok because here we
+ * restore the original saved context of the pthread and then treat this like a
+ * normal voluntary yield. */
+static void __exit_sighandler_cb(struct uthread *uthread, void *junk)
+{
+       __restore_after_sighandler(uthread);
+       uthread_paused(uthread);
 }
 
-/* Called from uthread_slim_init() */
-void init_posix_signals(void)
+/* Run a specific sighandler from the top of the sigstate stack. The 'info'
+ * struct is prepopulated before the call is triggered as the result of a
+ * reflected fault. */
+static void __run_sighandler(void)
 {
-       struct event_queue *posix_sig_ev_q;
-       register_ev_handler(EV_POSIX_SIGNAL, handle_event, 0);
-       posix_sig_ev_q = get_big_event_q();
-       assert(posix_sig_ev_q);
-       posix_sig_ev_q->ev_flags = EVENT_IPI | EVENT_INDIR | EVENT_FALLBACK;
-       register_kevent_q(posix_sig_ev_q, EV_POSIX_SIGNAL);
-       wfl_init(&sigdata_list);
+       struct uthread *uthread = current_uthread;
+       int signo = uthread->sigstate.data->info.si_signo;
+
+       __sigdelset(&uthread->sigstate.pending, signo);
+       trigger_posix_signal(signo, &uthread->sigstate.data->info,
+                            &uthread->sigstate.data->u_ctx);
+       uthread_yield(FALSE, __exit_sighandler_cb, 0);
 }
 
-int sigaddset(sigset_t *__set, int __signo)
+/* Run through all pending sighandlers and trigger them with a NULL info
+ * field. These handlers are triggered as the result of thread directed
+ * signals (i.e. not interprocess signals), and thus don't require individual
+ * 'info' structs. */
+static void __run_all_sighandlers(void)
 {
-       if (__signo == 0 || __signo > _NSIG) {
-               errno = EINVAL;
-               return -1;
+       struct uthread *uthread = current_uthread;
+       sigset_t andset = uthread->sigstate.pending & (~uthread->sigstate.mask);
+
+       for (int i = 1; i < _NSIG; i++) {
+               if (__sigismember(&andset, i)) {
+                       __sigdelset(&uthread->sigstate.pending, i);
+                       trigger_posix_signal(i, NULL, &uthread->sigstate.data->u_ctx);
+               }
        }
-       __sigaddset(__set, __signo);
-       return 0;
+       uthread_yield(FALSE, __exit_sighandler_cb, 0);
 }
 
-int sigdelset(sigset_t *__set, int __signo)
+int uthread_signal(struct uthread *uthread, int signo)
 {
-       if (__signo == 0 || __signo > _NSIG) {
-               errno = EINVAL;
-               return -1;
-       }
-       __sigdelset(__set, __signo);
-       return 0;
+       // Slightly racy with clearing of mask when triggering the signal, but
+       // that's OK, as signals are inherently racy since they don't queue up.
+       return sigaddset(&uthread->sigstate.pending, signo);
 }
 
-int sigismember(__const sigset_t *__set, int __signo)
+/* If there are any pending signals, prep the uthread to run it's signal
+ * handler. The next time the uthread is run, it will pop into it's signal
+ * handler context instead of its original saved context. Once the signal
+ * handler is complete, the original context will be restored and restarted. */
+void uthread_prep_pending_signals(struct uthread *uthread)
 {
-       if (__signo == 0 || __signo > _NSIG) {
-               errno = EINVAL;
-               return -1;
+       if (!uth_is_handling_sigs(uthread) && uthread->sigstate.pending) {
+               sigset_t andset = uthread->sigstate.pending & (~uthread->sigstate.mask);
+
+               if (!__sigisemptyset(&andset))
+                       __prep_sighandler(uthread, __run_all_sighandlers, NULL);
        }
-       __sigismember(__set, __signo);
-       return 0;
 }
 
-/* Would need a layer/interposition to ignore blocked signals when they come in,
- * and then to manually play them when they are unblocked, like how x86 does
- * with the IRR and the ISR for interrupt delivery. */
-int sigprocmask(int __how, __const sigset_t *__restrict __set,
-                sigset_t *__restrict __oset)
+/* If the given signal is unmasked, prep the uthread to run it's signal
+ * handler, but don't run it yet. In either case, make the uthread runnable
+ * again. Once the signal handler is complete, the original context will be
+ * restored and restarted. */
+void uthread_prep_signal_from_fault(struct uthread *uthread,
+                                    int signo, int code, void *addr)
 {
-       printf("Function not supported generically! "
-           "Use 2LS specific function e.g. pthread_sigmask\n");
-       return 0;
+       if (!__sigismember(&uthread->sigstate.mask, signo)) {
+               struct siginfo info = {0};
+
+               if (uth_is_handling_sigs(uthread)) {
+                       printf("Uthread sighandler faulted, signal: %d\n", signo);
+                       /* uthread.c already copied out the faulting ctx into the uth */
+                       print_user_context(&uthread->u_ctx);
+                       exit(-1);
+               }
+               info.si_signo = signo;
+               info.si_code = code;
+               info.si_addr = addr;
+               __prep_sighandler(uthread, __run_sighandler, &info);
+       }
 }
 
-/* Could do this with a loop on delivery of the signal, sleeping and getting
- * woken up by the kernel on any event, like we do with async syscalls. */
-int sigsuspend(__const sigset_t *__set)
+/* This is managed by vcore / 2LS code */
+static int __sigaltstack(__const struct sigaltstack *__restrict __ss,
+                         struct sigaltstack *__restrict __oss)
 {
        return 0;
 }
 
-int sigaction(int __sig, __const struct sigaction *__restrict __act,
-              struct sigaction *__restrict __oact)
+/* Akaros can't have signals interrupt syscalls to need a restart, though we can
+ * re-wake-up the process while it is waiting for its syscall. */
+static int __siginterrupt(int __sig, int __interrupt)
 {
-       if (__sig > _NSIG - 1 || __sig < 0)
-               return -1;
-       if (__oact) {
-               *__oact = sigactions[__sig];
-       }
-       if (!__act)
-               return 0;
-       sigactions[__sig] = *__act;
        return 0;
 }
 
 /* Not really possible or relevant - you'd need to walk/examine the event UCQ */
-int sigpending(sigset_t *__set)
+static int __sigpending(sigset_t *__set)
 {
        return 0;
 }
 
-/* Can be done similar to sigsuspend */
-int sigwait(__const sigset_t *__restrict __set, int *__restrict __sig)
+static int __sigprocmask(int __how, __const sigset_t *__restrict __set,
+                         sigset_t *__restrict __oset)
 {
-       return 0;
-}
+       sigset_t *sigmask;
+
+       /* Signal handlers might call sigprocmask, with the intent of affecting the
+        * uthread's sigmask.  Process-wide signal handlers run on behalf of the
+        * entire process and aren't bound to a uthread, which means sigprocmask
+        * won't work.  We can tell we're running one of these handlers since we are
+        * in vcore context.  Uthread signals (e.g. pthread_kill()) run from uthread
+        * context. */
+       if (in_vcore_context()) {
+               errno = ENOENT;
+               return -1;
+       }
 
-/* Can be done similar to sigsuspend */
-int sigwaitinfo(__const sigset_t *__restrict __set,
-                siginfo_t *__restrict __info)
-{
+       sigmask = &current_uthread->sigstate.mask;
+
+       if (__set && (__how != SIG_BLOCK) &&
+                    (__how != SIG_SETMASK) &&
+                    (__how != SIG_UNBLOCK)) {
+               errno = EINVAL;
+               return -1;
+       }
+
+       if (__oset)
+               *__oset = *sigmask;
+       if (__set) {
+               switch (__how) {
+                       case SIG_BLOCK:
+                               *sigmask = *sigmask | *__set;
+                               break;
+                       case SIG_SETMASK:
+                               *sigmask = *__set;
+                               break;
+                       case SIG_UNBLOCK:
+                               *sigmask = *sigmask & ~(*__set);
+                               break;
+               }
+       }
        return 0;
 }
 
-/* Can be done similar to sigsuspend, with an extra alarm syscall */
-int sigtimedwait(__const sigset_t *__restrict __set,
-                 siginfo_t *__restrict __info,
-                 __const struct timespec *__restrict __timeout)
+/* Needs support with trigger_posix_signal to deal with passing values with
+ * POSIX signals. */
+static int __sigqueue(__pid_t __pid, int __sig, __const union sigval __val)
 {
        return 0;
 }
 
-/* Needs support with trigger_posix_signal to deal with passing values with POSIX
- * signals. */
-int sigqueue(__pid_t __pid, int __sig, __const union sigval __val)
+/* Linux specific, and not really needed for us */
+static int __sigreturn(struct sigcontext *__scp)
 {
        return 0;
 }
 
-/* Old BSD interface, deprecated */
-int sigvec(int __sig, __const struct sigvec *__vec, struct sigvec *__ovec)
+/* This is managed by vcore / 2LS code */
+static int __sigstack(struct sigstack *__ss, struct sigstack *__oss)
 {
        return 0;
 }
 
-/* Linux specific, and not really needed for us */
-int sigreturn(struct sigcontext *__scp)
+/* Could do this with a loop on delivery of the signal, sleeping and getting
+ * woken up by the kernel on any event, like we do with async syscalls. */
+static int __sigsuspend(__const sigset_t *__set)
 {
        return 0;
 }
 
-/* Akaros can't have signals interrupt syscalls to need a restart, though we can
- * re-wake-up the process while it is waiting for its syscall. */
-int siginterrupt(int __sig, int __interrupt)
+/* Can be done similar to sigsuspend, with an extra alarm syscall */
+static int __sigtimedwait(__const sigset_t *__restrict __set,
+                          siginfo_t *__restrict __info,
+                          __const struct timespec *__restrict __timeout)
 {
        return 0;
 }
 
-/* This is managed by vcore / 2LS code */
-int sigstack(struct sigstack *__ss, struct sigstack *__oss)
+/* Can be done similar to sigsuspend */
+static int __sigwait(__const sigset_t *__restrict __set, int *__restrict __sig)
 {
        return 0;
 }
 
-/* This is managed by vcore / 2LS code */
-int sigaltstack(__const struct sigaltstack *__restrict __ss,
-                struct sigaltstack *__restrict __oss)
+/* Can be done similar to sigsuspend */
+static int __sigwaitinfo(__const sigset_t *__restrict __set,
+                         siginfo_t *__restrict __info)
 {
        return 0;
 }
 
-__sighandler_t signal(int sig, __sighandler_t handler)
+static int __sigself(int signo)
 {
        int ret;
-       struct sigaction newsa = {0};
-       struct sigaction oldsa = {0};
-       newsa.sa_handler = handler;
-       ret = sigaction(sig, &newsa, &oldsa);
-       if (ret < 0) {
-               errno = EINVAL;
-               return SIG_ERR;
+
+       if (in_vcore_context())
+               return kill(getpid(), signo);
+
+       ret = uthread_signal(current_uthread, signo);
+
+       void cb(struct uthread *uthread, void *arg)
+       {
+               uthread_paused(uthread);
        }
-       return oldsa.sa_handler;
+       if (ret == 0)
+               uthread_yield(TRUE, cb, 0);
+       return ret;
 }