From 7974fe2117b1308a46f16ae5803c64f75303521c Mon Sep 17 00:00:00 2001 From: Roland McGrath Date: Thu, 4 Jan 1996 17:00:45 +0000 Subject: [PATCH] Thu Jan 4 11:35:18 1996 Roland McGrath * 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. --- ChangeLog | 16 +++++++++ hurd/Makefile | 10 +++--- hurd/hurdfault.c | 42 +++++++++++------------ hurd/hurdfault.h | 24 +++++++------- sysdeps/mach/hurd/i386/trampoline.c | 25 +++++--------- sysdeps/mach/hurd/setitimer.c | 66 +++++++++++++++++++++---------------- 6 files changed, 102 insertions(+), 81 deletions(-) diff --git a/ChangeLog b/ChangeLog index 42bd5c6..c7b7ded 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,19 @@ +Thu Jan 4 11:35:18 1996 Roland McGrath + + * 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 * hurd/catch-signal.c: New file. diff --git a/hurd/Makefile b/hurd/Makefile index 69f9e96..fe9e43e 100644 --- a/hurd/Makefile +++ b/hurd/Makefile @@ -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 diff --git a/hurd/hurdfault.c b/hurd/hurdfault.c index 5aedc58..2a30db0 100644 --- a/hurd/hurdfault.c +++ b/hurd/hurdfault.c @@ -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 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_expect_signo = 0; + _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); + + 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); diff --git a/hurd/hurdfault.h b/hurd/hurdfault.h index 00ec905..4b6aaed 100644 --- a/hurd/hurdfault.h +++ b/hurd/hurdfault.h @@ -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 #include /* 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; +extern struct hurd_signal_preempter _hurdsig_fault_preempter; -/* If _hurdsig_catch_fault returns nonzero, these variables - contain information about the signal that arrived. */ +#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 */ diff --git a/sysdeps/mach/hurd/i386/trampoline.c b/sysdeps/mach/hurd/i386/trampoline.c index 9e947a4..f64539a 100644 --- a/sysdeps/mach/hurd/i386/trampoline.c +++ b/sysdeps/mach/hurd/i386/trampoline.c @@ -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 #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; } diff --git a/sysdeps/mach/hurd/setitimer.c b/sysdeps/mach/hurd/setitimer.c index 4f494a4..cba1d0e 100644 --- a/sysdeps/mach/hurd/setitimer.c +++ b/sysdeps/mach/hurd/setitimer.c @@ -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 #include #include +#include #include #include @@ -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 = + { + __sigmask (SIGALRM), 0, 0, + &restart_itimer, + }; + __mutex_lock (&_hurd_siglock); + if (! preempter.next && _hurdsig_preempters != &preempter) { - static struct hurd_signal_preempt preempt = - { preempt_sigalrm, 0, 0, NULL }; - _hurd_signal_preempt[SIGALRM] = &preempt; + 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) -- 2.7.4