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