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