thr_sigwait.c revision 123312
1271294Sngie//depot/projects/kse/lib/libpthread/thread/thr_sigwait.c#1 - branch change 15154 (text+ko) 2271294Sngie/* 3271294Sngie * Copyright (c) 1997 John Birrell <jb@cimlogic.com.au>. 4271294Sngie * All rights reserved. 5271294Sngie * 6271294Sngie * Redistribution and use in source and binary forms, with or without 7271294Sngie * modification, are permitted provided that the following conditions 8271294Sngie * are met: 9271294Sngie * 1. Redistributions of source code must retain the above copyright 10271294Sngie * notice, this list of conditions and the following disclaimer. 11271294Sngie * 2. Redistributions in binary form must reproduce the above copyright 12271294Sngie * notice, this list of conditions and the following disclaimer in the 13271294Sngie * documentation and/or other materials provided with the distribution. 14271294Sngie * 3. All advertising materials mentioning features or use of this software 15271294Sngie * must display the following acknowledgement: 16271294Sngie * This product includes software developed by John Birrell. 17271294Sngie * 4. Neither the name of the author nor the names of any co-contributors 18271294Sngie * may be used to endorse or promote products derived from this software 19271294Sngie * without specific prior written permission. 20271294Sngie * 21271294Sngie * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND 22271294Sngie * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23271294Sngie * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24271294Sngie * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 25271294Sngie * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26271294Sngie * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27271294Sngie * 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 123312 2003-12-09 02:20:56Z davidxu $ 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 42__weak_reference(__sigwait, sigwait); 43__weak_reference(__sigtimedwait, sigtimedwait); 44__weak_reference(__sigwaitinfo, sigwaitinfo); 45 46static int 47lib_sigtimedwait(const sigset_t *set, siginfo_t *info, 48 const struct timespec * timeout) 49{ 50 struct pthread *curthread = _get_curthread(); 51 int ret = 0; 52 int i; 53 struct sigwait_data waitdata; 54 sigset_t waitset; 55 kse_critical_t crit; 56 siginfo_t siginfo; 57 58 if (curthread->attr.flags & PTHREAD_SCOPE_SYSTEM) { 59 if (info == NULL) 60 info = &siginfo; 61 return (__sys_sigtimedwait((sigset_t *)set, info, 62 (struct timespec *)timeout)); 63 } 64 65 /* 66 * Initialize the set of signals that will be waited on: 67 */ 68 waitset = *set; 69 70 /* These signals can't be waited on. */ 71 SIGDELSET(waitset, SIGKILL); 72 SIGDELSET(waitset, SIGSTOP); 73 74 /* 75 * POSIX says that the _application_ must explicitly install 76 * a dummy handler for signals that are SIG_IGN in order 77 * to sigwait on them. Note that SIG_IGN signals are left in 78 * the mask because a subsequent sigaction could enable an 79 * ignored signal. 80 */ 81 82 crit = _kse_critical_enter(); 83 KSE_SCHED_LOCK(curthread->kse, curthread->kseg); 84 for (i = 1; i <= _SIG_MAXSIG; ++i) { 85 if (SIGISMEMBER(waitset, i) && 86 SIGISMEMBER(curthread->sigpend, i)) { 87 SIGDELSET(curthread->sigpend, i); 88 siginfo = curthread->siginfo[i - 1]; 89 KSE_SCHED_UNLOCK(curthread->kse, 90 curthread->kseg); 91 _kse_critical_leave(crit); 92 ret = i; 93 goto OUT; 94 } 95 } 96 curthread->timeout = 0; 97 curthread->interrupted = 0; 98 _thr_set_timeout(timeout); 99 /* Wait for a signal: */ 100 siginfo.si_signo = 0; 101 waitdata.waitset = &waitset; 102 waitdata.siginfo = &siginfo; 103 curthread->data.sigwait = &waitdata; 104 THR_SET_STATE(curthread, PS_SIGWAIT); 105 _thr_sched_switch_unlocked(curthread); 106 /* 107 * Return the signal number to the caller: 108 */ 109 if (siginfo.si_signo > 0) { 110 ret = siginfo.si_signo; 111 } else { 112 if (curthread->interrupted) 113 errno = EINTR; 114 else if (curthread->timeout) 115 errno = EAGAIN; 116 ret = -1; 117 } 118 curthread->timeout = 0; 119 curthread->interrupted = 0; 120 /* 121 * Probably unnecessary, but since it's in a union struct 122 * we don't know how it could be used in the future. 123 */ 124 curthread->data.sigwait = NULL; 125 126OUT: 127 if (ret > 0 && info != NULL) 128 *info = siginfo; 129 130 return (ret); 131} 132 133int 134__sigtimedwait(const sigset_t *set, siginfo_t *info, 135 const struct timespec * timeout) 136{ 137 struct pthread *curthread = _get_curthread(); 138 int ret; 139 140 _thr_cancel_enter(curthread); 141 ret = lib_sigtimedwait(set, info, timeout); 142 _thr_cancel_leave(curthread, 1); 143 return (ret); 144} 145 146int _sigtimedwait(const sigset_t *set, siginfo_t *info, 147 const struct timespec * timeout) 148{ 149 return lib_sigtimedwait(set, info, timeout); 150} 151 152int 153__sigwaitinfo(const sigset_t *set, siginfo_t *info) 154{ 155 struct pthread *curthread = _get_curthread(); 156 int ret; 157 158 _thr_cancel_enter(curthread); 159 ret = lib_sigtimedwait(set, info, NULL); 160 _thr_cancel_leave(curthread, 1); 161 return (ret); 162} 163 164int 165_sigwaitinfo(const sigset_t *set, siginfo_t *info) 166{ 167 return lib_sigtimedwait(set, info, NULL); 168} 169 170int 171__sigwait(const sigset_t *set, int *sig) 172{ 173 struct pthread *curthread = _get_curthread(); 174 int ret; 175 176 _thr_cancel_enter(curthread); 177 ret = lib_sigtimedwait(set, NULL, NULL); 178 if (ret > 0) { 179 *sig = ret; 180 ret = 0; 181 } 182 else 183 ret = -1; 184 _thr_cancel_leave(curthread, 1); 185 return (ret); 186} 187 188int 189_sigwait(const sigset_t *set, int *sig) 190{ 191 int ret; 192 193 ret = lib_sigtimedwait(set, NULL, NULL); 194 if (ret > 0) { 195 *sig = ret; 196 ret = 0; 197 } else { 198 ret = -1; 199 } 200 return (ret); 201} 202 203