diff options
-rw-r--r-- | lib/libpthread/uthread/pthread_private.h | 15 | ||||
-rw-r--r-- | lib/libpthread/uthread/uthread_kern.c | 78 | ||||
-rw-r--r-- | lib/libpthread/uthread/uthread_kill.c | 170 | ||||
-rw-r--r-- | lib/libpthread/uthread/uthread_mutex.c | 10 | ||||
-rw-r--r-- | lib/libpthread/uthread/uthread_sig.c | 266 | ||||
-rw-r--r-- | lib/libpthread/uthread/uthread_sigmask.c | 4 | ||||
-rw-r--r-- | lib/libpthread/uthread/uthread_sigwait.c | 7 |
7 files changed, 167 insertions, 383 deletions
diff --git a/lib/libpthread/uthread/pthread_private.h b/lib/libpthread/uthread/pthread_private.h index 78d34b82804..cae2335ef0d 100644 --- a/lib/libpthread/uthread/pthread_private.h +++ b/lib/libpthread/uthread/pthread_private.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pthread_private.h,v 1.41 2003/01/24 21:03:15 marc Exp $ */ +/* $OpenBSD: pthread_private.h,v 1.42 2003/01/27 22:22:30 marc Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -624,7 +624,6 @@ struct pthread { sigset_t sigmask; sigset_t sigpend; int sigmask_seqno; - int check_pending; /* Thread state: */ enum pthread_state state; @@ -1016,14 +1015,7 @@ SCLASS volatile int _spinblock_count /* Used to maintain pending and active signals: */ struct sigstatus { int pending; /* Is this a pending signal? */ - int blocked; /* - * A handler is currently active for - * this signal; ignore subsequent - * signals until the handler is done. - */ - int signo; /* arg 1 to signal handler */ siginfo_t siginfo; /* arg 2 to signal handler */ - struct sigcontext uc; /* arg 3 to signal handler */ }; SCLASS struct sigstatus _thread_sigq[NSIG]; @@ -1095,11 +1087,11 @@ void _waitq_clearactive(void); __dead void _thread_exit(const char *, int, const char *) __attribute__((__noreturn__)); void *_thread_cleanup(pthread_t); void _thread_cleanupspecific(void); +void _thread_clear_pending(int, pthread_t); void _thread_dump_data(const void *, int); void _thread_dump_info(void); void _thread_init(void); void _thread_kern_sched(struct sigcontext *); -void _thread_kern_sched_sig(void); void _thread_kern_sched_state(enum pthread_state,char *fname,int lineno); void _thread_kern_sched_state_unlock(enum pthread_state state, spinlock_t *lock, char *fname, int lineno); @@ -1107,9 +1099,8 @@ void _thread_kern_set_timeout(const struct timespec *); void _thread_kern_sig_defer(void); void _thread_kern_sig_undefer(void); void _thread_sig_handler(int, siginfo_t *, struct sigcontext *); -void _thread_sig_handle(int, struct sigcontext *); +int _thread_sig_handle(int, struct sigcontext *); void _thread_sig_init(void); -void _thread_sig_process(int, struct sigcontext *); void _thread_start(void); void _thread_start_sig_handler(void); void _thread_seterrno(pthread_t,int); diff --git a/lib/libpthread/uthread/uthread_kern.c b/lib/libpthread/uthread/uthread_kern.c index 9930098a974..d72e7b5ed9e 100644 --- a/lib/libpthread/uthread/uthread_kern.c +++ b/lib/libpthread/uthread/uthread_kern.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uthread_kern.c,v 1.24 2003/01/24 21:03:15 marc Exp $ */ +/* $OpenBSD: uthread_kern.c,v 1.25 2003/01/27 22:22:30 marc Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -50,12 +50,6 @@ #include <pthread.h> #include "pthread_private.h" -#if defined(PTHREAD_TRACE_KERN) -#define PTHREAD_TRACE(x) _thread_sys_write(-1, (void*) x, 0) -#else -#define PTHREAD_TRACE(x) -#endif - /* * local functions. Do NOT make these static... we want so see them in * crash dumps. @@ -68,16 +62,6 @@ inline void _thread_run_switch_hook(pthread_t, pthread_t); static int last_tick = 0; void -_thread_kern_sched_sig(void) -{ - struct pthread *curthread = _get_curthread(); - - PTHREAD_TRACE(1); - curthread->check_pending = 1; - _thread_kern_sched(NULL); -} - -void _thread_kern_sched(struct sigcontext * scp) { struct timespec ts; @@ -88,8 +72,6 @@ _thread_kern_sched(struct sigcontext * scp) int add_to_prioq; pthread_t old_thread_run; - PTHREAD_TRACE(2); - /* * Flag the pthread kernel as executing scheduler code * to avoid a scheduler signal from interrupting this @@ -257,23 +239,6 @@ _thread_kern_sched(struct sigcontext * scp) PTHREAD_WORKQ_INSERT(curthread); break; } - - /* - * Are there pending signals for this thread? - * - * This check has to be performed after the thread - * has been placed in the queue(s) appropriate for - * its state. The process of adding pending signals - * can change a threads state, which in turn will - * attempt to add or remove the thread from any - * scheduling queue to which it belongs. - */ -#ifdef notyet - if (curthread->check_pending != 0) { - curthread->check_pending = 0; - _thread_sig_check_pending(curthread); - } -#endif } /* @@ -502,18 +467,10 @@ _thread_kern_sched(struct sigcontext * scp) /* Restore floating point state. */ _thread_machdep_restore_float_state(&curthread->_machdep); - /* - * Restore the new thread, saving current. - */ + /* Restore the new thread, saving current. */ _thread_machdep_switch(&curthread->_machdep, &old_thread_run->_machdep); - - /* - * Process any pending signals for the thread we - * just switched to. - */ _thread_kern_in_sched = 0; - _dispatch_signals(scp); /* run any installed switch-hooks */ if ((_sched_switch_hook != NULL) && @@ -529,6 +486,10 @@ _thread_kern_sched(struct sigcontext * scp) PTHREAD_CANCEL_ASYNCHRONOUS) != 0)) pthread_testcancel(); + /* dispatch any pending signals if possible */ + if (curthread->sig_defer_count == 0) + _dispatch_signals(scp); + /* Check if a signal context was saved: */ if (curthread->sig_saved == 1) { /* return to signal handler. This code @@ -556,7 +517,6 @@ _thread_kern_sched_state(enum pthread_state state, char *fname, int lineno) { struct pthread *curthread = _get_curthread(); - PTHREAD_TRACE(3); /* * Flag the pthread kernel as executing scheduler code * to avoid a scheduler signal from interrupting this @@ -585,8 +545,6 @@ _thread_kern_sched_state_unlock(enum pthread_state state, { struct pthread *curthread = _get_curthread(); - PTHREAD_TRACE(4); - /* * Flag the pthread kernel as executing scheduler code * to avoid a scheduler signal from interrupting this @@ -624,8 +582,6 @@ _thread_kern_poll(int wait_reqd) struct timespec ts; struct timeval tv; - PTHREAD_TRACE(5); - /* Check if the caller wants to wait: */ if (wait_reqd == 0) { timeout_ms = 0; @@ -948,8 +904,6 @@ _thread_kern_set_timeout(const struct timespec * timeout) struct timespec current_time; struct timeval tv; - PTHREAD_TRACE(6); - /* Reset the timeout flag for the running thread: */ curthread->timeout = 0; @@ -990,8 +944,6 @@ _thread_kern_sig_defer(void) { struct pthread *curthread = _get_curthread(); - PTHREAD_TRACE(7); - /* Allow signal deferral to be recursive. */ curthread->sig_defer_count++; } @@ -1001,8 +953,6 @@ _thread_kern_sig_undefer(void) { struct pthread *curthread = _get_curthread(); - PTHREAD_TRACE(8); - /* * Perform checks to yield only if we are about to undefer * signals. @@ -1049,8 +999,6 @@ _dequeue_signals(void) char bufr[128]; int i, num; - PTHREAD_TRACE(9); - /* * Enter a loop to read and handle queued signals from the * pthread kernel pipe: @@ -1062,16 +1010,8 @@ _dequeue_signals(void) * each byte is the signal number. */ for (i = 0; i < num; i++) { - if ((int) bufr[i] == _SCHED_SIGNAL) { - /* - * Scheduling signals shouldn't ever be - * queued; just ignore it for now. - */ - } - else { - /* Handle this signal: */ - _thread_sig_process((int) bufr[i], NULL); - } + if ((int) bufr[i] != _SCHED_SIGNAL) + _thread_sig_handle((int) bufr[i], NULL); } } if ((num < 0) && (errno != EAGAIN)) { @@ -1089,8 +1029,6 @@ _thread_run_switch_hook(pthread_t thread_out, pthread_t thread_in) pthread_t tid_out = thread_out; pthread_t tid_in = thread_in; - PTHREAD_TRACE(10); - if ((tid_out != NULL) && (tid_out->flags & PTHREAD_FLAGS_PRIVATE) != 0) tid_out = NULL; diff --git a/lib/libpthread/uthread/uthread_kill.c b/lib/libpthread/uthread/uthread_kill.c index 59d78b80ebf..9e94a7f0ee4 100644 --- a/lib/libpthread/uthread/uthread_kill.c +++ b/lib/libpthread/uthread/uthread_kill.c @@ -1,37 +1,6 @@ -/* $OpenBSD: uthread_kill.c,v 1.8 2002/10/30 19:11:56 marc Exp $ */ -/* - * Copyright (c) 1997 John Birrell <jb@cimlogic.com.au>. - * 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 John Birrell. - * 4. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``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 THE AUTHOR OR CONTRIBUTORS 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. - * - * $FreeBSD: uthread_kill.c,v 1.9 1999/08/28 00:03:38 peter Exp $ - */ +/* $OpenBSD: uthread_kill.c,v 1.9 2003/01/27 22:22:30 marc Exp $ */ +/* PUBLIC_DOMAIN <marc@snafu.org> */ + #include <errno.h> #include <signal.h> #ifdef _THREAD_SAFE @@ -39,132 +8,29 @@ #include "pthread_private.h" /* - * XXX THIS IS WRONG! The signal has to either come through the OS to - * get the proper siginfo, context, etc., or we need to gen up a - * siginfo (assuming needed). Signal reset and other semantics - * also need to be obeyed. + * Validate the signal number and thread. If valid process the signal. + * ;;; need to fake up a siginfo_t and put it in the queue for this signal. */ int pthread_kill(pthread_t pthread, int sig) { int ret; - /* Check for invalid signal numbers: */ - if (sig < 0 || sig >= NSIG) - /* Invalid signal: */ - ret = EINVAL; - - /* - * Ensure the thread is in the list of active threads, and the - * signal is valid (signal 0 specifies error checking only) and - * not being ignored: - */ - else if (((ret = _find_thread(pthread)) == 0) && (sig > 0) && - (_thread_sigact[sig - 1].sa_handler != SIG_IGN)) { - /* - * Defer signals to protect the scheduling queues from - * access by the signal handler: - */ - _thread_kern_sig_defer(); - - switch (pthread->state) { - case PS_SIGSUSPEND: - /* - * Only wake up the thread if the signal is unblocked - * and there is a handler installed for the signal. - */ - if (!sigismember(&pthread->sigmask, sig) && - _thread_sigact[sig - 1].sa_handler != SIG_DFL) { - /* Change the state of the thread to run: */ - PTHREAD_NEW_STATE(pthread,PS_RUNNING); - - /* Return the signal number: */ - pthread->signo = sig; - } - sigaddset(&pthread->sigpend,sig); - break; - - case PS_SIGWAIT: - /* Wake up the thread if the signal is blocked. */ - if (sigismember(pthread->data.sigwait, sig)) { - /* Change the state of the thread to run: */ - PTHREAD_NEW_STATE(pthread,PS_RUNNING); - - /* Return the signal number: */ - pthread->signo = sig; - } else - sigaddset(&pthread->sigpend,sig); - break; - - case PS_FDR_WAIT: - case PS_FDW_WAIT: - case PS_POLL_WAIT: - case PS_SLEEP_WAIT: - case PS_SELECT_WAIT: - if (!sigismember(&pthread->sigmask, sig) && - (_thread_sigact[sig - 1].sa_handler != SIG_IGN)) { - /* Flag the operation as interrupted: */ - pthread->interrupted = 1; - - if (pthread->flags & PTHREAD_FLAGS_IN_WORKQ) - PTHREAD_WORKQ_REMOVE(pthread); - - /* Change the state of the thread to run: */ - PTHREAD_NEW_STATE(pthread,PS_RUNNING); - - /* Return the signal number: */ - pthread->signo = sig; - } else { - sigaddset(&pthread->sigpend,sig); + if (sig >= 0 && sig < NSIG) { + ret = _find_thread(pthread); + if (sig != 0) { + if (_thread_sigact[sig - 1].sa_handler != SIG_IGN) { + if (pthread->state == PS_SIGWAIT && + sigismember(pthread->data.sigwait, sig)) { + PTHREAD_NEW_STATE(pthread,PS_RUNNING); + pthread->signo = sig; + } else + _thread_signal(pthread,sig); } - break; - - default: - /* Increment the pending signal count: */ - sigaddset(&pthread->sigpend,sig); - break; } + } else + ret = EINVAL; - - /* - * Check that a custom handler is installed - * and if the signal is not blocked: - */ - if (_thread_sigact[sig - 1].sa_handler != SIG_DFL && - _thread_sigact[sig - 1].sa_handler != SIG_IGN && - sigismember(&pthread->sigpend, sig) && - !sigismember(&pthread->sigmask, sig)) { - pthread_t pthread_saved = _thread_run; - - /* Current thread inside critical region? */ - if (_thread_run->sig_defer_count > 0) - pthread->sig_defer_count++; - - _thread_run = pthread; - - /* Clear the pending signal: */ - sigdelset(&pthread->sigpend, sig); - - /* - * Dispatch the signal via the custom signal - * handler: ;;; what about SA_SIGINFO??? - */ - (*(_thread_sigact[sig - 1].sa_handler))(sig); - - _thread_run = pthread_saved; - - if (_thread_run->sig_defer_count > 0) - pthread->sig_defer_count--; - } - - /* - * Undefer and handle pending signals, yielding if - * necessary: - */ - _thread_kern_sig_undefer(); - } - - /* Return the completion status: */ - return (ret); + return ret; } #endif diff --git a/lib/libpthread/uthread/uthread_mutex.c b/lib/libpthread/uthread/uthread_mutex.c index 79bd3573379..5845cf01a6b 100644 --- a/lib/libpthread/uthread/uthread_mutex.c +++ b/lib/libpthread/uthread/uthread_mutex.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uthread_mutex.c,v 1.15 2002/10/30 19:11:56 marc Exp $ */ +/* $OpenBSD: uthread_mutex.c,v 1.16 2003/01/27 22:22:30 marc Exp $ */ /* * Copyright (c) 1995 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -114,11 +114,11 @@ int pthread_mutex_init(pthread_mutex_t * mutex, const pthread_mutexattr_t * mutex_attr) { - enum pthread_mutextype type; - int protocol; - int ceiling; - int flags; pthread_mutex_t pmutex; + enum pthread_mutextype type = 0; + int protocol = 0; + int ceiling = 0; + int flags = 0; int ret = 0; if (mutex == NULL) diff --git a/lib/libpthread/uthread/uthread_sig.c b/lib/libpthread/uthread/uthread_sig.c index 17eef3fa38e..d833465bf3a 100644 --- a/lib/libpthread/uthread/uthread_sig.c +++ b/lib/libpthread/uthread/uthread_sig.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uthread_sig.c,v 1.17 2003/01/24 21:03:15 marc Exp $ */ +/* $OpenBSD: uthread_sig.c,v 1.18 2003/01/27 22:22:30 marc Exp $ */ /* * Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au> * All rights reserved. @@ -41,11 +41,6 @@ #include <pthread.h> #include "pthread_private.h" -/* Static variables: */ -static _spinlock_lock_t signal_lock = _SPINLOCK_UNLOCKED; -siginfo_t info_queue[NSIG]; -volatile sig_atomic_t pending_sigs[NSIG]; -volatile sig_atomic_t check_pending = 0; /* Initialize signal handling facility: */ void @@ -55,32 +50,8 @@ _thread_sig_init(void) /* Clear local state */ for (i = 1; i < NSIG; i++) { - pending_sigs[i - 1] = 0; + _thread_sigq[i - 1].pending = 0; } - - /* Clear the lock: */ - signal_lock = _SPINLOCK_UNLOCKED; -} - -/* - * Process a pending signal unless it is already in progress. If the - * SA_NODEFER flag is on, process it any way. - */ -void -_thread_sig_process(int sig, struct sigcontext * scp) -{ - int locked = 0; - - if (_atomic_lock(&signal_lock) == 0) - locked = 1; - - if (locked || _thread_sigact[sig - 1].sa_flags & SA_NODEFER) { - pending_sigs[sig - 1] = 0; - _thread_sig_handle(sig, scp); - } else - check_pending = 1; - if (locked) - signal_lock = _SPINLOCK_UNLOCKED; } /* @@ -93,17 +64,6 @@ _thread_sig_handler(int sig, siginfo_t *info, struct sigcontext * scp) { struct pthread *curthread = _get_curthread(); char c; - int i; - - /* - * save the info for this signal in a per signal queue of depth - * one. Per a POSIX suggestion, only the info for the first - * of multiple activations of the same signal is kept. - */ - if (pending_sigs[sig - 1] == 0) { - pending_sigs[sig - 1]++; - memcpy(&info_queue[sig - 1], info, sizeof *info); - } if (sig == _SCHED_SIGNAL) { /* Update the scheduling clock: */ @@ -138,59 +98,68 @@ _thread_sig_handler(int sig, siginfo_t *info, struct sigcontext * scp) return; } } - } else if ((_queue_signals != 0) || - ((_thread_kern_in_sched == 0) && - (curthread->sig_defer_count > 0))) { - /* - * The kernel has been interrupted while the scheduler - * is accessing the scheduling queues or there is a currently - * running thread that has deferred signals. - * - * Cast the signal number to a character variable and Write - * the signal number to the kernel pipe so that it will be - * ready to read when this signal handler returns. - */ - c = sig; - _thread_sys_write(_thread_kern_pipe[1], &c, 1); - _sigq_check_reqd = 1; } else { - /* process the signal */ - _thread_sig_process(sig, scp); /* - * process pending signals unless a current signal handler - * is running (signal_lock is locked). When locked - * the pending signals will be processed when the running - * handler returns. + * save the info for this signal in a per signal queue of depth + * one. Per a POSIX suggestion, only the info for the first + * of multiple activations of the same signal is kept. */ - while (check_pending != 0 && _atomic_lock(&signal_lock) == 0) { - check_pending = 0; - signal_lock = _SPINLOCK_UNLOCKED; - for (i = 1; i < NSIG; i++) - if (pending_sigs[i - 1]) - _thread_sig_process(i, scp); + if (_thread_sigq[sig - 1].pending == 0) { + sigaddset(&_process_sigpending, sig); + _thread_sigq[sig - 1].pending++; + memcpy(&_thread_sigq[sig - 1].siginfo, info, + sizeof *info); } - } + if ((_queue_signals != 0) || + ((_thread_kern_in_sched == 0) && + (curthread->sig_defer_count > 0))) { + /* + * The kernel has been interrupted while the scheduler + * is accessing the scheduling queues or there is a + * currently running thread that has deferred signals. + * + * Cast the signal number to a character variable + * and Write the signal number to the kernel pipe so + * that it will be ready to read when this signal + * handler returns. + */ + c = sig; + _thread_sys_write(_thread_kern_pipe[1], &c, 1); + _sigq_check_reqd = 1; + } else { + if (_thread_sig_handle(sig, scp)) + _dispatch_signals(scp); + } + } } /* * Clear the pending flag for the given signal on all threads + * if per process, or only for the given thread if non null + * and the signal doesn't exist in _process_sigpending. */ void -_clear_pending_flag(int sig) +_thread_clear_pending(int sig, pthread_t thread) { pthread_t pthread; - TAILQ_FOREACH(pthread, &_thread_list, tle) { - sigdelset(&pthread->sigpend, sig); - } + if (sigismember(&_process_sigpending, sig)) { + _thread_sigq[sig - 1].pending = 0; + sigdelset(&_process_sigpending, sig); + TAILQ_FOREACH(pthread, &_thread_list, tle) { + sigdelset(&pthread->sigpend, sig); + } + } else if (thread) + sigdelset(&thread->sigpend, sig); } /* - * Process the given signal. + * Process the given signal. Returns 1 if the signal may be dispatched, + * otherwise 0. */ -void +int _thread_sig_handle(int sig, struct sigcontext * scp) { struct pthread *curthread = _get_curthread(); @@ -216,11 +185,27 @@ _thread_sig_handle(int sig, struct sigcontext * scp) } /* - * POSIX says that pending SIGCONT signals are - * discarded when one of these signals occurs. + * If the handler is SIG_IGN the signal never happened. + * remove it from the pending list and return. + */ + if (_thread_sigact[sig - 1].sa_handler == SIG_IGN) { + _thread_clear_pending(sig, curthread); + return 0; + } + + /* + * POSIX says that pending SIGCONT signals are discarded + * when one of these signals occurs and vice versa. */ - if (sig == SIGTSTP || sig == SIGTTIN || sig == SIGTTOU) - _clear_pending_flag(SIGCONT); + if (sig == SIGSTOP || sig == SIGTSTP || sig == SIGTTIN || + sig == SIGTTOU) + _thread_clear_pending(SIGCONT, curthread); + if (sig == SIGCONT) { + _thread_clear_pending(SIGSTOP, curthread); + _thread_clear_pending(SIGTSTP, curthread); + _thread_clear_pending(SIGTTIN, curthread); + _thread_clear_pending(SIGTTOU, curthread); + } /* * Enter a loop to process each thread in the waiting @@ -239,61 +224,49 @@ _thread_sig_handle(int sig, struct sigcontext * scp) if ((pthread->state == PS_SIGWAIT) && sigismember(pthread->data.sigwait, sig)) { - /* Change the state of the thread to run: */ - PTHREAD_NEW_STATE(pthread,PS_RUNNING); - - /* Return the signal number: */ - pthread->signo = sig; - /* - * Do not attempt to deliver this signal - * to other threads. + * found a sigwaiter. Mark its state as + * running, save the signal that will be + * returned, and mark the signal as no + * longer pending. */ - return; + PTHREAD_NEW_STATE(pthread,PS_RUNNING); + pthread->signo = sig; + _thread_clear_pending(sig, pthread); + return 0; } } - if (_thread_sigact[sig - 1].sa_handler != SIG_IGN) { - /* - * mark the signal as pending for each thread - * and give the thread a chance to update - * its state. - */ - TAILQ_FOREACH(pthread, &_thread_list, tle) { - /* Current thread inside critical region? */ - if (curthread->sig_defer_count > 0) - pthread->sig_defer_count++; - _thread_signal(pthread,sig); - if (curthread->sig_defer_count > 0) - pthread->sig_defer_count--; - } - /* - * Give the current thread a chance to dispatch - * the signals. Other threads will get thier - * chance (if the signal is still pending) later. - */ - _dispatch_signals(scp); - + /* + * mark the signal as pending for each thread + * and give the thread a chance to update + * its state. + */ + TAILQ_FOREACH(pthread, &_thread_list, tle) { + /* Current thread inside critical region? */ + if (curthread->sig_defer_count > 0) + pthread->sig_defer_count++; + _thread_signal(pthread,sig); + if (curthread->sig_defer_count > 0) + pthread->sig_defer_count--; } + return 1; } + return 0; } /* Perform thread specific actions in response to a signal: */ void _thread_signal(pthread_t pthread, int sig) { - /* - * Flag the signal as pending. It may be dispatched later. - */ + /* Flag the signal as pending. It may be dispatched later. */ sigaddset(&pthread->sigpend,sig); /* skip this thread if signal is masked */ if (sigismember(&pthread->sigmask, sig)) return; - /* - * Process according to thread state: - */ + /* Process according to thread state: */ switch (pthread->state) { /* * States which do not change when a signal is trapped: @@ -377,14 +350,49 @@ _thread_signal(pthread_t pthread, int sig) } /* - * possibly dispatch a signal to the current thread. + * Dispatch a signal to the current thread after setting up the + * appropriate signal mask. */ void -_dispatch_signals(struct sigcontext * scp) +_dispatch_signal(int sig, struct sigcontext * scp) { struct pthread *curthread = _get_curthread(); + + sigset_t set; + sigset_t oset; struct sigaction act; void (*action)(int, siginfo_t *, void *); + + _thread_clear_pending(sig, curthread); + + /* save off the action and set the signal mask */ + action = _thread_sigact[sig - 1].sa_sigaction; + set = _thread_sigact[sig - 1].sa_mask; + if ((_thread_sigact[sig-1].sa_flags & SA_NODEFER) == 0) + sigaddset(&set, sig); + oset = curthread->sigmask; + curthread->sigmask |= set; + + /* clear custom handler if SA_RESETHAND set. */ + if (_thread_sigact[sig - 1].sa_flags & SA_RESETHAND) { + act.sa_handler = SIG_DFL; + act.sa_flags = 0; + sigemptyset(&act.sa_mask); + sigaction(sig, &act, NULL); + } + + /* call the action and reset the signal mask */ + (*action)(sig, &_thread_sigq[sig - 1].siginfo, scp); + curthread->sigmask = oset; +} + +/* + * possibly dispatch a signal to the current thread. + */ +void +_dispatch_signals(struct sigcontext * scp) +{ + struct pthread *curthread = _get_curthread(); int i; /* @@ -401,24 +409,8 @@ _dispatch_signals(struct sigcontext * scp) if (_thread_sigact[i - 1].sa_handler != SIG_DFL && _thread_sigact[i - 1].sa_handler != SIG_IGN && sigismember(&curthread->sigpend,i) && - !sigismember(&curthread->sigmask,i)) { - action = _thread_sigact[i - 1].sa_sigaction; - _clear_pending_flag(i); - - /* clear custom handler if SA_RESETHAND set. */ - if (_thread_sigact[i - 1].sa_flags & - SA_RESETHAND) { - act.sa_handler = SIG_DFL; - act.sa_flags = 0; - sigemptyset(&act.sa_mask); - sigaction(i, &act, NULL); - } - - /* - * Dispatch the signal via the custom signal - * handler. - */ - (*action)(i, &info_queue[i - 1], scp); - } + !sigismember(&curthread->sigmask,i)) + /* dispatch */ + _dispatch_signal(i, scp); } #endif diff --git a/lib/libpthread/uthread/uthread_sigmask.c b/lib/libpthread/uthread/uthread_sigmask.c index 12dd6ec3c69..0b2e54e0652 100644 --- a/lib/libpthread/uthread/uthread_sigmask.c +++ b/lib/libpthread/uthread/uthread_sigmask.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uthread_sigmask.c,v 1.5 2002/02/21 20:57:41 fgsch Exp $ */ +/* $OpenBSD: uthread_sigmask.c,v 1.6 2003/01/27 22:22:30 marc Exp $ */ /* * Copyright (c) 1997 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -95,7 +95,7 @@ pthread_sigmask(int how, const sigset_t *set, sigset_t *oset) * Call the kernel scheduler which will safely * install a signal frame for the running thread: */ - _thread_kern_sched_sig(); + _thread_kern_sched(NULL); } /* Return the completion status: */ diff --git a/lib/libpthread/uthread/uthread_sigwait.c b/lib/libpthread/uthread/uthread_sigwait.c index b7b72c7ea09..6e4bc5fc8a9 100644 --- a/lib/libpthread/uthread/uthread_sigwait.c +++ b/lib/libpthread/uthread/uthread_sigwait.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uthread_sigwait.c,v 1.11 2002/10/30 19:11:56 marc Exp $ */ +/* $OpenBSD: uthread_sigwait.c,v 1.12 2003/01/27 22:22:30 marc Exp $ */ /* * Copyright (c) 1997 John Birrell <jb@cimlogic.com.au>. * All rights reserved. @@ -82,10 +82,7 @@ sigwait(const sigset_t * set, int *sig) } /* Clear the pending signal: */ - if (sigismember(&curthread->sigpend, i)) - sigdelset(&curthread->sigpend, i); - else - sigdelset(&_process_sigpending, i); + _thread_clear_pending(i, curthread); /* Return the signal number to the caller: */ *sig = i; |