thr_sigwait.c revision 156611
1//depot/projects/kse/lib/libpthread/thread/thr_sigwait.c#1 - branch change 15154 (text+ko) 2/* 3 * Copyright (c) 1997 John Birrell <jb@cimlogic.com.au>. 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. All advertising materials mentioning features or use of this software 15 * must display the following acknowledgement: 16 * This product includes software developed by John Birrell. 17 * 4. Neither the name of the author nor the names of any co-contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * $FreeBSD: head/lib/libkse/thread/thr_sigwait.c 156611 2006-03-13 00:59:51Z deischen $ 34 */ 35#include <signal.h> 36#include <sys/param.h> 37#include <sys/signalvar.h> 38#include <errno.h> 39#include <pthread.h> 40#include "thr_private.h" 41 42LT10_COMPAT_PRIVATE(__sigwait); 43LT10_COMPAT_PRIVATE(_sigwait); 44LT10_COMPAT_DEFAULT(sigwait); 45LT10_COMPAT_PRIVATE(__sigtimedwait); 46LT10_COMPAT_PRIVATE(_sigtimedwait); 47LT10_COMPAT_DEFAULT(sigtimedwait); 48LT10_COMPAT_PRIVATE(__sigwaitinfo); 49LT10_COMPAT_PRIVATE(_sigwaitinfo); 50LT10_COMPAT_DEFAULT(sigwaitinfo); 51 52__weak_reference(__sigwait, sigwait); 53__weak_reference(__sigtimedwait, sigtimedwait); 54__weak_reference(__sigwaitinfo, sigwaitinfo); 55 56static int 57lib_sigtimedwait(const sigset_t *set, siginfo_t *info, 58 const struct timespec * timeout) 59{ 60 struct pthread *curthread = _get_curthread(); 61 int ret = 0; 62 int i; 63 struct sigwait_data waitdata; 64 sigset_t waitset; 65 kse_critical_t crit; 66 siginfo_t siginfo; 67 68 if (curthread->attr.flags & PTHREAD_SCOPE_SYSTEM) { 69 if (info == NULL) 70 info = &siginfo; 71 return (__sys_sigtimedwait((sigset_t *)set, info, 72 (struct timespec *)timeout)); 73 } 74 75 /* 76 * Initialize the set of signals that will be waited on: 77 */ 78 waitset = *set; 79 80 /* These signals can't be waited on. */ 81 SIGDELSET(waitset, SIGKILL); 82 SIGDELSET(waitset, SIGSTOP); 83 84 /* 85 * POSIX says that the _application_ must explicitly install 86 * a dummy handler for signals that are SIG_IGN in order 87 * to sigwait on them. Note that SIG_IGN signals are left in 88 * the mask because a subsequent sigaction could enable an 89 * ignored signal. 90 */ 91 92 crit = _kse_critical_enter(); 93 KSE_SCHED_LOCK(curthread->kse, curthread->kseg); 94 for (i = 1; i <= _SIG_MAXSIG; ++i) { 95 if (SIGISMEMBER(waitset, i) && 96 SIGISMEMBER(curthread->sigpend, i)) { 97 SIGDELSET(curthread->sigpend, i); 98 siginfo = curthread->siginfo[i - 1]; 99 KSE_SCHED_UNLOCK(curthread->kse, 100 curthread->kseg); 101 _kse_critical_leave(crit); 102 ret = i; 103 goto OUT; 104 } 105 } 106 curthread->timeout = 0; 107 curthread->interrupted = 0; 108 _thr_set_timeout(timeout); 109 /* Wait for a signal: */ 110 siginfo.si_signo = 0; 111 waitdata.waitset = &waitset; 112 waitdata.siginfo = &siginfo; 113 curthread->data.sigwait = &waitdata; 114 THR_SET_STATE(curthread, PS_SIGWAIT); 115 _thr_sched_switch_unlocked(curthread); 116 /* 117 * Return the signal number to the caller: 118 */ 119 if (siginfo.si_signo > 0) { 120 ret = siginfo.si_signo; 121 } else { 122 if (curthread->interrupted) 123 errno = EINTR; 124 else if (curthread->timeout) 125 errno = EAGAIN; 126 ret = -1; 127 } 128 curthread->timeout = 0; 129 curthread->interrupted = 0; 130 /* 131 * Probably unnecessary, but since it's in a union struct 132 * we don't know how it could be used in the future. 133 */ 134 curthread->data.sigwait = NULL; 135 136OUT: 137 if (ret > 0 && info != NULL) 138 *info = siginfo; 139 140 return (ret); 141} 142 143int 144__sigtimedwait(const sigset_t *set, siginfo_t *info, 145 const struct timespec * timeout) 146{ 147 struct pthread *curthread = _get_curthread(); 148 int ret; 149 150 _thr_cancel_enter(curthread); 151 ret = lib_sigtimedwait(set, info, timeout); 152 _thr_cancel_leave(curthread, 1); 153 return (ret); 154} 155 156int _sigtimedwait(const sigset_t *set, siginfo_t *info, 157 const struct timespec * timeout) 158{ 159 return lib_sigtimedwait(set, info, timeout); 160} 161 162int 163__sigwaitinfo(const sigset_t *set, siginfo_t *info) 164{ 165 struct pthread *curthread = _get_curthread(); 166 int ret; 167 168 _thr_cancel_enter(curthread); 169 ret = lib_sigtimedwait(set, info, NULL); 170 _thr_cancel_leave(curthread, 1); 171 return (ret); 172} 173 174int 175_sigwaitinfo(const sigset_t *set, siginfo_t *info) 176{ 177 return lib_sigtimedwait(set, info, NULL); 178} 179 180int 181__sigwait(const sigset_t *set, int *sig) 182{ 183 struct pthread *curthread = _get_curthread(); 184 int ret; 185 186 _thr_cancel_enter(curthread); 187 ret = lib_sigtimedwait(set, NULL, NULL); 188 if (ret > 0) { 189 *sig = ret; 190 ret = 0; 191 } else { 192 ret = errno; 193 } 194 _thr_cancel_leave(curthread, 1); 195 return (ret); 196} 197 198int 199_sigwait(const sigset_t *set, int *sig) 200{ 201 int ret; 202 203 ret = lib_sigtimedwait(set, NULL, NULL); 204 if (ret > 0) { 205 *sig = ret; 206 ret = 0; 207 } else { 208 ret = errno; 209 } 210 return (ret); 211} 212 213