diff options
Diffstat (limited to 'mit-pthreads/pthreads/sig.c')
-rw-r--r-- | mit-pthreads/pthreads/sig.c | 452 |
1 files changed, 0 insertions, 452 deletions
diff --git a/mit-pthreads/pthreads/sig.c b/mit-pthreads/pthreads/sig.c deleted file mode 100644 index 85d4465bf1c..00000000000 --- a/mit-pthreads/pthreads/sig.c +++ /dev/null @@ -1,452 +0,0 @@ -/* ==== sig.c ======================================================= - * Copyright (c) 1994 by Chris Provenzano, proven@mit.edu - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Chris Provenzano. - * 4. The name of Chris Provenzano may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED BY CHRIS PROVENZANO ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL CHRIS PROVENZANO BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * Description : All the thread signal functions. - * - * 1.32 94/06/12 proven - * -Started coding this file. - */ - -#ifndef lint -static const char rcsid[] = "$Id$"; -#endif - -#include <errno.h> -#include <pthread.h> -#include <signal.h> -#include <string.h> - -#if defined(M_UNIX) -#define signal(A,B) machdep_sys_signal((A),(B)) -#endif - -extern void sig_handler_real(); - -struct pthread * pthread_sigwait; -static sigset_t pending_signals; - -struct pthread_sigvec { - void (*vector)(); - sigset_t mask; - int flags; -} pthread_sigvec[SIGMAX]; - -/* ========================================================================== - * pthread_sig_register() - * - * Assumes the kernel is locked. - */ -int pthread_sig_register(int sig) -{ - struct pthread ** pthread_ptr, * pthread; - int ret; - - /* - * If we have a siginfo structure and the signal is synchronous then - * only deliver the signal to the current thread. - */ - - /* Check waiting threads for delivery */ - for (pthread_ptr = &pthread_sigwait; (*pthread_ptr); - pthread_ptr = &((*pthread_ptr)->next)) { - if (sigismember((*pthread_ptr)->data.sigwait, sig)) { - pthread=*pthread_ptr; - *pthread_ptr=(*pthread_ptr)->next; - - pthread_prio_queue_enq(pthread_current_prio_queue, pthread); - ret = pthread->pthread_priority; - *(int *)(pthread->ret) = sig; - pthread->state = PS_RUNNING; - - return(ret); - } - } - - /* Check current running thread */ - if (pthread_run) { - if (!sigismember(&pthread_run->sigmask, sig)) { - sigaddset(&pthread_run->sigpending, sig); - pthread_run->sigcount++; - return(0); - } - } - - /* Check any running thread */ - for (pthread = pthread_current_prio_queue->next; - pthread; pthread = pthread->next) { - if (!sigismember(&pthread->sigmask, sig)) { - sigaddset(&pthread->sigpending, sig); - pthread->sigcount++; - return(0); - } - } - - /* Check any thread */ - for (pthread = pthread_link_list; pthread; pthread = pthread->pll) { - if (!sigismember(&pthread->sigmask, sig)) { - sigaddset(&pthread->sigpending, sig); - pthread->sigcount++; - return(0); - } - } - - sigaddset(&pending_signals, sig); - return(0); -} - -/* ========================================================================== - * pthread_sig_default() - */ -void pthread_sig_default(int sig) -{ - sigset_t mask, omask; - - if (pthread_sigvec[sig].vector == SIG_DFL) { - /* Set the signal handler to default before issueing the kill */ - signal(sig, SIG_DFL); - kill(getpid(), sig); - sigemptyset(&mask); - sigaddset(&mask, sig); - machdep_sys_sigprocmask(SIG_UNBLOCK, &mask, &omask); - signal(sig, sig_handler_real); - } -} - -/* ========================================================================== - * pthread_sig_process() - * - * Assumes the kernel is locked. - */ -void pthread_sig_process() -{ - void (*vector)(); - int i, j; - - for (i = 1; i < SIGMAX; i++) { - if (sigismember(&(pthread_run->sigpending), i)) { - if (! sigismember(&(pthread_run->sigmask), i)) { - sigdelset(&(pthread_run->sigpending), i); - pthread_run->sigcount--; - - if (pthread_sigvec[i].vector == SIG_IGN) { - continue; - } - if (pthread_sigvec[i].vector == SIG_DFL) { - pthread_sig_default(i); - continue; - } - - { - sigset_t omask; - - sigemptyset(&omask); - /* Save old mask */ - for (j = 1; j < SIGMAX; j++) { - if (sigismember(&(pthread_run->sigmask), j)) { - if (sigismember(&(pthread_sigvec[i].mask), j)) - sigaddset(&(pthread_run->sigmask), j); - sigaddset(&omask, j); - } - } - /* The signal is masked while handling the signal */ - sigaddset(&(pthread_run->sigmask), i); - - /* - * Allow interrupts during a signal, - * but not a change in the vector - */ - vector = pthread_sigvec[i].vector; - if (--pthread_kernel_lock) { - PANIC(); - } - vector(i); - pthread_run->sighandled=1; /* Mark for select; Monty */ - pthread_kernel_lock++; - - memcpy(&(pthread_run->sigmask), &omask, sizeof(omask)); - } - } - } - } -} - -/* ========================================================================== - * pthread_sigmask() - * - * It is unclear wheather this call should be implemented as an atomic - * operation. The resulting mask could be wrong if in the signal - * handler the thread calls sigprocmask for any signal other than the - * signal the handler is dealing with. - */ -int pthread_sigmask(int how, const sigset_t *set, sigset_t * oset) -{ - int i; - - if (oset) { - sigemptyset(oset); - for (i = 1; i < SIGMAX; i++) { - if (sigismember(&(pthread_run->sigmask), i)) { - sigaddset(oset, i); - } - } - } - - if (set) { - switch(how) { - case SIG_BLOCK: - for (i = 1; i < SIGMAX; i++) { - if (sigismember(set, i)) { - sigaddset(&(pthread_run->sigmask), i); - } - } - break; - case SIG_UNBLOCK: - pthread_sched_prevent(); - for (i = 1; i < SIGMAX; i++) { - if (sigismember(set, i)) { - sigdelset(&(pthread_run->sigmask), i); - if (sigismember(&pending_signals, i)) { - sigaddset(&(pthread_run->sigpending), i); - sigdelset(&pending_signals, i); - pthread_run->sigcount++; - } - } - } - pthread_sched_resume(); - break; - case SIG_SETMASK: - sigfillset(&(pthread_run->sigmask)); - pthread_sched_prevent(); - for (i = 1; i < SIGMAX; i++) { - if (! sigismember(set, i)) { - sigdelset(&(pthread_run->sigmask), i); - if (sigismember(&pending_signals, i)) { - sigaddset(&(pthread_run->sigpending), i); - sigdelset(&pending_signals, i); - pthread_run->sigcount++; - } - } - } - pthread_sched_resume(); - break; - default: - SET_ERRNO(EINVAL); - return(NOTOK); - } - } - return(OK); -} - -int sigprocmask(int how, const sigset_t *set, sigset_t * oset) -{ - return(pthread_sigmask(how, set, oset)); -} - -/* ========================================================================== - * sigwait() - */ -int sigwait(const sigset_t * set, int * sig) -{ - int i; - - /* Check that sig is valid */ - *sig = 0; - - pthread_sched_prevent(); - for (i = 1; i < SIGMAX; i++) { - if (sigismember(set, i)) { - /* Check personal signals */ - if (sigismember(&(pthread_run->sigpending), i)) { - sigdelset(&(pthread_run->sigpending), i); - pthread_sched_resume(); - *sig = i; - return(OK); - } - /* Check kernel signals */ - if (sigismember(&pending_signals, i)) { - sigdelset(&pending_signals, i); - pthread_sched_resume(); - *sig = i; - return(OK); - } - } - } - - /* No pending signals, wait for one */ - pthread_run->next = pthread_sigwait; - pthread_sigwait = pthread_run; - pthread_run->data.sigwait = set; - pthread_run->ret = sig; - - SET_PF_AT_CANCEL_POINT(pthread_run); /* This is a cancel point */ - pthread_resched_resume(PS_SIGWAIT); - CLEAR_PF_AT_CANCEL_POINT(pthread_run); /* No longer at cancel point */ - - return(OK); -} - -/* ========================================================================== - * raise() - */ -int raise(int sig) -{ - return(pthread_kill(pthread_self(), sig)); -} - -/* ========================================================================== - * sigsuspend() - */ -int sigsuspend(const sigset_t * mask) -{ - int ret_sig, ret; - sigset_t nm, om; - - sigfillset(&nm); - for(ret_sig = 1; ret_sig < SIGMAX; ret_sig++) { - if (sigismember(mask, ret_sig)) { - sigdelset(&nm, ret_sig); - } - } - pthread_sigmask(SIG_BLOCK, &nm, &om); - if ((ret = sigwait(&nm, &ret_sig)) == OK) { - sigemptyset(&nm); - sigaddset(&nm, ret_sig); - pthread_kill(pthread_self(), ret_sig); - pthread_sigmask(SIG_UNBLOCK, &nm, NULL); - /* There is a race condition here, it's not worth worring about */ - pthread_sigmask(SIG_BLOCK, &nm, NULL); - SET_ERRNO(EINTR); - ret = NOTOK; - } - pthread_sigmask(SIG_SETMASK, &om, NULL); - return(ret); -} - -/* ========================================================================== - * pthread_signal() - */ -void (*pthread_signal(int sig, void (*dispatch)(int)))() -{ - void (*odispatch)(int); - - odispatch = pthread_sigvec[sig].vector; - if ((sig > 0) && (sig < SIGMAX)) { - pthread_sigvec[sig].vector = dispatch; - sigemptyset(&(pthread_sigvec[sig].mask)); - pthread_sigvec[sig].flags = 0; - } - return(odispatch); -} - -/* ========================================================================== - * pthread_sigprocmask() - */ -int pthread_sigaction(int sig, const struct sigaction * act, - struct sigaction * oact) -{ - if ((sig > 0) && (sig < SIGMAX)) { - if (oact) { - memcpy(&(oact->sa_mask), &(pthread_sigvec[sig].mask), - sizeof(sigset_t)); - oact->sa_handler = pthread_sigvec[sig].vector; - oact->sa_flags = pthread_sigvec[sig].flags; - } - if (act) { - memcpy(&(pthread_sigvec[sig].mask), &(act->sa_mask), - sizeof(sigset_t)); - pthread_sigvec[sig].vector = act->sa_handler; - pthread_sigvec[sig].flags = act->sa_flags; - } - return(OK); - } - SET_ERRNO(EINVAL); - return(NOTOK); -} - -/* - * The following here are stolen from BSD because I get mutiply defined - * symbols between sig.o and posix_sig.o in Sun's libc.a under Sunos 4.1.3. - * The problem is that sigprocmask() is defined in posix_sig.o, in the same - * module that a lot of other sigset-primitives are defined, and we have - * our definition of sigprocmask() here, but use those other primitives. - */ - -#undef sigemptyset -#undef sigfillset -#undef sigaddset -#undef sigdelset -#undef sigismember - -static const sigset_t __sigemptyset = __SIGEMPTYSET; -int sigemptyset(sigset_t *set) -{ - *set = __sigemptyset; - return (0); -} - -static const sigset_t __sigfillset = __SIGFILLSET; -int sigfillset(sigset_t * set) -{ - *set = __sigfillset; - return (0); -} - -#define _MAXIMUM_SIG NSIG - -int sigaddset(sigset_t *set, int signo) -{ - if (signo <= 0 || signo >= _MAXIMUM_SIG) { - errno = EINVAL; - return -1; - } - __SIGADDSET(set, signo); - return (0); -} - -int sigdelset(sigset_t *set, int signo) -{ - if (signo <= 0 || signo >= _MAXIMUM_SIG) { - errno = EINVAL; - return -1; - } - __SIGDELSET(set, signo); - return (0); -} - -int sigismember(const sigset_t *set, int signo) -{ - if (signo <= 0 || signo >= _MAXIMUM_SIG) { - errno = EINVAL; - return -1; - } - return(__SIGISMEMBER(set, signo)); -} - |