113546Sjulian/*
213546Sjulian * Copyright (c) 1995 John Birrell <jb@cimlogic.com.au>.
313546Sjulian * All rights reserved.
413546Sjulian *
513546Sjulian * Redistribution and use in source and binary forms, with or without
613546Sjulian * modification, are permitted provided that the following conditions
713546Sjulian * are met:
813546Sjulian * 1. Redistributions of source code must retain the above copyright
913546Sjulian *    notice, this list of conditions and the following disclaimer.
1013546Sjulian * 2. Redistributions in binary form must reproduce the above copyright
1113546Sjulian *    notice, this list of conditions and the following disclaimer in the
1213546Sjulian *    documentation and/or other materials provided with the distribution.
13165967Simp * 3. Neither the name of the author nor the names of any co-contributors
1413546Sjulian *    may be used to endorse or promote products derived from this software
1513546Sjulian *    without specific prior written permission.
1613546Sjulian *
1713546Sjulian * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
1813546Sjulian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1913546Sjulian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2049439Sdeischen * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2113546Sjulian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2213546Sjulian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2313546Sjulian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2413546Sjulian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2513546Sjulian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2613546Sjulian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2713546Sjulian * SUCH DAMAGE.
2813546Sjulian *
2950476Speter * $FreeBSD$
3013546Sjulian */
31149691Sstefanf
32174112Sdeischen#include "namespace.h"
33149691Sstefanf#include <sys/types.h>
34149691Sstefanf#include <sys/signalvar.h>
3513546Sjulian#include <errno.h>
3613546Sjulian#include <pthread.h>
37149691Sstefanf#include <signal.h>
38113658Sdeischen#include <string.h>
39174112Sdeischen#include "un-namespace.h"
40103388Smini#include "thr_private.h"
4113546Sjulian
42174112Sdeischenint	__sigsuspend(const sigset_t * set);
43174112Sdeischen
4475369Sdeischen__weak_reference(__sigsuspend, sigsuspend);
4571581Sdeischen
4613546Sjulianint
47113658Sdeischen_sigsuspend(const sigset_t *set)
48113658Sdeischen{
49113658Sdeischen	struct pthread	*curthread = _get_curthread();
50130374Sdavidxu	sigset_t	oldmask, newmask, tempset;
51113658Sdeischen	int             ret = -1;
52113658Sdeischen
53119063Sdavidxu	if (curthread->attr.flags & PTHREAD_SCOPE_SYSTEM)
54117706Sdavidxu		return (__sys_sigsuspend(set));
55116977Sdavidxu
56113658Sdeischen	/* Check if a new signal set was provided by the caller: */
57113658Sdeischen	if (set != NULL) {
58117300Sdavidxu		newmask = *set;
59117706Sdavidxu		SIG_CANTMASK(newmask);
60116514Sdavidxu		THR_LOCK_SWITCH(curthread);
61113658Sdeischen
62130374Sdavidxu		/* Save current sigmask: */
63130374Sdavidxu		oldmask = curthread->sigmask;
64130374Sdavidxu		curthread->oldsigmask = &oldmask;
65117300Sdavidxu
66113658Sdeischen		/* Change the caller's mask: */
67130374Sdavidxu		curthread->sigmask = newmask;
68130374Sdavidxu		tempset = curthread->sigpend;
69130374Sdavidxu		SIGSETNAND(tempset, newmask);
70130374Sdavidxu		if (SIGISEMPTY(tempset)) {
71130374Sdavidxu			THR_SET_STATE(curthread, PS_SIGSUSPEND);
72130374Sdavidxu			/* Wait for a signal: */
73130374Sdavidxu			_thr_sched_switch_unlocked(curthread);
74130374Sdavidxu		} else {
75139023Sdeischen			curthread->check_pending = 1;
76130374Sdavidxu			THR_UNLOCK_SWITCH(curthread);
77130374Sdavidxu			/* check pending signal I can handle: */
78130374Sdavidxu			_thr_sig_check_pending(curthread);
79130374Sdavidxu		}
80139052Sdeischen		if ((curthread->cancelflags & THR_CANCELLING) != 0)
81139052Sdeischen			curthread->oldsigmask = NULL;
82139052Sdeischen		else {
83139052Sdeischen			THR_ASSERT(curthread->oldsigmask == NULL,
84139052Sdeischen		 	          "oldsigmask is not cleared");
85139052Sdeischen		}
86139052Sdeischen
87113658Sdeischen		/* Always return an interrupted error: */
88113658Sdeischen		errno = EINTR;
89113658Sdeischen	} else {
90113658Sdeischen		/* Return an invalid argument error: */
91113658Sdeischen		errno = EINVAL;
92113658Sdeischen	}
93113658Sdeischen
94113658Sdeischen	/* Return the completion status: */
95113658Sdeischen	return (ret);
96113658Sdeischen}
97113658Sdeischen
98113658Sdeischenint
9971581Sdeischen__sigsuspend(const sigset_t * set)
10056698Sjasone{
101113658Sdeischen	struct pthread *curthread = _get_curthread();
102113658Sdeischen	int		ret;
10356698Sjasone
104123312Sdavidxu	_thr_cancel_enter(curthread);
105113658Sdeischen	ret = _sigsuspend(set);
106123312Sdavidxu	_thr_cancel_leave(curthread, 1);
10756698Sjasone
108113658Sdeischen	return (ret);
10956698Sjasone}
110