diff options
Diffstat (limited to 'REORG.TODO/hurd/catch-exc.c')
-rw-r--r-- | REORG.TODO/hurd/catch-exc.c | 131 |
1 files changed, 131 insertions, 0 deletions
diff --git a/REORG.TODO/hurd/catch-exc.c b/REORG.TODO/hurd/catch-exc.c new file mode 100644 index 0000000000..1a4fa95c9f --- /dev/null +++ b/REORG.TODO/hurd/catch-exc.c @@ -0,0 +1,131 @@ +/* Copyright (C) 1994-2017 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 <mach/exc_server.h> +#include <hurd/signal.h> +#include <assert.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, +#ifdef EXC_MASK_ALL /* New interface flavor. */ + exception_type_t exception, + exception_data_t code, + mach_msg_type_number_t codeCnt +#else /* Vanilla Mach 3.0 interface. */ + integer_t exception, + integer_t code, integer_t subcode +#endif + ) +{ + struct hurd_sigstate *ss; + int signo; + struct hurd_signal_detail d; + + if (task != __mach_task_self ()) + /* The sender wasn't the kernel. */ + return EPERM; + + d.exc = exception; +#ifdef EXC_MASK_ALL + assert (codeCnt >= 2); + d.exc_code = code[0]; + d.exc_subcode = code[1]; +#else + d.exc_code = code; + d.exc_subcode = subcode; +#endif + + /* Call the machine-dependent function to translate the Mach exception + codes into a signal number and subcode. */ + _hurd_exception2signal (&d, &signo); + + /* 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. */ + + __spin_unlock (&ss->critical_section_lock); + ss->context = NULL; + __spin_unlock (&ss->lock); + } + + /* Post the signal. */ + _hurd_internal_post_signal (ss, signo, &d, + MACH_PORT_NULL, MACH_MSG_TYPE_PORT_SEND, + 0); + + return KERN_SUCCESS; +} + +#ifdef EXC_MASK_ALL +/* XXX New interface flavor has additional RPCs that we could be using + instead. These RPCs roll a thread_get_state/thread_set_state into + the message, so the signal thread ought to use these to save some calls. + */ +kern_return_t +_S_catch_exception_raise_state (mach_port_t port, + exception_type_t exception, + exception_data_t code, + mach_msg_type_number_t codeCnt, + int *flavor, + thread_state_t old_state, + mach_msg_type_number_t old_stateCnt, + thread_state_t new_state, + mach_msg_type_number_t *new_stateCnt) +{ + abort (); + return KERN_FAILURE; +} + +kern_return_t +_S_catch_exception_raise_state_identity (mach_port_t exception_port, + thread_t thread, + task_t task, + exception_type_t exception, + exception_data_t code, + mach_msg_type_number_t codeCnt, + int *flavor, + thread_state_t old_state, + mach_msg_type_number_t old_stateCnt, + thread_state_t new_state, + mach_msg_type_number_t *new_stateCnt) +{ + abort (); + return KERN_FAILURE; +} +#endif |