Back to index

glibc  2.9
catch-exc.c
Go to the documentation of this file.
00001 /* Copyright (C) 1994,95,96,97,2002 Free Software Foundation, Inc.
00002    This file is part of the GNU C Library.
00003 
00004    The GNU C Library is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Lesser General Public
00006    License as published by the Free Software Foundation; either
00007    version 2.1 of the License, or (at your option) any later version.
00008 
00009    The GNU C Library is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012    Lesser General Public License for more details.
00013 
00014    You should have received a copy of the GNU Lesser General Public
00015    License along with the GNU C Library; if not, write to the Free
00016    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00017    02111-1307 USA.  */
00018 
00019 #include <mach/exc_server.h>
00020 #include <hurd/signal.h>
00021 #include <assert.h>
00022 
00023 /* Called by the microkernel when a thread gets an exception.  */
00024 
00025 kern_return_t
00026 _S_catch_exception_raise (mach_port_t port,
00027                        thread_t thread,
00028                        task_t task,
00029 #ifdef EXC_MASK_ALL         /* New interface flavor.  */
00030                        exception_type_t exception,
00031                        exception_data_t code,
00032                        mach_msg_type_number_t codeCnt
00033 #else                       /* Vanilla Mach 3.0 interface.  */
00034                        integer_t exception,
00035                        integer_t code, integer_t subcode
00036 #endif
00037                        )
00038 {
00039   struct hurd_sigstate *ss;
00040   int signo;
00041   struct hurd_signal_detail d;
00042 
00043   if (task != __mach_task_self ())
00044     /* The sender wasn't the kernel.  */
00045     return EPERM;
00046 
00047   d.exc = exception;
00048 #ifdef EXC_MASK_ALL
00049   assert (codeCnt >= 2);
00050   d.exc_code = code[0];
00051   d.exc_subcode = code[1];
00052 #else
00053   d.exc_code = code;
00054   d.exc_subcode = subcode;
00055 #endif
00056 
00057   /* Call the machine-dependent function to translate the Mach exception
00058      codes into a signal number and subcode.  */
00059   _hurd_exception2signal (&d, &signo);
00060 
00061   /* Find the sigstate structure for the faulting thread.  */
00062   __mutex_lock (&_hurd_siglock);
00063   for (ss = _hurd_sigstates; ss != NULL; ss = ss->next)
00064     if (ss->thread == thread)
00065       break;
00066   __mutex_unlock (&_hurd_siglock);
00067   if (ss == NULL)
00068     ss = _hurd_thread_sigstate (thread); /* Allocate a fresh one.  */
00069 
00070   if (__spin_lock_locked (&ss->lock))
00071     {
00072       /* Loser.  The thread faulted with its sigstate lock held.  Its
00073         sigstate data is now suspect.  So we reset the parts of it which
00074         could cause trouble for the signal thread.  Anything else
00075         clobbered therein will just hose this user thread, but it's
00076         faulting already.
00077 
00078         This is almost certainly a library bug: unless random memory
00079         clobberation caused the sigstate lock to gratuitously appear held,
00080         no code should do anything that can fault while holding the
00081         sigstate lock.  */
00082 
00083       __spin_unlock (&ss->critical_section_lock);
00084       ss->context = NULL;
00085       __spin_unlock (&ss->lock);
00086     }
00087 
00088   /* Post the signal.  */
00089   _hurd_internal_post_signal (ss, signo, &d,
00090                            MACH_PORT_NULL, MACH_MSG_TYPE_PORT_SEND,
00091                            0);
00092 
00093   return KERN_SUCCESS;
00094 }
00095 
00096 #ifdef EXC_MASK_ALL
00097 /* XXX New interface flavor has additional RPCs that we could be using
00098    instead.  These RPCs roll a thread_get_state/thread_set_state into
00099    the message, so the signal thread ought to use these to save some calls.
00100  */
00101 kern_return_t
00102 _S_catch_exception_raise_state (mach_port_t port,
00103                             exception_type_t exception,
00104                             exception_data_t code,
00105                             mach_msg_type_number_t codeCnt,
00106                             int *flavor,
00107                             thread_state_t old_state,
00108                             mach_msg_type_number_t old_stateCnt,
00109                             thread_state_t new_state,
00110                             mach_msg_type_number_t *new_stateCnt)
00111 {
00112   abort ();
00113   return KERN_FAILURE;
00114 }
00115 
00116 kern_return_t
00117 _S_catch_exception_raise_state_identity (mach_port_t exception_port,
00118                                     thread_t thread,
00119                                     task_t task,
00120                                     exception_type_t exception,
00121                                     exception_data_t code,
00122                                     mach_msg_type_number_t codeCnt,
00123                                     int *flavor,
00124                                     thread_state_t old_state,
00125                                     mach_msg_type_number_t old_stateCnt,
00126                                     thread_state_t new_state,
00127                                     mach_msg_type_number_t *new_stateCnt)
00128 {
00129   abort ();
00130   return KERN_FAILURE;
00131 }
00132 #endif