thr_sigwait.c revision 117216
1103419Smini//depot/projects/kse/lib/libpthread/thread/thr_sigwait.c#1 - branch change 15154 (text+ko) 222315Sjulian/* 322315Sjulian * Copyright (c) 1997 John Birrell <jb@cimlogic.com.au>. 422315Sjulian * All rights reserved. 522315Sjulian * 622315Sjulian * Redistribution and use in source and binary forms, with or without 722315Sjulian * modification, are permitted provided that the following conditions 822315Sjulian * are met: 922315Sjulian * 1. Redistributions of source code must retain the above copyright 1022315Sjulian * notice, this list of conditions and the following disclaimer. 1122315Sjulian * 2. Redistributions in binary form must reproduce the above copyright 1222315Sjulian * notice, this list of conditions and the following disclaimer in the 1322315Sjulian * documentation and/or other materials provided with the distribution. 1422315Sjulian * 3. All advertising materials mentioning features or use of this software 1522315Sjulian * must display the following acknowledgement: 1622315Sjulian * This product includes software developed by John Birrell. 1722315Sjulian * 4. Neither the name of the author nor the names of any co-contributors 1822315Sjulian * may be used to endorse or promote products derived from this software 1922315Sjulian * without specific prior written permission. 2022315Sjulian * 2122315Sjulian * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND 2222315Sjulian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2322315Sjulian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2449439Sdeischen * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2522315Sjulian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2622315Sjulian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2722315Sjulian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2822315Sjulian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2922315Sjulian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3022315Sjulian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3122315Sjulian * SUCH DAMAGE. 3222315Sjulian * 3350476Speter * $FreeBSD: head/lib/libkse/thread/thr_sigwait.c 117216 2003-07-04 07:49:06Z davidxu $ 3422315Sjulian */ 3522315Sjulian#include <signal.h> 3651816Smarcel#include <sys/param.h> 3751816Smarcel#include <sys/signalvar.h> 3822315Sjulian#include <errno.h> 3922315Sjulian#include <pthread.h> 40103388Smini#include "thr_private.h" 4122315Sjulian 42116977Sdavidxu__weak_reference(__sigwait, sigwait); 43116977Sdavidxu__weak_reference(__sigtimedwait, sigtimedwait); 44116977Sdavidxu__weak_reference(__sigwaitinfo, sigwaitinfo); 4571581Sdeischen 46116977Sdavidxustatic int 47116977Sdavidxulib_sigtimedwait(const sigset_t *set, siginfo_t *info, 48116977Sdavidxu const struct timespec * timeout) 4922315Sjulian{ 50113658Sdeischen struct pthread *curthread = _get_curthread(); 51113658Sdeischen int ret = 0; 52113658Sdeischen int i; 53113658Sdeischen sigset_t tempset, waitset; 54113658Sdeischen struct sigaction act; 55114254Sdeischen kse_critical_t crit; 56116977Sdavidxu siginfo_t siginfo; 57114254Sdeischen 58116977Sdavidxu if (!_kse_isthreaded()) { 59116977Sdavidxu if (info == NULL) 60116977Sdavidxu info = &siginfo; 61116977Sdavidxu return __sys_sigtimedwait((sigset_t *)set, info, 62116977Sdavidxu (struct timespec *)timeout); 63116977Sdavidxu } 6422315Sjulian 6538539Sjb /* 66113658Sdeischen * Specify the thread kernel signal handler. 6738539Sjb */ 68113658Sdeischen act.sa_handler = (void (*) ()) _thr_sig_handler; 69113658Sdeischen act.sa_flags = SA_RESTART | SA_SIGINFO; 70113658Sdeischen /* Ensure the signal handler cannot be interrupted by other signals: */ 71116977Sdavidxu SIGFILLSET(act.sa_mask); 72113658Sdeischen 73113658Sdeischen /* 74113658Sdeischen * Initialize the set of signals that will be waited on: 75113658Sdeischen */ 76113658Sdeischen waitset = *set; 77113658Sdeischen 78113658Sdeischen /* These signals can't be waited on. */ 79116977Sdavidxu SIGDELSET(waitset, SIGKILL); 80116977Sdavidxu SIGDELSET(waitset, SIGSTOP); 81113658Sdeischen 82114254Sdeischen crit = _kse_critical_enter(); 83114254Sdeischen KSE_LOCK_ACQUIRE(curthread->kse, &_thread_signal_lock); 84113658Sdeischen 85113658Sdeischen /* 86116977Sdavidxu * Enter a loop to find the signals that are SIG_DFL. For 87113658Sdeischen * these signals we must install a dummy signal handler in 88113658Sdeischen * order for the kernel to pass them in to us. POSIX says 89113658Sdeischen * that the _application_ must explicitly install a dummy 90113658Sdeischen * handler for signals that are SIG_IGN in order to sigwait 91113658Sdeischen * on them. Note that SIG_IGN signals are left in the 92113658Sdeischen * mask because a subsequent sigaction could enable an 93113658Sdeischen * ignored signal. 94113658Sdeischen */ 95116977Sdavidxu SIGEMPTYSET(tempset); 96116977Sdavidxu for (i = 1; i <= _SIG_MAXSIG; i++) { 97116977Sdavidxu if (SIGISMEMBER(waitset, i) && 98113658Sdeischen (_thread_sigact[i - 1].sa_handler == SIG_DFL)) { 99116977Sdavidxu _thread_dfl_count[i - 1]++; 100116977Sdavidxu SIGADDSET(tempset, i); 101116977Sdavidxu if (_thread_dfl_count[i - 1] == 1) { 102113658Sdeischen if (__sys_sigaction(i, &act, NULL) != 0) 103116977Sdavidxu /* ret = -1 */; 104113658Sdeischen } 105113658Sdeischen } 106113658Sdeischen } 107116977Sdavidxu 108113658Sdeischen if (ret == 0) { 109116977Sdavidxu /* Done accessing _thread_dfl_count for now. */ 110116977Sdavidxu KSE_LOCK_RELEASE(curthread->kse, &_thread_signal_lock); 111116977Sdavidxu KSE_SCHED_LOCK(curthread->kse, curthread->kseg); 112116977Sdavidxu for (i = 1; i <= _SIG_MAXSIG; ++i) { 113116977Sdavidxu if (SIGISMEMBER(waitset, i) && 114116977Sdavidxu SIGISMEMBER(curthread->sigpend, i)) { 115116977Sdavidxu SIGDELSET(curthread->sigpend, i); 116117216Sdavidxu siginfo = curthread->siginfo[i - 1]; 117116977Sdavidxu KSE_SCHED_UNLOCK(curthread->kse, 118116977Sdavidxu curthread->kseg); 119116977Sdavidxu _kse_critical_leave(crit); 120117216Sdavidxu ret = i; 121117216Sdavidxu goto OUT; 122116977Sdavidxu } 123116977Sdavidxu } 124116977Sdavidxu curthread->timeout = 0; 125116977Sdavidxu _thr_set_timeout(timeout); 126113658Sdeischen /* Wait for a signal: */ 127116977Sdavidxu curthread->oldsigmask = curthread->sigmask; 128116977Sdavidxu siginfo.si_signo = 0; 129116977Sdavidxu curthread->data.sigwaitinfo = &siginfo; 130116977Sdavidxu SIGFILLSET(curthread->sigmask); 131116977Sdavidxu SIGSETNAND(curthread->sigmask, waitset); 132113658Sdeischen THR_SET_STATE(curthread, PS_SIGWAIT); 133115080Sdeischen _thr_sched_switch_unlocked(curthread); 134116977Sdavidxu /* 135116977Sdavidxu * Return the signal number to the caller: 136116977Sdavidxu * XXX Here is race, how about a signal come in before 137116977Sdavidxu * we reach here? so we might got an incorrect timeout 138116977Sdavidxu * status. 139116977Sdavidxu */ 140116977Sdavidxu if (siginfo.si_signo > 0) { 141116977Sdavidxu ret = siginfo.si_signo; 142116977Sdavidxu } else { 143116977Sdavidxu if (curthread->timeout) 144116977Sdavidxu errno = EAGAIN; 145116977Sdavidxu ret = -1; 146116977Sdavidxu } 147113658Sdeischen 148113658Sdeischen /* 149113658Sdeischen * Probably unnecessary, but since it's in a union struct 150113658Sdeischen * we don't know how it could be used in the future. 151113658Sdeischen */ 152116977Sdavidxu crit = _kse_critical_enter(); 153116977Sdavidxu curthread->data.sigwaitinfo = NULL; 154116977Sdavidxu /* 155116977Sdavidxu * Relock the array of SIG_DFL wait counts. 156116977Sdavidxu */ 157116977Sdavidxu KSE_LOCK_ACQUIRE(curthread->kse, &_thread_signal_lock); 158113658Sdeischen } 159113658Sdeischen 160117216SdavidxuOUT: 161113658Sdeischen /* Restore the sigactions: */ 162113658Sdeischen act.sa_handler = SIG_DFL; 163116977Sdavidxu for (i = 1; i <= _SIG_MAXSIG; i++) { 164116977Sdavidxu if (SIGISMEMBER(tempset, i)) { 165116977Sdavidxu _thread_dfl_count[i - 1]--; 166113658Sdeischen if ((_thread_sigact[i - 1].sa_handler == SIG_DFL) && 167116977Sdavidxu (_thread_dfl_count[i - 1] == 0)) { 168113658Sdeischen if (__sys_sigaction(i, &act, NULL) != 0) 169116977Sdavidxu /* ret = -1 */ ; 170113658Sdeischen } 171113658Sdeischen } 172113658Sdeischen } 173113658Sdeischen /* Done accessing _thread_dfl_count. */ 174114254Sdeischen KSE_LOCK_RELEASE(curthread->kse, &_thread_signal_lock); 175114254Sdeischen _kse_critical_leave(crit); 176116977Sdavidxu 177117216Sdavidxu if (ret > 0 && info != NULL) 178117216Sdavidxu *info = siginfo; 179117216Sdavidxu 180116977Sdavidxu return (ret); 181116977Sdavidxu} 182116977Sdavidxu 183116977Sdavidxuint 184116977Sdavidxu__sigtimedwait(const sigset_t *set, siginfo_t *info, 185116977Sdavidxu const struct timespec * timeout) 186116977Sdavidxu{ 187116977Sdavidxu struct pthread *curthread = _get_curthread(); 188116977Sdavidxu int ret; 189116977Sdavidxu 190116977Sdavidxu _thr_enter_cancellation_point(curthread); 191116977Sdavidxu ret = lib_sigtimedwait(set, info, timeout); 192114254Sdeischen _thr_leave_cancellation_point(curthread); 193116977Sdavidxu return (ret); 194116977Sdavidxu} 195113658Sdeischen 196116977Sdavidxuint _sigtimedwait(const sigset_t *set, siginfo_t *info, 197116977Sdavidxu const struct timespec * timeout) 198116977Sdavidxu{ 199116977Sdavidxu return lib_sigtimedwait(set, info, timeout); 200116977Sdavidxu} 201116977Sdavidxu 202116977Sdavidxuint 203116977Sdavidxu__sigwaitinfo(const sigset_t *set, siginfo_t *info) 204116977Sdavidxu{ 205116977Sdavidxu struct pthread *curthread = _get_curthread(); 206116977Sdavidxu int ret; 207116977Sdavidxu 208116977Sdavidxu _thr_enter_cancellation_point(curthread); 209116977Sdavidxu ret = lib_sigtimedwait(set, info, NULL); 210116977Sdavidxu _thr_leave_cancellation_point(curthread); 211113658Sdeischen return (ret); 21222315Sjulian} 213116977Sdavidxu 214116977Sdavidxuint 215116977Sdavidxu_sigwaitinfo(const sigset_t *set, siginfo_t *info) 216116977Sdavidxu{ 217116977Sdavidxu return lib_sigtimedwait(set, info, NULL); 218116977Sdavidxu} 219116977Sdavidxu 220116977Sdavidxuint 221116977Sdavidxu__sigwait(const sigset_t *set, int *sig) 222116977Sdavidxu{ 223116977Sdavidxu struct pthread *curthread = _get_curthread(); 224116977Sdavidxu int ret; 225116977Sdavidxu 226116977Sdavidxu _thr_enter_cancellation_point(curthread); 227116977Sdavidxu ret = lib_sigtimedwait(set, NULL, NULL); 228116977Sdavidxu if (ret > 0) { 229116977Sdavidxu *sig = ret; 230116977Sdavidxu ret = 0; 231116977Sdavidxu } 232116977Sdavidxu else 233116977Sdavidxu ret = -1; 234116977Sdavidxu _thr_leave_cancellation_point(curthread); 235116977Sdavidxu return (ret); 236116977Sdavidxu} 237116977Sdavidxu 238116977Sdavidxuint 239116977Sdavidxu_sigwait(const sigset_t *set, int *sig) 240116977Sdavidxu{ 241116977Sdavidxu int ret; 242116977Sdavidxu 243116977Sdavidxu ret = lib_sigtimedwait(set, NULL, NULL); 244116977Sdavidxu if (ret > 0) { 245116977Sdavidxu *sig = ret; 246116977Sdavidxu ret = 0; 247116977Sdavidxu } else { 248116977Sdavidxu ret = -1; 249116977Sdavidxu } 250116977Sdavidxu return (ret); 251116977Sdavidxu} 252116977Sdavidxu 253