176 lines
4.2 KiB
Text
176 lines
4.2 KiB
Text
$NetBSD: patch-al,v 1.1.1.1 2011/07/27 10:23:49 cherry Exp $
|
|
|
|
--- src/netbsd/signal-netbsd.c.orig 2009-12-16 12:47:32.000000000 +0000
|
|
+++ src/netbsd/signal-netbsd.c
|
|
@@ -0,0 +1,171 @@
|
|
+/*
|
|
+ * Copyright (C) 1995-2007, Hewlett-Packard Development Company, L.P.
|
|
+ *
|
|
+ * This program is free software; you can redistribute it and/or modify
|
|
+ * it under the terms of the GNU General Public License as published by
|
|
+ * the Free Software Foundation; either version 2 of the License, or
|
|
+ * (at your option) any later version.
|
|
+ *
|
|
+ * This program 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 General Public License for more details.
|
|
+ *
|
|
+ * You should have received a copy of the GNU General Public License along
|
|
+ * with this program; if not, write to the Free Software Foundation, Inc.,
|
|
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
+ *
|
|
+ */
|
|
+
|
|
+#include <sys/types.h>
|
|
+#include <assert.h>
|
|
+#include <errno.h>
|
|
+#include <signal.h>
|
|
+#include <string.h>
|
|
+
|
|
+#include "std.h"
|
|
+#include "types.h"
|
|
+#include "exportui.h"
|
|
+#include "coreui.h"
|
|
+#include "sim.h"
|
|
+#include "libsrs.h"
|
|
+#include "libcore.h"
|
|
+#include "state.h"
|
|
+
|
|
+#include "netbsd/signal-netbsd.h"
|
|
+
|
|
+static struct {
|
|
+ int valid;
|
|
+ int flags;
|
|
+ ADDR handler;
|
|
+ sigset_t mask;
|
|
+ struct siginfo64 info;
|
|
+} siginfo[SIGRTMAX];
|
|
+
|
|
+static sigset_t sigpend, sigmask;
|
|
+
|
|
+void signal_return(void)
|
|
+{
|
|
+ assert(0);
|
|
+}
|
|
+
|
|
+void signal_invoke_handler(int in_syscall)
|
|
+{
|
|
+ int i, sig;
|
|
+ uint32_t sigword;
|
|
+
|
|
+ for (i = 0, sig = 0; i < _SIG_WORDS; i++, sig += 32) {
|
|
+ sigword = sigpend.__bits[i] & ~sigmask.__bits[i];
|
|
+ if (sigword)
|
|
+ break;
|
|
+ }
|
|
+ assert(sigword);
|
|
+ sig += ffs(sigword);
|
|
+ assert(sig > 0 && sig <= SIGRTMAX);
|
|
+
|
|
+ /* XXX need to actually deliver the signal. Ignore for now. */
|
|
+ sigdelset(&sigpend, sig);
|
|
+}
|
|
+
|
|
+int signal_pending(void)
|
|
+{
|
|
+ int i;
|
|
+
|
|
+ for (i = 0; i < _SIG_WORDS; i++) {
|
|
+ if (sigpend.__bits[i] &&
|
|
+ sigpend.__bits[i] & ~sigmask.__bits[i])
|
|
+ return (1);
|
|
+ }
|
|
+ return (0);
|
|
+}
|
|
+
|
|
+void signal_queue_info(int sig, ADDR ifa)
|
|
+{
|
|
+ struct siginfo64 *si64;
|
|
+
|
|
+ /* Sanity checks. */
|
|
+ if (sig <= 0 || sig > SIGRTMAX)
|
|
+ return;
|
|
+
|
|
+ /* XXX We need to deliver the trap. For now, halt the program. */
|
|
+ progStop("Got trap %d (IFA=0x%016llx, IP=0x%016llx)\n", sig, ifa, ip);
|
|
+
|
|
+ sigaddset(&sigpend, sig);
|
|
+ si64 = &siginfo[sig - 1].info;
|
|
+ memset(si64, 0, sizeof(*si64));
|
|
+ si64->si_addr = ifa; /* XXX: normalise pointers to ptr64_t */
|
|
+}
|
|
+
|
|
+static void signal_handler(int sig, siginfo_t *si, void *uc)
|
|
+{
|
|
+ struct siginfo64 *si64;
|
|
+
|
|
+ /* Sanity checks. */
|
|
+ if (sig <= 0 || sig > SIGRTMAX) {
|
|
+ return;
|
|
+ }
|
|
+
|
|
+#if 0
|
|
+ printf("Got signal %d\n", sig);
|
|
+#endif
|
|
+
|
|
+ sigaddset(&sigpend, sig);
|
|
+ si64 = &siginfo[sig - 1].info;
|
|
+ si64->si_signo = sig;
|
|
+ si64->si_errno = si->si_errno;
|
|
+ si64->si_code = si->si_code;
|
|
+ si64->si_pid = si->si_pid;
|
|
+ si64->si_uid = si->si_uid;
|
|
+ si64->si_status = si->si_status;
|
|
+ si64->si_addr = (long)si->si_addr;
|
|
+ si64->si_value.sival_ptr = si->si_value.sival_ptr;
|
|
+ si64->si_band = si->si_band;
|
|
+}
|
|
+
|
|
+int signal_get_handler(int sig, struct sigaction64 *sa64)
|
|
+{
|
|
+ struct sigaction sa;
|
|
+
|
|
+ if (sig <= 0 || sig > SIGRTMAX)
|
|
+ return (EINVAL);
|
|
+
|
|
+ if (!siginfo[sig - 1].valid) {
|
|
+ if (sigaction(sig, NULL, &sa) == -1)
|
|
+ return (errno);
|
|
+ siginfo[sig - 1].valid = 1;
|
|
+ siginfo[sig - 1].handler = 0;
|
|
+ siginfo[sig - 1].flags = sa.sa_flags;
|
|
+ siginfo[sig - 1].mask = sa.sa_mask;
|
|
+ }
|
|
+ sa64->sa_handler = siginfo[sig - 1].handler;
|
|
+ sa64->sa_flags = siginfo[sig - 1].flags;
|
|
+ sa64->sa_mask = siginfo[sig - 1].mask;
|
|
+ return (0);
|
|
+}
|
|
+
|
|
+int signal_set_handler(int sig, struct sigaction64 *sa64)
|
|
+{
|
|
+ struct sigaction sa;
|
|
+
|
|
+ if (sig <= 0 || sig > SIGRTMAX)
|
|
+ return (EINVAL);
|
|
+
|
|
+ sa.sa_flags = sa64->sa_flags;
|
|
+ sa.sa_mask = sa64->sa_mask;
|
|
+ if (sa64->sa_handler == 0)
|
|
+ sa.sa_handler = SIG_DFL;
|
|
+ else if (sa64->sa_handler == 1)
|
|
+ sa.sa_handler = SIG_IGN;
|
|
+ else {
|
|
+ sa.sa_sigaction = signal_handler;
|
|
+ sa.sa_flags |= SA_SIGINFO;
|
|
+ }
|
|
+ if (sigaction(sig, &sa, NULL) == -1)
|
|
+ return (errno);
|
|
+
|
|
+ siginfo[sig - 1].handler = sa64->sa_handler;
|
|
+ siginfo[sig - 1].flags = sa64->sa_flags;
|
|
+ siginfo[sig - 1].mask = sa64->sa_mask;
|
|
+ siginfo[sig - 1].valid = 1;
|
|
+ return (0);
|
|
+}
|