diff options
author | David Xu <davidxu@FreeBSD.org> | 2003-07-17 23:02:30 +0000 |
---|---|---|
committer | David Xu <davidxu@FreeBSD.org> | 2003-07-17 23:02:30 +0000 |
commit | 090b336154a0d8570ea8fad84e60e7d49aa801e7 (patch) | |
tree | 501dc66c4a1aec9b0ce29190b9613a1163a1f18a /lib/libkse/thread/thr_sigwait.c | |
parent | 3074d1b454e37e25facad76e56d2a05317f9e751 (diff) |
Notes
Diffstat (limited to 'lib/libkse/thread/thr_sigwait.c')
-rw-r--r-- | lib/libkse/thread/thr_sigwait.c | 151 |
1 files changed, 50 insertions, 101 deletions
diff --git a/lib/libkse/thread/thr_sigwait.c b/lib/libkse/thread/thr_sigwait.c index 46dac92e3c3b9..041a7e93916a4 100644 --- a/lib/libkse/thread/thr_sigwait.c +++ b/lib/libkse/thread/thr_sigwait.c @@ -50,27 +50,19 @@ lib_sigtimedwait(const sigset_t *set, siginfo_t *info, struct pthread *curthread = _get_curthread(); int ret = 0; int i; - sigset_t tempset, waitset; - struct sigaction act; + sigset_t waitset; kse_critical_t crit; siginfo_t siginfo; - if (!_kse_isthreaded()) { + if (!_kse_isthreaded() || + (curthread->attr.flags & PTHREAD_SCOPE_SYSTEM)) { if (info == NULL) info = &siginfo; - return __sys_sigtimedwait((sigset_t *)set, info, - (struct timespec *)timeout); + return (__sys_sigtimedwait((sigset_t *)set, info, + (struct timespec *)timeout)); } /* - * Specify the thread kernel signal handler. - */ - act.sa_handler = (void (*) ()) _thr_sig_handler; - act.sa_flags = SA_RESTART | SA_SIGINFO; - /* Ensure the signal handler cannot be interrupted by other signals: */ - SIGFILLSET(act.sa_mask); - - /* * Initialize the set of signals that will be waited on: */ waitset = *set; @@ -79,103 +71,60 @@ lib_sigtimedwait(const sigset_t *set, siginfo_t *info, SIGDELSET(waitset, SIGKILL); SIGDELSET(waitset, SIGSTOP); - crit = _kse_critical_enter(); - KSE_LOCK_ACQUIRE(curthread->kse, &_thread_signal_lock); - /* - * Enter a loop to find the signals that are SIG_DFL. For - * these signals we must install a dummy signal handler in - * order for the kernel to pass them in to us. POSIX says - * that the _application_ must explicitly install a dummy - * handler for signals that are SIG_IGN in order to sigwait - * on them. Note that SIG_IGN signals are left in the - * mask because a subsequent sigaction could enable an + * POSIX says that the _application_ must explicitly install + * a dummy handler for signals that are SIG_IGN in order + * to sigwait on them. Note that SIG_IGN signals are left in + * the mask because a subsequent sigaction could enable an * ignored signal. */ - SIGEMPTYSET(tempset); - for (i = 1; i <= _SIG_MAXSIG; i++) { + + crit = _kse_critical_enter(); + KSE_SCHED_LOCK(curthread->kse, curthread->kseg); + for (i = 1; i <= _SIG_MAXSIG; ++i) { if (SIGISMEMBER(waitset, i) && - (_thread_sigact[i - 1].sa_handler == SIG_DFL)) { - _thread_dfl_count[i - 1]++; - SIGADDSET(tempset, i); - if (_thread_dfl_count[i - 1] == 1) { - if (__sys_sigaction(i, &act, NULL) != 0) - /* ret = -1 */; - } + SIGISMEMBER(curthread->sigpend, i)) { + SIGDELSET(curthread->sigpend, i); + siginfo = curthread->siginfo[i - 1]; + KSE_SCHED_UNLOCK(curthread->kse, + curthread->kseg); + _kse_critical_leave(crit); + ret = i; + goto OUT; } } - - if (ret == 0) { - /* Done accessing _thread_dfl_count for now. */ - KSE_LOCK_RELEASE(curthread->kse, &_thread_signal_lock); - KSE_SCHED_LOCK(curthread->kse, curthread->kseg); - for (i = 1; i <= _SIG_MAXSIG; ++i) { - if (SIGISMEMBER(waitset, i) && - SIGISMEMBER(curthread->sigpend, i)) { - SIGDELSET(curthread->sigpend, i); - siginfo = curthread->siginfo[i - 1]; - KSE_SCHED_UNLOCK(curthread->kse, - curthread->kseg); - KSE_LOCK_ACQUIRE(curthread->kse, - &_thread_signal_lock); - ret = i; - goto OUT; - } - } - curthread->timeout = 0; - curthread->interrupted = 0; - _thr_set_timeout(timeout); - /* Wait for a signal: */ - curthread->oldsigmask = curthread->sigmask; - siginfo.si_signo = 0; - curthread->data.sigwaitinfo = &siginfo; - SIGFILLSET(curthread->sigmask); - SIGSETNAND(curthread->sigmask, waitset); - THR_SET_STATE(curthread, PS_SIGWAIT); - _thr_sched_switch_unlocked(curthread); - /* - * Return the signal number to the caller: - */ - if (siginfo.si_signo > 0) { - ret = siginfo.si_signo; - } else { - if (curthread->interrupted) - errno = EINTR; - else if (curthread->timeout) - errno = EAGAIN; - ret = -1; - } - curthread->timeout = 0; - curthread->interrupted = 0; - /* - * Probably unnecessary, but since it's in a union struct - * we don't know how it could be used in the future. - */ - crit = _kse_critical_enter(); - curthread->data.sigwaitinfo = NULL; - /* - * Relock the array of SIG_DFL wait counts. - */ - KSE_LOCK_ACQUIRE(curthread->kse, &_thread_signal_lock); + curthread->timeout = 0; + curthread->interrupted = 0; + _thr_set_timeout(timeout); + /* Wait for a signal: */ + curthread->oldsigmask = curthread->sigmask; + siginfo.si_signo = 0; + curthread->data.sigwaitinfo = &siginfo; + SIGFILLSET(curthread->sigmask); + SIGSETNAND(curthread->sigmask, waitset); + THR_SET_STATE(curthread, PS_SIGWAIT); + _thr_sched_switch_unlocked(curthread); + /* + * Return the signal number to the caller: + */ + if (siginfo.si_signo > 0) { + ret = siginfo.si_signo; + } else { + if (curthread->interrupted) + errno = EINTR; + else if (curthread->timeout) + errno = EAGAIN; + ret = -1; } + curthread->timeout = 0; + curthread->interrupted = 0; + /* + * Probably unnecessary, but since it's in a union struct + * we don't know how it could be used in the future. + */ + curthread->data.sigwaitinfo = NULL; OUT: - /* Restore the sigactions: */ - act.sa_handler = SIG_DFL; - for (i = 1; i <= _SIG_MAXSIG; i++) { - if (SIGISMEMBER(tempset, i)) { - _thread_dfl_count[i - 1]--; - if ((_thread_sigact[i - 1].sa_handler == SIG_DFL) && - (_thread_dfl_count[i - 1] == 0)) { - if (__sys_sigaction(i, &act, NULL) != 0) - /* ret = -1 */ ; - } - } - } - /* Done accessing _thread_dfl_count. */ - KSE_LOCK_RELEASE(curthread->kse, &_thread_signal_lock); - _kse_critical_leave(crit); - if (ret > 0 && info != NULL) *info = siginfo; |