Thu Jan 4 11:35:18 1996 Roland McGrath <roland@churchy.gnu.ai.mit.edu>

* sysdeps/mach/hurd/setitimer.c: Code rearranged a bit to use new
	preemption interface.

	* sysdeps/mach/hurd/i386/trampoline.c (_hurd_setup_sighandler):
	Use _hurdsig_catch_memory_fault.

	* hurd/Makefile (headers): Add hurd/sigpreempt.h.
	(sig): Add catch-signal.

	* hurd/hurdfault.c (_hurdsig_fault_catch_exception_raise):
	Rewritten using a preempter in new interface.
	* hurd/hurdfault.h (_hurdsig_catch_fault): Likewise.
	(_hurdsig_catch_memory_fault): New macro.
This commit is contained in:
Roland McGrath 1996-01-04 17:00:45 +00:00
parent fb8e70d6dd
commit 7974fe2117
6 changed files with 101 additions and 80 deletions

View File

@ -1,3 +1,19 @@
Thu Jan 4 11:35:18 1996 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
* sysdeps/mach/hurd/setitimer.c: Code rearranged a bit to use new
preemption interface.
* sysdeps/mach/hurd/i386/trampoline.c (_hurd_setup_sighandler):
Use _hurdsig_catch_memory_fault.
* hurd/Makefile (headers): Add hurd/sigpreempt.h.
(sig): Add catch-signal.
* hurd/hurdfault.c (_hurdsig_fault_catch_exception_raise):
Rewritten using a preempter in new interface.
* hurd/hurdfault.h (_hurdsig_catch_fault): Likewise.
(_hurdsig_catch_memory_fault): New macro.
Wed Jan 3 20:23:42 1996 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
* hurd/catch-signal.c: New file.

View File

@ -1,4 +1,4 @@
# Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
# Copyright (C) 1991, 92, 93, 94, 95, 96 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
@ -25,8 +25,8 @@ include ../Makeconfig
headers = hurd.h $(interface-headers) \
$(addprefix hurd/,fd.h id.h port.h signal.h userlink.h \
resource.h threadvar.h lookup.h)
$(addprefix hurd/,fd.h id.h port.h signal.h sigpreempt.h \
userlink.h resource.h threadvar.h lookup.h)
distribute := hurdstartup.h hurdfault.h intr-rpc.defs STATUS
@ -51,10 +51,10 @@ routines = hurdstartup hurdinit \
fopenport \
vpprintf \
ports-get ports-set hurdports hurdmsg \
$(sig) $(dtable) hurdinline port-cleanup
$(sig) $(dtable) hurdinline port-cleanup # report-wait
sig = hurdsig hurdfault faultexc siginfo hurd-raise preempt-sig \
trampoline longjmp-ts catch-exc exc2signal hurdkill sigunwind \
thread-self thread-cancel intr-msg
thread-self thread-cancel intr-msg catch-signal
dtable = dtable port2fd new-fd alloc-fd intern-fd \
getdport openport \
fd-close fd-read fd-write hurdioctl ctty-input ctty-output

View File

@ -1,5 +1,5 @@
/* Handle faults in the signal thread.
Copyright (C) 1994, 1995 Free Software Foundation, Inc.
Copyright (C) 1994, 1995, 1996 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
@ -29,13 +29,10 @@ Cambridge, MA 02139, USA. */
#include <assert.h>
jmp_buf _hurdsig_fault_env;
struct hurd_signal_preempter _hurdsig_fault_preempter;
static mach_port_t forward_sigexc;
int _hurdsig_fault_expect_signo;
long int _hurdsig_fault_sigcode;
int _hurdsig_fault_sigerror;
kern_return_t
_hurdsig_fault_catch_exception_raise (mach_port_t port,
thread_t thread,
@ -45,6 +42,8 @@ _hurdsig_fault_catch_exception_raise (mach_port_t port,
int subcode)
{
int signo;
long int sigcode;
int sigerror;
if (port != forward_sigexc ||
thread != _hurd_msgport_thread || task != __mach_task_self ())
@ -52,10 +51,11 @@ _hurdsig_fault_catch_exception_raise (mach_port_t port,
/* Call the machine-dependent function to translate the Mach exception
codes into a signal number and subcode. */
_hurd_exception2signal (exception, code, subcode, &signo,
&_hurdsig_fault_sigcode, &_hurdsig_fault_sigerror);
_hurd_exception2signal (exception, code, subcode,
&signo, &sigcode, &sigerror);
return signo == _hurdsig_fault_expect_signo ? 0 : EGREGIOUS;
return HURD_PREEMPT_SIGNAL_P (&_hurdsig_fault_preempter, signo, sigcode)
? 0 : EGREGIOUS;
}
static void
@ -85,19 +85,17 @@ faulted (void)
/* Run the exc demuxer which should call the server function above.
That function returns 0 if the exception was expected. */
switch (_hurdsig_fault_exc_server (&request.head, &reply.head))
{
case KERN_SUCCESS:
if (reply.head.msgh_remote_port != MACH_PORT_NULL)
__mach_msg (&reply.head, MACH_SEND_MSG, reply.head.msgh_size,
0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
break;
default:
__mach_msg_destroy (&request.head);
case MIG_NO_REPLY:
}
_hurdsig_fault_exc_server (&request.head, &reply.head);
if (reply.head.msgh_remote_port != MACH_PORT_NULL)
__mach_msg (&reply.head, MACH_SEND_MSG, reply.head.msgh_size,
0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
if (reply.result == MIG_BAD_ID)
__mach_msg_destroy (&request.head);
_hurdsig_fault_expect_signo = 0;
if (reply.result)
__libc_fatal ("BUG: unexpected fault in signal thread\n");
_hurdsig_fault_preempter.signals = 0;
longjmp (_hurdsig_fault_env, 1);
}
@ -125,8 +123,10 @@ _hurdsig_fault_init (void)
err = __mach_port_insert_right (__mach_task_self (), sigexc,
sigexc, MACH_MSG_TYPE_MAKE_SEND);
assert_perror (err);
#if 0 /* XXX gdb bites */
err = __thread_set_special_port (_hurd_msgport_thread,
THREAD_EXCEPTION_PORT, sigexc);
#endif
__mach_port_deallocate (__mach_task_self (), sigexc);
assert_perror (err);

View File

@ -1,5 +1,5 @@
/* Declarations for handling faults in the signal thread.
Copyright (C) 1994 Free Software Foundation, Inc.
Copyright (C) 1994, 1996 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
@ -20,6 +20,7 @@ Cambridge, MA 02139, USA. */
#ifndef _HURD_FAULT_H
#define _HURD_FAULT_H
#include <hurd/sigpreempt.h>
#include <setjmp.h>
/* Call this before code that might fault in the signal thread; SIGNO is
@ -27,23 +28,24 @@ Cambridge, MA 02139, USA. */
returns zero the first time, and returns again nonzero if the signal
does arrive. */
#define _hurdsig_catch_fault(signo) \
(_hurdsig_fault_expect_signo = (signo), setjmp (_hurdsig_fault_env))
#define _hurdsig_catch_fault(sigset, firstcode, lastcode) \
(_hurdsig_fault_preempter.signals = (sigset), \
_hurdsig_fault_preempter.first = (long int) (firstcode), \
_hurdsig_fault_preempter.last = (long int) (lastcode), \
setjmp (_hurdsig_fault_env))
/* Call this at the end of a section protected by _hurdsig_catch_fault. */
#define _hurdsig_end_catch_fault() \
(_hurdsig_fault_expect_signo = 0)
(_hurdsig_fault_preempter.signals = 0)
extern jmp_buf _hurdsig_fault_env;
extern int _hurdsig_fault_expect_signo;
/* If _hurdsig_catch_fault returns nonzero, these variables
contain information about the signal that arrived. */
extern struct hurd_signal_preempter _hurdsig_fault_preempter;
#define _hurdsig_catch_memory_fault(object) \
_hurdsig_catch_fault (sigmask (SIGSEGV) | sigmask (SIGBUS), \
(object), (object) + 1)
extern long int _hurdsig_fault_sigcode;
extern int _hurdsig_fault_sigerror;
#endif /* hurd/fault.h */
#endif /* hurdfault.h */

View File

@ -1,5 +1,5 @@
/* Set thread_state for sighandler, and sigcontext to recover. i386 version.
Copyright (C) 1994, 1995 Free Software Foundation, Inc.
Copyright (C) 1994, 1995, 1996 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
@ -24,7 +24,7 @@ Cambridge, MA 02139, USA. */
#include <errno.h>
#include "hurdfault.h"
struct mach_msg_trap_args
{
void *retaddr; /* Address mach_msg_trap will return to. */
@ -50,7 +50,7 @@ _hurd_setup_sighandler (struct hurd_sigstate *ss, __sighandler_t handler,
extern const void _hurd_intr_rpc_msg_sp_restored;
void *volatile sigsp;
struct sigcontext *scp;
struct
struct
{
int signo;
long int sigcode;
@ -67,10 +67,7 @@ _hurd_setup_sighandler (struct hurd_sigstate *ss, __sighandler_t handler,
/* We have a previous sigcontext that sigreturn was about
to restore when another signal arrived. We will just base
our setup on that. */
if (_hurdsig_catch_fault (SIGSEGV))
assert (_hurdsig_fault_sigcode >= (long int) ss->context &&
_hurdsig_fault_sigcode < (long int) (ss->context + 1));
else
if (! _hurdsig_catch_memory_fault (ss->context))
{
memcpy (&state->basic, &ss->context->sc_i386_thread_state,
sizeof (state->basic));
@ -97,7 +94,7 @@ _hurd_setup_sighandler (struct hurd_sigstate *ss, __sighandler_t handler,
per-thread variables, cthreads. */
}
/* This code has intimate knowledge of the special mach_msg system call
done in intr-msg.c; that code does:
done in intr-msg.c; that code does:
movl %esp, %ecx
leal ARGS, %esp
_hurd_intr_rpc_msg_cx_sp: movl $-25, %eax
@ -107,7 +104,7 @@ _hurd_setup_sighandler (struct hurd_sigstate *ss, __sighandler_t handler,
We must check for the window during which %esp points at the
mach_msg arguments. The space below until %ecx is used by
the _hurd_intr_rpc_mach_msg frame, and must not be clobbered. */
else if (state->basic.eip >= (int) &_hurd_intr_rpc_msg_cx_sp &&
else if (state->basic.eip >= (int) &_hurd_intr_rpc_msg_cx_sp &&
state->basic.eip < (int) &_hurd_intr_rpc_msg_sp_restored)
/* The SP now points at the mach_msg args, but there is more stack
space used below it. The real SP is saved in %ecx; we must push the
@ -121,10 +118,8 @@ _hurd_setup_sighandler (struct hurd_sigstate *ss, __sighandler_t handler,
sigsp -= sizeof (*stackframe);
stackframe = sigsp;
if (_hurdsig_catch_fault (SIGSEGV))
if (_hurdsig_catch_memory_fault (stackframe))
{
assert (_hurdsig_fault_sigcode >= (long int) stackframe &&
_hurdsig_fault_sigcode <= (long int) (stackframe + 1));
/* We got a fault trying to write the stack frame.
We cannot set up the signal handler.
Returning NULL tells our caller, who will nuke us with a SIGILL. */
@ -187,17 +182,15 @@ _hurd_setup_sighandler (struct hurd_sigstate *ss, __sighandler_t handler,
still waiting for a reply. We will have it run the special
trampoline code which retries the message receive before running
the signal handler.
To do this we change the OPTION argument on its stack to enable only
message reception, since the request message has already been
sent. */
struct mach_msg_trap_args *args = (void *) state->basic.esp;
if (_hurdsig_catch_fault (SIGSEGV))
if (_hurdsig_catch_memory_fault (args))
{
assert (_hurdsig_fault_sigcode >= (long int) args &&
_hurdsig_fault_sigcode < (long int) (args + 1));
/* Faulted accessing ARGS. Bomb. */
return NULL;
}

View File

@ -1,4 +1,4 @@
/* Copyright (C) 1994, 1995 Free Software Foundation, Inc.
/* Copyright (C) 1994, 1995, 1996 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
@ -22,6 +22,7 @@ Cambridge, MA 02139, USA. */
#include <sys/time.h>
#include <hurd.h>
#include <hurd/signal.h>
#include <hurd/sigpreempt.h>
#include <hurd/msg_request.h>
#include <mach/message.h>
@ -109,9 +110,29 @@ timer_thread (void)
}
}
/* Forward declaration. */
static sighandler_t preempt_sigalrm (thread_t thread, int signo,
long int sigcode, int sigerror);
static sighandler_t
restart_itimer (struct hurd_signal_preempter *preempter,
struct hurd_sigstate *ss,
int *signo, long int *sigcode,
int *sigerror)
{
static int setitimer_locked (const struct itimerval *new,
struct itimerval *old, void *crit);
/* This function gets called in the signal thread
each time a SIGALRM is arriving (even if blocked). */
struct itimerval it;
/* Either reload or disable the itimer. */
__spin_lock (&_hurd_itimer_lock);
it.it_value = it.it_interval = _hurd_itimerval.it_interval;
setitimer_locked (&it, NULL, NULL);
/* Continue with normal delivery (or hold, etc.) of SIGALRM. */
return SIG_ERR;
}
/* Called before any normal SIGALRM signal is delivered.
Reload the itimer, or disable the itimer. */
@ -138,12 +159,20 @@ setitimer_locked (const struct itimerval *new, struct itimerval *old,
{
/* Make sure the itimer thread is set up. */
if (_hurd_signal_preempt[SIGALRM] == NULL)
/* Set up a signal preempter global for all threads to
run `restart_itimer' each time a SIGALRM would arrive. */
static struct hurd_signal_preempter preempter =
{
static struct hurd_signal_preempt preempt =
{ preempt_sigalrm, 0, 0, NULL };
_hurd_signal_preempt[SIGALRM] = &preempt;
__sigmask (SIGALRM), 0, 0,
&restart_itimer,
};
__mutex_lock (&_hurd_siglock);
if (! preempter.next && _hurdsig_preempters != &preempter)
{
preempter.next = _hurdsig_preempters;
_hurdsig_preempters = &preempter;
}
__mutex_unlock (&_hurd_siglock);
if (_hurd_itimer_port == MACH_PORT_NULL)
{
@ -170,7 +199,7 @@ setitimer_locked (const struct itimerval *new, struct itimerval *old,
&_hurd_itimer_thread_stack_size))
{
__thread_terminate (_hurd_itimer_thread);
_hurd_itimer_thread = MACH_PORT_NULL;
_hurd_itimer_thread = MACH_PORT_NULL;
goto out;
}
_hurd_itimer_thread_suspended = 1;
@ -293,25 +322,6 @@ DEFUN(__setitimer, (which, new, old),
__spin_lock (&_hurd_itimer_lock);
return setitimer_locked (new, old, crit);
}
static sighandler_t
preempt_sigalrm (thread_t thread, int signo, long int sigcode, int sigerror)
{
struct itimerval it;
if (thread != _hurd_sigthread || signo != SIGALRM || sigcode != 0)
/* Too much monkey business. */
return SIG_DFL;
/* Either reload or disable the itimer. */
__spin_lock (&_hurd_itimer_lock);
it = _hurd_itimerval;
it.it_value = it.it_interval;
setitimer_locked (&it, NULL, NULL);
/* Continue with normal delivery of SIGALRM. */
return SIG_DFL;
}
static void
fork_itimer (void)