Weasel apart parlib/libc symbols for signals (XCC)
authorKevin Klues <klueska@cs.berkeley.edu>
Tue, 10 Nov 2015 02:45:25 +0000 (18:45 -0800)
committerBarret Rhoden <brho@cs.berkeley.edu>
Mon, 16 Nov 2015 23:15:03 +0000 (15:15 -0800)
Previously, all of the akaros signal handling code was in parlib, which meant
that none of the glibc functions could use it. Moreover, there was no
good way for an individul 2LS to overwrite many of the commong signal
handling functions with its own functionality.  This commit weasels
apart some of this mess, allowing a 2LS to hook in its own set of
functions for common functions for masking/relaying posix signals.
Moreover, it allows glibc to now access the generic signal_ops struct,
so any function pointers a 2LS wishes to set in there can be called from
glibc if desired.  This will prove useful when implementing SIGPIPE in a
subsequent commit.

Signed-off-by: Kevin Klues <klueska@cs.berkeley.edu>
Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
17 files changed:
tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/Versions
tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/sigaction.c [new file with mode: 0644]
tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/sigaltstack.c [new file with mode: 0644]
tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/sigintr.c [new file with mode: 0644]
tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/sigpending.c [new file with mode: 0644]
tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/sigprocmask.c [new file with mode: 0644]
tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/sigqueue.c [new file with mode: 0644]
tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/sigreturn.c [new file with mode: 0644]
tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/sigstack.c [new file with mode: 0644]
tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/sigsuspend.c [new file with mode: 0644]
tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/sigtimedwait.c [new file with mode: 0644]
tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/sigwait.c [new file with mode: 0644]
tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/sigwaitinfo.c [new file with mode: 0644]
user/parlib/include/parlib.h
user/parlib/include/signal.h [new file with mode: 0644]
user/parlib/signal.c
user/pthread/pthread.c

index e580909..7ca731d 100644 (file)
@@ -23,6 +23,8 @@ libc {
        _sys_siglist;
        sys_siglist;
        sys_sigabbrev;
+    signal_ops;
+    trigger_posix_signal;
 
     init_empty_dir;
     convM2S;
diff --git a/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/sigaction.c b/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/sigaction.c
new file mode 100644 (file)
index 0000000..9ba55ac
--- /dev/null
@@ -0,0 +1,165 @@
+/* Copyright (c) 2013 The Regents of the University of California
+ * Copyright (c) 2015 Google Inc.
+ * Barret Rhoden <brho@cs.berkeley.edu>
+ * Kevin Klues <klueska@cs.berkeley.edu>
+ * See LICENSE for details.
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#include <ros/procinfo.h>
+#include <ros/syscall.h>
+#include <parlib/signal.h>
+#include <parlib/vcore.h>
+
+/* We define the signal_ops struct in glibc so that it is accessible without
+ * being linked to parlib. Parlib-based 2LSs will override it with their
+ * scheduler specific signal ops. */
+struct signal_ops *signal_ops;
+
+/* This is list of sigactions associated with each posix signal. */
+static struct sigaction sigactions[_NSIG];
+
+/* 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);
+}
+
+static void default_core_handler(int signr, siginfo_t *info, void *ctx)
+{
+       printf("Segmentation Fault (sorry, no core dump yet)\n");
+       if (ctx)
+               print_user_context((struct user_context*)ctx);
+       else
+               printf("No ctx for %s\n", __func__);
+       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). */
+               printf("Fault type %d at addr %p\n", info->si_errno,
+                       info->si_addr);
+       } else {
+               printf("No fault info\n");
+       }
+       default_term_handler((1 << 7) + signr, info, ctx);
+}
+
+static void default_stop_handler(int signr, siginfo_t *info, void *ctx)
+{
+       printf("Stop signal received!  No support to stop yet though!\n");
+}
+
+static void default_cont_handler(int signr, siginfo_t *info, void *ctx)
+{
+       printf("Cont signal received!  No support to cont yet though!\n");
+}
+
+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,
+       [SIGSYS+1 ... _NSIG-1] = SIGACT_IGN
+};
+
+/* 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)
+{
+       struct sigaction *action;
+
+       if (sig_nr >= _NSIG || 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);
+       } else {
+               action->sa_handler(sig_nr);
+       }
+}
+
+int __sigaction(int __sig, __const struct sigaction *__restrict __act,
+                struct sigaction *__restrict __oact)
+{
+       if (__sig <= 0 || __sig >= NSIG) {
+               __set_errno(EINVAL);
+               return -1;
+       }
+       if (__oact)
+               *__oact = sigactions[__sig];
+       if (!__act)
+               return 0;
+       sigactions[__sig] = *__act;
+       return 0;
+}
+libc_hidden_def(__sigaction)
+weak_alias(__sigaction, sigaction)
diff --git a/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/sigaltstack.c b/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/sigaltstack.c
new file mode 100644 (file)
index 0000000..d774aed
--- /dev/null
@@ -0,0 +1,27 @@
+/* Copyright (C) 1992-2014 Free Software Foundation, Inc.
+ * This file is part of the GNU C Library.
+ *
+ * The GNU C Library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * The GNU C Library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the GNU C Library; if not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#include <errno.h>
+#include <parlib/signal.h>
+
+/* Run signals handlers on the stack specified by SS (if not NULL).
+ * If OSS is not NULL, it is filled in with the old signal stack status.  */
+int sigaltstack(const struct sigaltstack *ss, struct sigaltstack *oss)
+{
+       return signal_ops->sigaltstack(ss, oss);
+}
diff --git a/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/sigintr.c b/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/sigintr.c
new file mode 100644 (file)
index 0000000..a22f4f6
--- /dev/null
@@ -0,0 +1,28 @@
+/* Copyright (C) 1992-2014 Free Software Foundation, Inc.
+ * This file is part of the GNU C Library.
+ *
+ * The GNU C Library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * The GNU C Library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the GNU C Library; if not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#include <stddef.h>
+#include <parlib/signal.h>
+
+/* If INTERRUPT is nonzero, make signal SIG interrupt system calls
+ * (causing them to fail with EINTR); if INTERRUPT is zero, make system
+ * calls be restarted after signal SIG.  */
+int siginterrupt(int sig, int interrupt)
+{
+       return signal_ops->siginterrupt(sig, interrupt);
+}
diff --git a/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/sigpending.c b/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/sigpending.c
new file mode 100644 (file)
index 0000000..bde4338
--- /dev/null
@@ -0,0 +1,28 @@
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
+ * This file is part of the GNU C Library.
+ *
+ * The GNU C Library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * The GNU C Library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the GNU C Library; if not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#include <errno.h>
+#include <stddef.h>
+#include <parlib/signal.h>
+
+
+/* Store in SET all signals that are blocked and pending.  */
+int sigpending(sigset_t *set)
+{
+       return signal_ops->sigpending(set);
+}
diff --git a/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/sigprocmask.c b/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/sigprocmask.c
new file mode 100644 (file)
index 0000000..b51953e
--- /dev/null
@@ -0,0 +1,30 @@
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
+ * This file is part of the GNU C Library.
+ *
+ * The GNU C Library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * The GNU C Library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the GNU C Library; if not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#include <errno.h>
+#include <parlib/signal.h>
+
+
+/* If SET is not NULL, modify the current set of blocked signals
+ * according to HOW, which may be SIG_BLOCK, SIG_UNBLOCK or SIG_SETMASK.
+ * If OSET is not NULL, store the old set of blocked signals in *OSET.  */
+int __sigprocmask(int how, const sigset_t *set, sigset_t *oset)
+{
+       return signal_ops->sigprocmask(how, set, oset);
+}
+weak_alias(__sigprocmask, sigprocmask)
diff --git a/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/sigqueue.c b/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/sigqueue.c
new file mode 100644 (file)
index 0000000..8f11e81
--- /dev/null
@@ -0,0 +1,28 @@
+/* Implementation of sigqueue function from POSIX.1b.
+ * Copyright (C) 1997-2014 Free Software Foundation, Inc.
+ * This file is part of the GNU C Library.
+ *
+ * The GNU C Library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * The GNU C Library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the GNU C Library; if not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#include <errno.h>
+#include <parlib/signal.h>
+#include <sys/types.h>
+
+int __sigqueue(pid_t pid, int sig, const union sigval val)
+{
+       return signal_ops->sigqueue(pid, sig, val);
+}
+weak_alias(__sigqueue, sigqueue)
diff --git a/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/sigreturn.c b/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/sigreturn.c
new file mode 100644 (file)
index 0000000..b4c5da8
--- /dev/null
@@ -0,0 +1,26 @@
+/* Copyright (C) 1992-2014 Free Software Foundation, Inc.
+ * This file is part of the GNU C Library.
+ *
+ * The GNU C Library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * The GNU C Library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the GNU C Library; if not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#include <errno.h>
+#include <parlib/signal.h>
+
+int __sigreturn(struct sigcontext *context)
+{
+       signal_ops->sigreturn(context);
+}
+weak_alias(__sigreturn, sigreturn)
diff --git a/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/sigstack.c b/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/sigstack.c
new file mode 100644 (file)
index 0000000..8f1cc13
--- /dev/null
@@ -0,0 +1,27 @@
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
+ * This file is part of the GNU C Library.
+ *
+ * The GNU C Library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * The GNU C Library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the GNU C Library; if not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#include <errno.h>
+#include <parlib/signal.h>
+
+/* Run signals handlers on the stack specified by SS (if not NULL).
+ * If OSS is not NULL, it is filled in with the old signal stack status.  */
+int sigstack(struct sigstack *ss, struct sigstack *oss)
+{
+       return signal_ops->sigstack(ss, oss);
+}
diff --git a/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/sigsuspend.c b/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/sigsuspend.c
new file mode 100644 (file)
index 0000000..12627b8
--- /dev/null
@@ -0,0 +1,32 @@
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
+ * This file is part of the GNU C Library.
+ *
+ * The GNU C Library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * The GNU C Library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the GNU C Library; if not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#include <errno.h>
+#include <stddef.h>
+#include <unistd.h>
+#include <parlib/signal.h>
+
+
+/* Change the set of blocked signals to SET,
+ * wait until a signal arrives, and restore the set of blocked signals.  */
+int __sigsuspend(const sigset_t *set)
+{
+       return signal_ops->sigsuspend(set);
+}
+libc_hidden_def(__sigsuspend)
+weak_alias(__sigsuspend, sigsuspend)
diff --git a/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/sigtimedwait.c b/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/sigtimedwait.c
new file mode 100644 (file)
index 0000000..6883ac3
--- /dev/null
@@ -0,0 +1,29 @@
+/* Implementation of sigtimedwait function from POSIX.1b.
+ * Copyright (C) 1997-2014 Free Software Foundation, Inc.
+ * This file is part of the GNU C Library.
+ *
+ * The GNU C Library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * The GNU C Library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the GNU C Library; if not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#include <errno.h>
+#include <parlib/signal.h>
+
+int __sigtimedwait(const sigset_t *set, siginfo_t *info,
+                   const struct timespec *timeout)
+{
+       return signal_ops->sigtimedwait(set, info, timeout);
+}
+libc_hidden_def(__sigtimedwait)
+weak_alias(__sigtimedwait, sigtimedwait)
diff --git a/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/sigwait.c b/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/sigwait.c
new file mode 100644 (file)
index 0000000..be323ea
--- /dev/null
@@ -0,0 +1,28 @@
+/* Implementation of sigait function from POSIX.1b.
+ * Copyright (C) 1997-2014 Free Software Foundation, Inc.
+ * This file is part of the GNU C Library.
+ *
+ * The GNU C Library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * The GNU C Library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the GNU C Library; if not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#include <errno.h>
+#include <parlib/signal.h>
+
+int __sigwait(const sigset_t *set, int *sig)
+{
+       return signal_ops->sigwait(set, sig);
+}
+libc_hidden_def(__sigwait)
+weak_alias(__sigwait, sigwait)
diff --git a/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/sigwaitinfo.c b/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/sigwaitinfo.c
new file mode 100644 (file)
index 0000000..4789b51
--- /dev/null
@@ -0,0 +1,28 @@
+/* Implementation of sigwaitinfo function from POSIX.1b.
+ * Copyright (C) 1997-2014 Free Software Foundation, Inc.
+ * This file is part of the GNU C Library.
+ *
+ * The GNU C Library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * The GNU C Library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the GNU C Library; if not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#include <errno.h>
+#include <parlib/signal.h>
+
+int __sigwaitinfo(const sigset_t *set, siginfo_t *info)
+{
+       return signal_ops->sigwaitinfo(set, info);
+}
+libc_hidden_def(__sigwaitinfo)
+weak_alias(__sigwaitinfo, sigwaitinfo)
index 749d038..d8a9083 100644 (file)
@@ -59,24 +59,6 @@ int         sys_tap_fds(struct fd_tap_req *tap_reqs, size_t nr_reqs);
 
 void           syscall_async(struct syscall *sysc, unsigned long num, ...);
 
-/* Posix signal related stuff */
-struct sigdata {
-       struct user_context u_ctx;
-       struct ancillary_state as;
-       struct siginfo info;
-       void *stack;
-};
-/* This is the set of global function pointers that a 2LS using signals needs
- * to implement.  Subject to grow over time. */
-struct signal_ops {
-       int (*sigprocmask)(int, __const sigset_t *__restrict, sigset_t *__restrict);
-};
-extern struct signal_ops *signal_ops;
-void init_posix_signals(void);
-struct sigdata *alloc_sigdata();
-void free_sigdata(struct sigdata *sigdata);
-void trigger_posix_signal(int sig_nr, struct siginfo *info, void *aux);
-
 /* Control variables */
 extern bool parlib_wants_to_be_mcp;    /* instructs the 2LS to be an MCP */
 
diff --git a/user/parlib/include/signal.h b/user/parlib/include/signal.h
new file mode 100644 (file)
index 0000000..6d6ce99
--- /dev/null
@@ -0,0 +1,49 @@
+/* Copyright (c) 2015 Google Inc.
+ * Kevin Klues <klueska@cs.berkeley.edu>
+ * See LICENSE for details.
+ */
+
+#pragma once
+#ifdef BUILDING_PARLIB
+#include_next "signal.h"
+#else
+#include <signal.h>
+#endif
+
+#include <ros/procinfo.h>
+
+/* Data we need to carry around as part of handling posix signals on akaros. */
+struct sigdata {
+       struct user_context u_ctx;
+       struct ancillary_state as;
+       struct siginfo info;
+       void *stack;
+};
+
+/* A set of functions related to handling posix signals on akaros. The
+ * implementation of these functions is 2LS specific. */
+struct signal_ops {
+       int (*sigaltstack)(__const struct sigaltstack *__restrict,
+                       struct sigaltstack *__restrict);
+       int (*siginterrupt)(int, int);
+       int (*sigpending)(sigset_t *);
+       int (*sigprocmask)(int, __const sigset_t *__restrict, sigset_t *__restrict);
+       int (*sigqueue)(__pid_t, int, __const union sigval);
+       int (*sigreturn)(struct sigcontext *__scp);
+       int (*sigstack)(struct sigstack *, struct sigstack *);
+       int (*sigsuspend)(__const sigset_t *);
+       int (*sigtimedwait)(__const sigset_t *__restrict, siginfo_t *__restrict,
+                           __const struct timespec *__restrict);
+       int (*sigwait)(__const sigset_t *__restrict, int *__restrict);
+       int (*sigwaitinfo)(__const sigset_t *__restrict, siginfo_t *__restrict);
+};
+
+/* Glibc defines the symbol for signal_ops so that the function pointers
+ * assigned in it can be used from within glibc itself. */
+extern struct signal_ops *signal_ops;
+
+/* External API for initializing and generating posix signals inside a 2LS. */
+void init_posix_signals(void);
+struct sigdata *alloc_sigdata();
+void free_sigdata(struct sigdata *sigdata);
+void trigger_posix_signal(int sig_nr, struct siginfo *info, void *aux);
index 0e3d592..9817135 100644 (file)
 #include <parlib/waitfreelist.h>
 #include <parlib/stdio.h>
 
-/* This is list of sigactions associated with each posix signal. */
-static struct sigaction sigactions[_NSIG];
-
-/* Forward declare some functions. */
+/* 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);
 
 /* 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
 };
-struct signal_ops *signal_ops = &default_signal_ops;
 
 /* 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
@@ -58,89 +78,6 @@ struct signal_ops *signal_ops = &default_signal_ops;
 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);
-}
-
-static void default_core_handler(int signr, siginfo_t *info, void *ctx)
-{
-       printf("Segmentation Fault (sorry, no core dump yet)\n");
-       if (ctx)
-               print_user_context((struct user_context*)ctx);
-       else
-               printf("No ctx for %s\n", __func__);
-       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). */
-               printf("Fault type %d at addr %p\n", info->si_errno,
-                       info->si_addr);
-       } else {
-               printf("No fault info\n");
-       }
-       default_term_handler((1 << 7) + signr, info, ctx);
-}
-
-static void default_stop_handler(int signr, siginfo_t *info, void *ctx)
-{
-       printf("Stop signal received!  No support to stop yet though!\n");
-}
-
-static void default_cont_handler(int signr, siginfo_t *info, void *ctx)
-{
-       printf("Cont signal received!  No support to cont yet though!\n");
-}
-
-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,
-       [SIGSYS+1 ... _NSIG-1] = SIGACT_IGN
-};
-
 /* 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
@@ -167,48 +104,6 @@ void free_sigdata(struct sigdata *sigdata)
        wfl_insert(&sigdata_list, sigdata);
 }
 
-/* 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)
-{
-       struct sigaction *action;
-       if (sig_nr >= _NSIG || 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);
-       } else {
-               action->sa_handler(sig_nr);
-       }
-}
-
 /* 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 */
@@ -228,6 +123,8 @@ static void handle_event(struct event_msg *ev_msg, unsigned int ev_type,
 void init_posix_signals(void)
 {
        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);
@@ -237,33 +134,23 @@ void init_posix_signals(void)
        wfl_init(&sigdata_list);
 }
 
-int sigaddset(sigset_t *__set, int __signo)
+/* This is managed by vcore / 2LS code */
+static int __sigaltstack(__const struct sigaltstack *__restrict __ss,
+                         struct sigaltstack *__restrict __oss)
 {
-       if (__signo == 0 || __signo >= _NSIG) {
-               errno = EINVAL;
-               return -1;
-       }
-       __sigaddset(__set, __signo);
        return 0;
 }
 
-int sigdelset(sigset_t *__set, int __signo)
+/* 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 (__signo == 0 || __signo >= _NSIG) {
-               errno = EINVAL;
-               return -1;
-       }
-       __sigdelset(__set, __signo);
        return 0;
 }
 
-int sigismember(__const sigset_t *__set, int __signo)
+/* Not really possible or relevant - you'd need to walk/examine the event UCQ */
+static int __sigpending(sigset_t *__set)
 {
-       if (__signo == 0 || __signo >= _NSIG) {
-               errno = EINVAL;
-               return -1;
-       }
-       __sigismember(__set, __signo);
        return 0;
 }
 
@@ -275,109 +162,50 @@ static int __sigprocmask(int __how, __const sigset_t *__restrict __set,
        return 0;
 }
 
-int sigprocmask(int __how, __const sigset_t *__restrict __set,
-                sigset_t *__restrict __oset)
-{
-       return signal_ops->sigprocmask(__how, __set, __oset);
-}
-
-/* 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)
-{
-       return 0;
-}
-
-int sigaction(int __sig, __const struct sigaction *__restrict __act,
-              struct sigaction *__restrict __oact)
+/* 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)
 {
-       if (__sig >= _NSIG || __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)
+/* Linux specific, and not really needed for us */
+static int __sigreturn(struct sigcontext *__scp)
 {
        return 0;
 }
 
-/* Can be done similar to sigsuspend */
-int sigwait(__const sigset_t *__restrict __set, int *__restrict __sig)
+/* This is managed by vcore / 2LS code */
+static int __sigstack(struct sigstack *__ss, struct sigstack *__oss)
 {
        return 0;
 }
 
-/* Can be done similar to sigsuspend */
-int sigwaitinfo(__const sigset_t *__restrict __set,
-                siginfo_t *__restrict __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. */
+static int __sigsuspend(__const sigset_t *__set)
 {
        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)
-{
-       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)
-{
-       return 0;
-}
-
-/* Old BSD interface, deprecated */
-int sigvec(int __sig, __const struct sigvec *__vec, struct sigvec *__ovec)
-{
-       return 0;
-}
-
-/* Linux specific, and not really needed for us */
-int sigreturn(struct sigcontext *__scp)
+static int __sigtimedwait(__const sigset_t *__restrict __set,
+                          siginfo_t *__restrict __info,
+                          __const struct timespec *__restrict __timeout)
 {
        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)
-{
-       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)
-{
-       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;
-       }
-       return oldsa.sa_handler;
-}
index 27cf399..0eeb5d1 100644 (file)
@@ -18,6 +18,7 @@
 #include <sys/mman.h>
 #include <parlib/event.h>
 #include <parlib/ucq.h>
+#include <parlib/signal.h>
 
 struct pthread_queue ready_queue = TAILQ_HEAD_INITIALIZER(ready_queue);
 struct pthread_queue active_queue = TAILQ_HEAD_INITIALIZER(active_queue);