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