1103419Smini//depot/projects/kse/lib/libpthread/thread/thr_sigwait.c#1 - branch change 15154 (text+ko)
222315Sjulian/*
322315Sjulian * Copyright (c) 1997 John Birrell <jb@cimlogic.com.au>.
422315Sjulian * All rights reserved.
522315Sjulian *
622315Sjulian * Redistribution and use in source and binary forms, with or without
722315Sjulian * modification, are permitted provided that the following conditions
822315Sjulian * are met:
922315Sjulian * 1. Redistributions of source code must retain the above copyright
1022315Sjulian *    notice, this list of conditions and the following disclaimer.
1122315Sjulian * 2. Redistributions in binary form must reproduce the above copyright
1222315Sjulian *    notice, this list of conditions and the following disclaimer in the
1322315Sjulian *    documentation and/or other materials provided with the distribution.
14165967Simp * 3. Neither the name of the author nor the names of any co-contributors
1522315Sjulian *    may be used to endorse or promote products derived from this software
1622315Sjulian *    without specific prior written permission.
1722315Sjulian *
1822315Sjulian * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
1922315Sjulian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2022315Sjulian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2149439Sdeischen * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2222315Sjulian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2322315Sjulian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2422315Sjulian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2522315Sjulian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2622315Sjulian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2722315Sjulian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2822315Sjulian * SUCH DAMAGE.
2922315Sjulian *
3050476Speter * $FreeBSD$
3122315Sjulian */
32174112Sdeischen
33174112Sdeischen#include "namespace.h"
3422315Sjulian#include <signal.h>
3551816Smarcel#include <sys/param.h>
3651816Smarcel#include <sys/signalvar.h>
3722315Sjulian#include <errno.h>
3822315Sjulian#include <pthread.h>
39174112Sdeischen#include "un-namespace.h"
40103388Smini#include "thr_private.h"
4122315Sjulian
42174112Sdeischenint	__sigtimedwait(const sigset_t *set, siginfo_t *info,
43174112Sdeischen	    const struct timespec *timeout);
44174112Sdeischenint	__sigwaitinfo(const sigset_t *set, siginfo_t *info);
45174112Sdeischenint	__sigwait(const sigset_t *set, int *sig);
46174112Sdeischenint	_sigtimedwait(const sigset_t *set, siginfo_t *info,
47174112Sdeischen	    const struct timespec *timeout);
48174112Sdeischenint	_sigwaitinfo(const sigset_t *set, siginfo_t *info);
49174112Sdeischenint	_sigwait(const sigset_t *set, int *sig);
50174112Sdeischen
51116977Sdavidxu__weak_reference(__sigwait, sigwait);
52116977Sdavidxu__weak_reference(__sigtimedwait, sigtimedwait);
53116977Sdavidxu__weak_reference(__sigwaitinfo, sigwaitinfo);
5471581Sdeischen
55116977Sdavidxustatic int
56116977Sdavidxulib_sigtimedwait(const sigset_t *set, siginfo_t *info,
57174112Sdeischen	const struct timespec *timeout)
5822315Sjulian{
59113658Sdeischen	struct pthread	*curthread = _get_curthread();
60113658Sdeischen	int		ret = 0;
61113658Sdeischen	int		i;
62118075Sdavidxu	struct sigwait_data waitdata;
63117706Sdavidxu	sigset_t	waitset;
64114254Sdeischen	kse_critical_t  crit;
65116977Sdavidxu	siginfo_t	siginfo;
66114254Sdeischen
67119063Sdavidxu	if (curthread->attr.flags & PTHREAD_SCOPE_SYSTEM) {
68116977Sdavidxu		if (info == NULL)
69116977Sdavidxu			info = &siginfo;
70174112Sdeischen		return (__sys_sigtimedwait(set, info, timeout));
71116977Sdavidxu	}
7222315Sjulian
7338539Sjb	/*
74113658Sdeischen	 * Initialize the set of signals that will be waited on:
75113658Sdeischen	 */
76113658Sdeischen	waitset = *set;
77113658Sdeischen
78113658Sdeischen	/* These signals can't be waited on. */
79116977Sdavidxu	SIGDELSET(waitset, SIGKILL);
80116977Sdavidxu	SIGDELSET(waitset, SIGSTOP);
81113658Sdeischen
82113658Sdeischen	/*
83117706Sdavidxu	 * POSIX says that the _application_ must explicitly install
84117706Sdavidxu	 * a dummy handler for signals that are SIG_IGN in order
85117706Sdavidxu	 * to sigwait on them. Note that SIG_IGN signals are left in
86117706Sdavidxu	 * the mask because a subsequent sigaction could enable an
87113658Sdeischen	 * ignored signal.
88113658Sdeischen	 */
89117706Sdavidxu
90117706Sdavidxu	crit = _kse_critical_enter();
91117706Sdavidxu	KSE_SCHED_LOCK(curthread->kse, curthread->kseg);
92117706Sdavidxu	for (i = 1; i <= _SIG_MAXSIG; ++i) {
93116977Sdavidxu		if (SIGISMEMBER(waitset, i) &&
94117706Sdavidxu		    SIGISMEMBER(curthread->sigpend, i)) {
95117706Sdavidxu			SIGDELSET(curthread->sigpend, i);
96117706Sdavidxu			siginfo = curthread->siginfo[i - 1];
97117706Sdavidxu			KSE_SCHED_UNLOCK(curthread->kse,
98117706Sdavidxu				curthread->kseg);
99117706Sdavidxu			_kse_critical_leave(crit);
100117706Sdavidxu			ret = i;
101117706Sdavidxu			goto OUT;
102113658Sdeischen		}
103113658Sdeischen	}
104117706Sdavidxu	curthread->timeout = 0;
105117706Sdavidxu	curthread->interrupted = 0;
106117706Sdavidxu	_thr_set_timeout(timeout);
107117706Sdavidxu	/* Wait for a signal: */
108117706Sdavidxu	siginfo.si_signo = 0;
109118075Sdavidxu	waitdata.waitset = &waitset;
110118075Sdavidxu	waitdata.siginfo = &siginfo;
111118075Sdavidxu	curthread->data.sigwait = &waitdata;
112117706Sdavidxu	THR_SET_STATE(curthread, PS_SIGWAIT);
113117706Sdavidxu	_thr_sched_switch_unlocked(curthread);
114117706Sdavidxu	/*
115117706Sdavidxu	 * Return the signal number to the caller:
116117706Sdavidxu	 */
117117706Sdavidxu	if (siginfo.si_signo > 0) {
118117706Sdavidxu		ret = siginfo.si_signo;
119117706Sdavidxu	} else {
120117706Sdavidxu		if (curthread->interrupted)
121117706Sdavidxu			errno = EINTR;
122117706Sdavidxu		else if (curthread->timeout)
123117706Sdavidxu			errno = EAGAIN;
124117706Sdavidxu		ret = -1;
125113658Sdeischen	}
126117706Sdavidxu	curthread->timeout = 0;
127117706Sdavidxu	curthread->interrupted = 0;
128117706Sdavidxu	/*
129117706Sdavidxu	 * Probably unnecessary, but since it's in a union struct
130117706Sdavidxu	 * we don't know how it could be used in the future.
131117706Sdavidxu	 */
132118075Sdavidxu	curthread->data.sigwait = NULL;
133113658Sdeischen
134117216SdavidxuOUT:
135117216Sdavidxu	if (ret > 0 && info != NULL)
136117216Sdavidxu		*info = siginfo;
137117216Sdavidxu
138116977Sdavidxu	return (ret);
139116977Sdavidxu}
140116977Sdavidxu
141116977Sdavidxuint
142116977Sdavidxu__sigtimedwait(const sigset_t *set, siginfo_t *info,
143116977Sdavidxu	const struct timespec * timeout)
144116977Sdavidxu{
145116977Sdavidxu	struct pthread	*curthread = _get_curthread();
146116977Sdavidxu	int ret;
147116977Sdavidxu
148123312Sdavidxu	_thr_cancel_enter(curthread);
149116977Sdavidxu	ret = lib_sigtimedwait(set, info, timeout);
150123312Sdavidxu	_thr_cancel_leave(curthread, 1);
151116977Sdavidxu	return (ret);
152116977Sdavidxu}
153113658Sdeischen
154116977Sdavidxuint _sigtimedwait(const sigset_t *set, siginfo_t *info,
155116977Sdavidxu	const struct timespec * timeout)
156116977Sdavidxu{
157116977Sdavidxu	return lib_sigtimedwait(set, info, timeout);
158116977Sdavidxu}
159116977Sdavidxu
160116977Sdavidxuint
161116977Sdavidxu__sigwaitinfo(const sigset_t *set, siginfo_t *info)
162116977Sdavidxu{
163116977Sdavidxu	struct pthread	*curthread = _get_curthread();
164116977Sdavidxu	int ret;
165116977Sdavidxu
166123312Sdavidxu	_thr_cancel_enter(curthread);
167116977Sdavidxu	ret = lib_sigtimedwait(set, info, NULL);
168123312Sdavidxu	_thr_cancel_leave(curthread, 1);
169113658Sdeischen	return (ret);
17022315Sjulian}
171116977Sdavidxu
172116977Sdavidxuint
173116977Sdavidxu_sigwaitinfo(const sigset_t *set, siginfo_t *info)
174116977Sdavidxu{
175116977Sdavidxu	return lib_sigtimedwait(set, info, NULL);
176116977Sdavidxu}
177116977Sdavidxu
178116977Sdavidxuint
179116977Sdavidxu__sigwait(const sigset_t *set, int *sig)
180116977Sdavidxu{
181116977Sdavidxu	struct pthread	*curthread = _get_curthread();
182116977Sdavidxu	int ret;
183116977Sdavidxu
184123312Sdavidxu	_thr_cancel_enter(curthread);
185116977Sdavidxu	ret = lib_sigtimedwait(set, NULL, NULL);
186116977Sdavidxu	if (ret > 0) {
187116977Sdavidxu		*sig = ret;
188116977Sdavidxu		ret = 0;
189127102Sdavidxu	} else {
190127102Sdavidxu		ret = errno;
191116977Sdavidxu	}
192123312Sdavidxu	_thr_cancel_leave(curthread, 1);
193116977Sdavidxu	return (ret);
194116977Sdavidxu}
195116977Sdavidxu
196116977Sdavidxuint
197116977Sdavidxu_sigwait(const sigset_t *set, int *sig)
198116977Sdavidxu{
199116977Sdavidxu	int ret;
200116977Sdavidxu
201116977Sdavidxu	ret = lib_sigtimedwait(set, NULL, NULL);
202116977Sdavidxu	if (ret > 0) {
203116977Sdavidxu		*sig = ret;
204116977Sdavidxu		ret = 0;
205116977Sdavidxu	} else {
206127102Sdavidxu		ret = errno;
207116977Sdavidxu	}
208116977Sdavidxu	return (ret);
209116977Sdavidxu}
210116977Sdavidxu
211