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