New file.
[kopensolaris-gnu/glibc.git] / hurd / hurdfault.c
1 /* Handle faults in the signal thread.
2 Copyright (C) 1994, 1995 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 License, or (at your option) any later version.
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public
16 License along with the GNU C Library; see the file COPYING.LIB.  If
17 not, write to the Free Software Foundation, Inc., 675 Mass Ave,
18 Cambridge, MA 02139, USA.  */
19
20 #include <hurd.h>
21 #include <hurd/signal.h>
22 #include "hurdfault.h"
23 #include <errno.h>
24 #include <string.h>
25 #include <setjmp.h>
26 #include <stdio.h>
27 #include "thread_state.h"
28 #include "faultexc.h"           /* mig-generated header for our exc server.  */
29 #include <assert.h>
30
31 jmp_buf _hurdsig_fault_env;
32
33 static mach_port_t forward_sigexc;
34
35 int _hurdsig_fault_expect_signo;
36 long int _hurdsig_fault_sigcode;
37 int _hurdsig_fault_sigerror;
38
39 kern_return_t
40 _hurdsig_fault_catch_exception_raise (mach_port_t port,
41                                       thread_t thread,
42                                       task_t task,
43                                       int exception,
44                                       int code,
45                                       int subcode)
46 {
47   int signo;
48
49   if (port != forward_sigexc ||
50       thread != _hurd_msgport_thread || task != __mach_task_self ())
51     return EPERM;               /* Strange bogosity.  */
52
53   /* Call the machine-dependent function to translate the Mach exception
54      codes into a signal number and subcode.  */
55   _hurd_exception2signal (exception, code, subcode, &signo,
56                           &_hurdsig_fault_sigcode, &_hurdsig_fault_sigerror);
57
58   return signo == _hurdsig_fault_expect_signo ? 0 : EGREGIOUS;
59 }
60
61 static void
62 faulted (void)
63 {
64   struct
65     {
66       mach_msg_header_t head;
67       char buf[64];
68     } request;
69   struct
70     {
71       mach_msg_header_t head;
72       mach_msg_type_t type;
73       int result;
74     } reply;
75   extern int _hurdsig_fault_exc_server (mach_msg_header_t *,
76                                         mach_msg_header_t *);
77
78  /* Wait for the exception_raise message forwarded by the proc server.  */
79
80  if (__mach_msg (&request.head, MACH_RCV_MSG, 0,
81                   sizeof request, forward_sigexc,
82                   MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL)
83       != MACH_MSG_SUCCESS)
84     __libc_fatal ("msg receive failed on signal thread exc\n");
85
86   /* Run the exc demuxer which should call the server function above.
87      That function returns 0 if the exception was expected.  */
88   switch (_hurdsig_fault_exc_server (&request.head, &reply.head))
89     {
90     case KERN_SUCCESS:
91       if (reply.head.msgh_remote_port != MACH_PORT_NULL)
92         __mach_msg (&reply.head, MACH_SEND_MSG, reply.head.msgh_size,
93                     0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
94       break;
95     default:
96       __mach_msg_destroy (&request.head);
97     case MIG_NO_REPLY:
98     }
99
100   _hurdsig_fault_expect_signo = 0;
101   longjmp (_hurdsig_fault_env, 1);
102 }
103
104 static char faultstack[1024];
105
106 /* Send exceptions for the signal thread to the proc server.
107    It will forward the message on to our message port,
108    and then restore the thread's state to code which
109    does `longjmp (_hurd_sigthread_fault_env, 1)'.  */
110
111 void
112 _hurdsig_fault_init (void)
113 {
114   error_t err;
115   struct machine_thread_state state;
116   mach_port_t sigexc;
117
118   err = __mach_port_allocate (__mach_task_self (),
119                               MACH_PORT_RIGHT_RECEIVE, &sigexc);
120   assert_perror (err);
121   err = __mach_port_allocate (__mach_task_self (),
122                               MACH_PORT_RIGHT_RECEIVE, &forward_sigexc);
123   assert_perror (err);
124
125   err = __mach_port_insert_right (__mach_task_self (), sigexc,
126                                   sigexc, MACH_MSG_TYPE_MAKE_SEND);
127   assert_perror (err);
128   err = __thread_set_special_port (_hurd_msgport_thread,
129                                    THREAD_EXCEPTION_PORT, sigexc);
130   __mach_port_deallocate (__mach_task_self (), sigexc);
131   assert_perror (err);
132
133   memset (&state, 0, sizeof state);
134   MACHINE_THREAD_STATE_SET_PC (&state, faulted);
135   MACHINE_THREAD_STATE_SET_SP (&state, faultstack, sizeof faultstack);
136
137   err = __USEPORT
138     (PROC,
139      __proc_handle_exceptions (port,
140                                sigexc,
141                                forward_sigexc, MACH_MSG_TYPE_MAKE_SEND,
142                                MACHINE_THREAD_STATE_FLAVOR,
143                                (natural_t *) &state,
144                                MACHINE_THREAD_STATE_COUNT));
145   assert_perror (err);
146 }
147