aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'hurd/catch-exc.c')
-rw-r--r--hurd/catch-exc.c78
1 files changed, 78 insertions, 0 deletions
diff --git a/hurd/catch-exc.c b/hurd/catch-exc.c
new file mode 100644
index 0000000000..72e06db1d3
--- /dev/null
+++ b/hurd/catch-exc.c
@@ -0,0 +1,78 @@
+/* Copyright (C) 1994, 1995 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 Library General Public License as
+published by the Free Software Foundation; either version 2 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <mach/exc_server.h>
+#include <hurd/signal.h>
+
+/* Called by the microkernel when a thread gets an exception. */
+
+kern_return_t
+_S_catch_exception_raise (mach_port_t port,
+ thread_t thread,
+ task_t task,
+ int exception,
+ int code,
+ int subcode)
+{
+ int signo, error;
+ long int sigcode;
+ struct hurd_sigstate *ss;
+
+ if (task != __mach_task_self ())
+ /* The sender wasn't the kernel. */
+ return EPERM;
+
+ /* Call the machine-dependent function to translate the Mach exception
+ codes into a signal number and subcode. */
+ _hurd_exception2signal (exception, code, subcode,
+ &signo, &sigcode, &error);
+
+ /* Find the sigstate structure for the faulting thread. */
+ __mutex_lock (&_hurd_siglock);
+ for (ss = _hurd_sigstates; ss != NULL; ss = ss->next)
+ if (ss->thread == thread)
+ break;
+ __mutex_unlock (&_hurd_siglock);
+ if (ss == NULL)
+ ss = _hurd_thread_sigstate (thread); /* Allocate a fresh one. */
+
+ if (__spin_lock_locked (&ss->lock))
+ {
+ /* Loser. The thread faulted with its sigstate lock held. Its
+ sigstate data is now suspect. So we reset the parts of it which
+ could cause trouble for the signal thread. Anything else
+ clobbered therein will just hose this user thread, but it's
+ faulting already.
+
+ This is almost certainly a library bug: unless random memory
+ clobberation caused the sigstate lock to gratuitously appear held,
+ no code should do anything that can fault while holding the
+ sigstate lock. */
+
+ ss->critical_section = 0;
+ ss->context = NULL;
+ __spin_unlock (&ss->lock);
+ }
+
+ /* Post the signal. */
+ _hurd_internal_post_signal (ss, signo, sigcode, error,
+ MACH_PORT_NULL, MACH_MSG_TYPE_PORT_SEND,
+ 0);
+
+ return KERN_SUCCESS;
+}