diff options
Diffstat (limited to 'sysdeps/mach/hurd/setitimer.c')
-rw-r--r-- | sysdeps/mach/hurd/setitimer.c | 66 |
1 files changed, 38 insertions, 28 deletions
diff --git a/sysdeps/mach/hurd/setitimer.c b/sysdeps/mach/hurd/setitimer.c index 4f494a4c6e..cba1d0e65a 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 <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 = + { + __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) |