thr_sigwait.c revision 118075
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 118075 2003-07-27 06:46:34Z 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 (!_kse_isthreaded() ||
59	    (curthread->attr.flags & PTHREAD_SCOPE_SYSTEM)) {
60		if (info == NULL)
61			info = &siginfo;
62		return (__sys_sigtimedwait((sigset_t *)set, info,
63			(struct timespec *)timeout));
64	}
65
66	/*
67	 * Initialize the set of signals that will be waited on:
68	 */
69	waitset = *set;
70
71	/* These signals can't be waited on. */
72	SIGDELSET(waitset, SIGKILL);
73	SIGDELSET(waitset, SIGSTOP);
74
75	/*
76	 * POSIX says that the _application_ must explicitly install
77	 * a dummy handler for signals that are SIG_IGN in order
78	 * to sigwait on them. Note that SIG_IGN signals are left in
79	 * the mask because a subsequent sigaction could enable an
80	 * ignored signal.
81	 */
82
83	crit = _kse_critical_enter();
84	KSE_SCHED_LOCK(curthread->kse, curthread->kseg);
85	for (i = 1; i <= _SIG_MAXSIG; ++i) {
86		if (SIGISMEMBER(waitset, i) &&
87		    SIGISMEMBER(curthread->sigpend, i)) {
88			SIGDELSET(curthread->sigpend, i);
89			siginfo = curthread->siginfo[i - 1];
90			KSE_SCHED_UNLOCK(curthread->kse,
91				curthread->kseg);
92			_kse_critical_leave(crit);
93			ret = i;
94			goto OUT;
95		}
96	}
97	curthread->timeout = 0;
98	curthread->interrupted = 0;
99	_thr_set_timeout(timeout);
100	/* Wait for a signal: */
101	siginfo.si_signo = 0;
102	waitdata.waitset = &waitset;
103	waitdata.siginfo = &siginfo;
104	curthread->data.sigwait = &waitdata;
105	THR_SET_STATE(curthread, PS_SIGWAIT);
106	_thr_sched_switch_unlocked(curthread);
107	/*
108	 * Return the signal number to the caller:
109	 */
110	if (siginfo.si_signo > 0) {
111		ret = siginfo.si_signo;
112	} else {
113		if (curthread->interrupted)
114			errno = EINTR;
115		else if (curthread->timeout)
116			errno = EAGAIN;
117		ret = -1;
118	}
119	curthread->timeout = 0;
120	curthread->interrupted = 0;
121	/*
122	 * Probably unnecessary, but since it's in a union struct
123	 * we don't know how it could be used in the future.
124	 */
125	curthread->data.sigwait = NULL;
126
127OUT:
128	if (ret > 0 && info != NULL)
129		*info = siginfo;
130
131	return (ret);
132}
133
134int
135__sigtimedwait(const sigset_t *set, siginfo_t *info,
136	const struct timespec * timeout)
137{
138	struct pthread	*curthread = _get_curthread();
139	int ret;
140
141	_thr_enter_cancellation_point(curthread);
142	ret = lib_sigtimedwait(set, info, timeout);
143	_thr_leave_cancellation_point(curthread);
144	return (ret);
145}
146
147int _sigtimedwait(const sigset_t *set, siginfo_t *info,
148	const struct timespec * timeout)
149{
150	return lib_sigtimedwait(set, info, timeout);
151}
152
153int
154__sigwaitinfo(const sigset_t *set, siginfo_t *info)
155{
156	struct pthread	*curthread = _get_curthread();
157	int ret;
158
159	_thr_enter_cancellation_point(curthread);
160	ret = lib_sigtimedwait(set, info, NULL);
161	_thr_leave_cancellation_point(curthread);
162	return (ret);
163}
164
165int
166_sigwaitinfo(const sigset_t *set, siginfo_t *info)
167{
168	return lib_sigtimedwait(set, info, NULL);
169}
170
171int
172__sigwait(const sigset_t *set, int *sig)
173{
174	struct pthread	*curthread = _get_curthread();
175	int ret;
176
177	_thr_enter_cancellation_point(curthread);
178	ret = lib_sigtimedwait(set, NULL, NULL);
179	if (ret > 0) {
180		*sig = ret;
181		ret = 0;
182	}
183	else
184		ret = -1;
185	_thr_leave_cancellation_point(curthread);
186	return (ret);
187}
188
189int
190_sigwait(const sigset_t *set, int *sig)
191{
192	int ret;
193
194	ret = lib_sigtimedwait(set, NULL, NULL);
195	if (ret > 0) {
196		*sig = ret;
197		ret = 0;
198	} else {
199		ret = -1;
200	}
201	return (ret);
202}
203
204