Sun Feb 18 12:13:07 1996 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
[glibc/history.git] / hurd / hurdfault.c
blobbb6fa9576d879f44df2d5f7b9520c4610bfb5936
1 /* Handle faults in the signal thread.
2 Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
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.
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.
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. */
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>
31 jmp_buf _hurdsig_fault_env;
32 struct hurd_signal_preempter _hurdsig_fault_preempter;
34 static mach_port_t forward_sigexc;
36 kern_return_t
37 _hurdsig_fault_catch_exception_raise (mach_port_t port,
38 thread_t thread,
39 task_t task,
40 int exception,
41 int code,
42 int subcode)
44 int signo;
45 long int sigcode;
46 int sigerror;
48 if (port != forward_sigexc ||
49 thread != _hurd_msgport_thread || task != __mach_task_self ())
50 return EPERM; /* Strange bogosity. */
52 /* Call the machine-dependent function to translate the Mach exception
53 codes into a signal number and subcode. */
54 _hurd_exception2signal (exception, code, subcode,
55 &signo, &sigcode, &sigerror);
57 return HURD_PREEMPT_SIGNAL_P (&_hurdsig_fault_preempter, signo, sigcode)
58 ? 0 : EGREGIOUS;
61 static void
62 faulted (void)
64 struct
66 mach_msg_header_t head;
67 char buf[64];
68 } request;
69 struct
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 *);
78 /* Wait for the exception_raise message forwarded by the proc server. */
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");
86 /* Run the exc demuxer which should call the server function above.
87 That function returns 0 if the exception was expected. */
88 _hurdsig_fault_exc_server (&request.head, &reply.head);
89 if (reply.head.msgh_remote_port != MACH_PORT_NULL)
90 __mach_msg (&reply.head, MACH_SEND_MSG, reply.head.msgh_size,
91 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
92 if (reply.result == MIG_BAD_ID)
93 __mach_msg_destroy (&request.head);
95 if (reply.result)
96 __libc_fatal ("BUG: unexpected fault in signal thread\n");
98 _hurdsig_fault_preempter.signals = 0;
99 longjmp (_hurdsig_fault_env, 1);
102 static char faultstack[1024];
104 /* Send exceptions for the signal thread to the proc server.
105 It will forward the message on to our message port,
106 and then restore the thread's state to code which
107 does `longjmp (_hurd_sigthread_fault_env, 1)'. */
109 void
110 _hurdsig_fault_init (void)
112 error_t err;
113 struct machine_thread_state state;
114 mach_port_t sigexc;
116 /* Allocate a port to receive signal thread exceptions.
117 We will move this receive right to the proc server. */
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);
125 /* Allocate a port to receive the exception msgs forwarded
126 from the proc server. */
127 err = __mach_port_insert_right (__mach_task_self (), sigexc,
128 sigexc, MACH_MSG_TYPE_MAKE_SEND);
129 assert_perror (err);
131 /* Set the queue limit for this port to just one. The proc server will
132 notice if we ever get a second exception while one remains queued and
133 unreceived, and decide we are hopelessly buggy. */
134 err = __mach_port_set_qlimit (__mach_task_self (), forward_sigexc, 1);
135 assert_perror (err);
137 /* This state will be restored when we fault.
138 It runs the function above. */
139 memset (&state, 0, sizeof state);
140 MACHINE_THREAD_STATE_SET_PC (&state, faulted);
141 MACHINE_THREAD_STATE_SET_SP (&state, faultstack, sizeof faultstack);
143 err = __USEPORT
144 (PROC,
145 __proc_handle_exceptions (port,
146 sigexc,
147 forward_sigexc, MACH_MSG_TYPE_MAKE_SEND,
148 MACHINE_THREAD_STATE_FLAVOR,
149 (natural_t *) &state,
150 MACHINE_THREAD_STATE_COUNT));
151 assert_perror (err);
153 /* Direct signal thread exceptions to the proc server. */
154 err = __thread_set_special_port (_hurd_msgport_thread,
155 THREAD_EXCEPTION_PORT, sigexc);
156 __mach_port_deallocate (__mach_task_self (), sigexc);
157 assert_perror (err);