Blame hurd/catch-exc.c

Packit 6c4009
/* Copyright (C) 1994-2018 Free Software Foundation, Inc.
Packit 6c4009
   This file is part of the GNU C Library.
Packit 6c4009
Packit 6c4009
   The GNU C Library is free software; you can redistribute it and/or
Packit 6c4009
   modify it under the terms of the GNU Lesser General Public
Packit 6c4009
   License as published by the Free Software Foundation; either
Packit 6c4009
   version 2.1 of the License, or (at your option) any later version.
Packit 6c4009
Packit 6c4009
   The GNU C Library is distributed in the hope that it will be useful,
Packit 6c4009
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 6c4009
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 6c4009
   Lesser General Public License for more details.
Packit 6c4009
Packit 6c4009
   You should have received a copy of the GNU Lesser General Public
Packit 6c4009
   License along with the GNU C Library; if not, see
Packit 6c4009
   <http://www.gnu.org/licenses/>.  */
Packit 6c4009
Packit 6c4009
#include <mach/exc_server.h>
Packit 6c4009
#include <hurd/signal.h>
Packit 6c4009
#include <assert.h>
Packit 6c4009
Packit 6c4009
/* Called by the microkernel when a thread gets an exception.  */
Packit 6c4009
Packit 6c4009
kern_return_t
Packit 6c4009
_S_catch_exception_raise (mach_port_t port,
Packit 6c4009
			  thread_t thread,
Packit 6c4009
			  task_t task,
Packit 6c4009
#ifdef EXC_MASK_ALL		/* New interface flavor.  */
Packit 6c4009
			  exception_type_t exception,
Packit 6c4009
			  exception_data_t code,
Packit 6c4009
			  mach_msg_type_number_t codeCnt
Packit 6c4009
#else				/* Vanilla Mach 3.0 interface.  */
Packit 6c4009
			  integer_t exception,
Packit 6c4009
			  integer_t code, integer_t subcode
Packit 6c4009
#endif
Packit 6c4009
			  )
Packit 6c4009
{
Packit 6c4009
  struct hurd_sigstate *ss;
Packit 6c4009
  int signo;
Packit 6c4009
  struct hurd_signal_detail d;
Packit 6c4009
Packit 6c4009
  if (task != __mach_task_self ())
Packit 6c4009
    /* The sender wasn't the kernel.  */
Packit 6c4009
    return EPERM;
Packit 6c4009
Packit 6c4009
  d.exc = exception;
Packit 6c4009
#ifdef EXC_MASK_ALL
Packit 6c4009
  assert (codeCnt >= 2);
Packit 6c4009
  d.exc_code = code[0];
Packit 6c4009
  d.exc_subcode = code[1];
Packit 6c4009
#else
Packit 6c4009
  d.exc_code = code;
Packit 6c4009
  d.exc_subcode = subcode;
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
  /* Call the machine-dependent function to translate the Mach exception
Packit 6c4009
     codes into a signal number and subcode.  */
Packit 6c4009
  _hurd_exception2signal (&d, &signo);
Packit 6c4009
Packit 6c4009
  /* Find the sigstate structure for the faulting thread.  */
Packit 6c4009
  __mutex_lock (&_hurd_siglock);
Packit 6c4009
  for (ss = _hurd_sigstates; ss != NULL; ss = ss->next)
Packit 6c4009
    if (ss->thread == thread)
Packit 6c4009
      break;
Packit 6c4009
  __mutex_unlock (&_hurd_siglock);
Packit 6c4009
  if (ss == NULL)
Packit 6c4009
    ss = _hurd_thread_sigstate (thread); /* Allocate a fresh one.  */
Packit 6c4009
Packit 6c4009
  if (__spin_lock_locked (&ss->lock))
Packit 6c4009
    {
Packit 6c4009
      /* Loser.  The thread faulted with its sigstate lock held.  Its
Packit 6c4009
	 sigstate data is now suspect.  So we reset the parts of it which
Packit 6c4009
	 could cause trouble for the signal thread.  Anything else
Packit 6c4009
	 clobbered therein will just hose this user thread, but it's
Packit 6c4009
	 faulting already.
Packit 6c4009
Packit 6c4009
	 This is almost certainly a library bug: unless random memory
Packit 6c4009
	 clobberation caused the sigstate lock to gratuitously appear held,
Packit 6c4009
	 no code should do anything that can fault while holding the
Packit 6c4009
	 sigstate lock.  */
Packit 6c4009
Packit 6c4009
      __spin_unlock (&ss->critical_section_lock);
Packit 6c4009
      ss->context = NULL;
Packit 6c4009
      __spin_unlock (&ss->lock);
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  /* Post the signal.  */
Packit 6c4009
  _hurd_internal_post_signal (ss, signo, &d,
Packit 6c4009
			      MACH_PORT_NULL, MACH_MSG_TYPE_PORT_SEND,
Packit 6c4009
			      0);
Packit 6c4009
Packit 6c4009
  return KERN_SUCCESS;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
#ifdef EXC_MASK_ALL
Packit 6c4009
/* XXX New interface flavor has additional RPCs that we could be using
Packit 6c4009
   instead.  These RPCs roll a thread_get_state/thread_set_state into
Packit 6c4009
   the message, so the signal thread ought to use these to save some calls.
Packit 6c4009
 */
Packit 6c4009
kern_return_t
Packit 6c4009
_S_catch_exception_raise_state (mach_port_t port,
Packit 6c4009
				exception_type_t exception,
Packit 6c4009
				exception_data_t code,
Packit 6c4009
				mach_msg_type_number_t codeCnt,
Packit 6c4009
				int *flavor,
Packit 6c4009
				thread_state_t old_state,
Packit 6c4009
				mach_msg_type_number_t old_stateCnt,
Packit 6c4009
				thread_state_t new_state,
Packit 6c4009
				mach_msg_type_number_t *new_stateCnt)
Packit 6c4009
{
Packit 6c4009
  abort ();
Packit 6c4009
  return KERN_FAILURE;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
kern_return_t
Packit 6c4009
_S_catch_exception_raise_state_identity (mach_port_t exception_port,
Packit 6c4009
					 thread_t thread,
Packit 6c4009
					 task_t task,
Packit 6c4009
					 exception_type_t exception,
Packit 6c4009
					 exception_data_t code,
Packit 6c4009
					 mach_msg_type_number_t codeCnt,
Packit 6c4009
					 int *flavor,
Packit 6c4009
					 thread_state_t old_state,
Packit 6c4009
					 mach_msg_type_number_t old_stateCnt,
Packit 6c4009
					 thread_state_t new_state,
Packit 6c4009
					 mach_msg_type_number_t *new_stateCnt)
Packit 6c4009
{
Packit 6c4009
  abort ();
Packit 6c4009
  return KERN_FAILURE;
Packit 6c4009
}
Packit 6c4009
#endif