thr_sigwait.c revision 127102
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.
1422315Sjulian * 3. All advertising materials mentioning features or use of this software
1522315Sjulian *    must display the following acknowledgement:
1622315Sjulian *	This product includes software developed by John Birrell.
1722315Sjulian * 4. Neither the name of the author nor the names of any co-contributors
1822315Sjulian *    may be used to endorse or promote products derived from this software
1922315Sjulian *    without specific prior written permission.
2022315Sjulian *
2122315Sjulian * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
2222315Sjulian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2322315Sjulian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2449439Sdeischen * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2522315Sjulian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2622315Sjulian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2722315Sjulian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2822315Sjulian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2922315Sjulian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3022315Sjulian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3122315Sjulian * SUCH DAMAGE.
3222315Sjulian *
3350476Speter * $FreeBSD: head/lib/libkse/thread/thr_sigwait.c 127102 2004-03-17 02:12:19Z davidxu $
3422315Sjulian */
3522315Sjulian#include <signal.h>
3651816Smarcel#include <sys/param.h>
3751816Smarcel#include <sys/signalvar.h>
3822315Sjulian#include <errno.h>
3922315Sjulian#include <pthread.h>
40103388Smini#include "thr_private.h"
4122315Sjulian
42116977Sdavidxu__weak_reference(__sigwait, sigwait);
43116977Sdavidxu__weak_reference(__sigtimedwait, sigtimedwait);
44116977Sdavidxu__weak_reference(__sigwaitinfo, sigwaitinfo);
4571581Sdeischen
46116977Sdavidxustatic int
47116977Sdavidxulib_sigtimedwait(const sigset_t *set, siginfo_t *info,
48116977Sdavidxu	const struct timespec * timeout)
4922315Sjulian{
50113658Sdeischen	struct pthread	*curthread = _get_curthread();
51113658Sdeischen	int		ret = 0;
52113658Sdeischen	int		i;
53118075Sdavidxu	struct sigwait_data waitdata;
54117706Sdavidxu	sigset_t	waitset;
55114254Sdeischen	kse_critical_t  crit;
56116977Sdavidxu	siginfo_t	siginfo;
57114254Sdeischen
58119063Sdavidxu	if (curthread->attr.flags & PTHREAD_SCOPE_SYSTEM) {
59116977Sdavidxu		if (info == NULL)
60116977Sdavidxu			info = &siginfo;
61117706Sdavidxu		return (__sys_sigtimedwait((sigset_t *)set, info,
62117706Sdavidxu			(struct timespec *)timeout));
63116977Sdavidxu	}
6422315Sjulian
6538539Sjb	/*
66113658Sdeischen	 * Initialize the set of signals that will be waited on:
67113658Sdeischen	 */
68113658Sdeischen	waitset = *set;
69113658Sdeischen
70113658Sdeischen	/* These signals can't be waited on. */
71116977Sdavidxu	SIGDELSET(waitset, SIGKILL);
72116977Sdavidxu	SIGDELSET(waitset, SIGSTOP);
73113658Sdeischen
74113658Sdeischen	/*
75117706Sdavidxu	 * POSIX says that the _application_ must explicitly install
76117706Sdavidxu	 * a dummy handler for signals that are SIG_IGN in order
77117706Sdavidxu	 * to sigwait on them. Note that SIG_IGN signals are left in
78117706Sdavidxu	 * the mask because a subsequent sigaction could enable an
79113658Sdeischen	 * ignored signal.
80113658Sdeischen	 */
81117706Sdavidxu
82117706Sdavidxu	crit = _kse_critical_enter();
83117706Sdavidxu	KSE_SCHED_LOCK(curthread->kse, curthread->kseg);
84117706Sdavidxu	for (i = 1; i <= _SIG_MAXSIG; ++i) {
85116977Sdavidxu		if (SIGISMEMBER(waitset, i) &&
86117706Sdavidxu		    SIGISMEMBER(curthread->sigpend, i)) {
87117706Sdavidxu			SIGDELSET(curthread->sigpend, i);
88117706Sdavidxu			siginfo = curthread->siginfo[i - 1];
89117706Sdavidxu			KSE_SCHED_UNLOCK(curthread->kse,
90117706Sdavidxu				curthread->kseg);
91117706Sdavidxu			_kse_critical_leave(crit);
92117706Sdavidxu			ret = i;
93117706Sdavidxu			goto OUT;
94113658Sdeischen		}
95113658Sdeischen	}
96117706Sdavidxu	curthread->timeout = 0;
97117706Sdavidxu	curthread->interrupted = 0;
98117706Sdavidxu	_thr_set_timeout(timeout);
99117706Sdavidxu	/* Wait for a signal: */
100117706Sdavidxu	siginfo.si_signo = 0;
101118075Sdavidxu	waitdata.waitset = &waitset;
102118075Sdavidxu	waitdata.siginfo = &siginfo;
103118075Sdavidxu	curthread->data.sigwait = &waitdata;
104117706Sdavidxu	THR_SET_STATE(curthread, PS_SIGWAIT);
105117706Sdavidxu	_thr_sched_switch_unlocked(curthread);
106117706Sdavidxu	/*
107117706Sdavidxu	 * Return the signal number to the caller:
108117706Sdavidxu	 */
109117706Sdavidxu	if (siginfo.si_signo > 0) {
110117706Sdavidxu		ret = siginfo.si_signo;
111117706Sdavidxu	} else {
112117706Sdavidxu		if (curthread->interrupted)
113117706Sdavidxu			errno = EINTR;
114117706Sdavidxu		else if (curthread->timeout)
115117706Sdavidxu			errno = EAGAIN;
116117706Sdavidxu		ret = -1;
117113658Sdeischen	}
118117706Sdavidxu	curthread->timeout = 0;
119117706Sdavidxu	curthread->interrupted = 0;
120117706Sdavidxu	/*
121117706Sdavidxu	 * Probably unnecessary, but since it's in a union struct
122117706Sdavidxu	 * we don't know how it could be used in the future.
123117706Sdavidxu	 */
124118075Sdavidxu	curthread->data.sigwait = NULL;
125113658Sdeischen
126117216SdavidxuOUT:
127117216Sdavidxu	if (ret > 0 && info != NULL)
128117216Sdavidxu		*info = siginfo;
129117216Sdavidxu
130116977Sdavidxu	return (ret);
131116977Sdavidxu}
132116977Sdavidxu
133116977Sdavidxuint
134116977Sdavidxu__sigtimedwait(const sigset_t *set, siginfo_t *info,
135116977Sdavidxu	const struct timespec * timeout)
136116977Sdavidxu{
137116977Sdavidxu	struct pthread	*curthread = _get_curthread();
138116977Sdavidxu	int ret;
139116977Sdavidxu
140123312Sdavidxu	_thr_cancel_enter(curthread);
141116977Sdavidxu	ret = lib_sigtimedwait(set, info, timeout);
142123312Sdavidxu	_thr_cancel_leave(curthread, 1);
143116977Sdavidxu	return (ret);
144116977Sdavidxu}
145113658Sdeischen
146116977Sdavidxuint _sigtimedwait(const sigset_t *set, siginfo_t *info,
147116977Sdavidxu	const struct timespec * timeout)
148116977Sdavidxu{
149116977Sdavidxu	return lib_sigtimedwait(set, info, timeout);
150116977Sdavidxu}
151116977Sdavidxu
152116977Sdavidxuint
153116977Sdavidxu__sigwaitinfo(const sigset_t *set, siginfo_t *info)
154116977Sdavidxu{
155116977Sdavidxu	struct pthread	*curthread = _get_curthread();
156116977Sdavidxu	int ret;
157116977Sdavidxu
158123312Sdavidxu	_thr_cancel_enter(curthread);
159116977Sdavidxu	ret = lib_sigtimedwait(set, info, NULL);
160123312Sdavidxu	_thr_cancel_leave(curthread, 1);
161113658Sdeischen	return (ret);
16222315Sjulian}
163116977Sdavidxu
164116977Sdavidxuint
165116977Sdavidxu_sigwaitinfo(const sigset_t *set, siginfo_t *info)
166116977Sdavidxu{
167116977Sdavidxu	return lib_sigtimedwait(set, info, NULL);
168116977Sdavidxu}
169116977Sdavidxu
170116977Sdavidxuint
171116977Sdavidxu__sigwait(const sigset_t *set, int *sig)
172116977Sdavidxu{
173116977Sdavidxu	struct pthread	*curthread = _get_curthread();
174116977Sdavidxu	int ret;
175116977Sdavidxu
176123312Sdavidxu	_thr_cancel_enter(curthread);
177116977Sdavidxu	ret = lib_sigtimedwait(set, NULL, NULL);
178116977Sdavidxu	if (ret > 0) {
179116977Sdavidxu		*sig = ret;
180116977Sdavidxu		ret = 0;
181127102Sdavidxu	} else {
182127102Sdavidxu		ret = errno;
183116977Sdavidxu	}
184123312Sdavidxu	_thr_cancel_leave(curthread, 1);
185116977Sdavidxu	return (ret);
186116977Sdavidxu}
187116977Sdavidxu
188116977Sdavidxuint
189116977Sdavidxu_sigwait(const sigset_t *set, int *sig)
190116977Sdavidxu{
191116977Sdavidxu	int ret;
192116977Sdavidxu
193116977Sdavidxu	ret = lib_sigtimedwait(set, NULL, NULL);
194116977Sdavidxu	if (ret > 0) {
195116977Sdavidxu		*sig = ret;
196116977Sdavidxu		ret = 0;
197116977Sdavidxu	} else {
198127102Sdavidxu		ret = errno;
199116977Sdavidxu	}
200116977Sdavidxu	return (ret);
201116977Sdavidxu}
202116977Sdavidxu
203