thr_sigwait.c revision 38539
1/*
2 * Copyright (c) 1997 John Birrell <jb@cimlogic.com.au>.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 *    must display the following acknowledgement:
15 *	This product includes software developed by John Birrell.
16 * 4. Neither the name of the author nor the names of any co-contributors
17 *    may be used to endorse or promote products derived from this software
18 *    without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 *
32 */
33#include <signal.h>
34#include <errno.h>
35#ifdef _THREAD_SAFE
36#include <pthread.h>
37#include "pthread_private.h"
38
39int
40sigwait(const sigset_t * set, int *sig)
41{
42	int		ret = 0;
43	int		i;
44	sigset_t	oset;
45	struct sigaction act;
46
47	/*
48	 * Specify the thread kernel signal handler.
49	 */
50	act.sa_handler = (void (*) ()) _thread_sig_handler;
51	act.sa_flags = SA_RESTART;
52	act.sa_mask = *set;
53
54	/*
55	 * These signals can't be waited on.
56	 */
57	sigdelset(&act.sa_mask, SIGKILL);
58	sigdelset(&act.sa_mask, SIGSTOP);
59	sigdelset(&act.sa_mask, SIGVTALRM);
60	sigdelset(&act.sa_mask, SIGCHLD);
61	sigdelset(&act.sa_mask, SIGINFO);
62
63	/*
64	 * Enter a loop to find the signals that are SIG_DFL.  For
65	 * these signals we must install a dummy signal handler in
66	 * order for the kernel to pass them in to us.  POSIX says
67	 * that the application must explicitly install a dummy
68	 * handler for signals that are SIG_IGN in order to sigwait
69	 * on them, so we ignore SIG_IGN signals.
70	 */
71	for (i = 1; i < NSIG; i++) {
72		if (sigismember(&act.sa_mask, i)) {
73			if (_thread_sigact[i - 1].sa_handler == SIG_DFL) {
74				if (_thread_sys_sigaction(i,&act,NULL) != 0)
75					ret = -1;
76			}
77			else if (_thread_sigact[i - 1].sa_handler == SIG_IGN)
78				sigdelset(&act.sa_mask, i);
79		}
80	}
81	if (ret == 0) {
82
83		/* Save the current signal mask: */
84		oset = _thread_run->sigmask;
85
86		/* Combine the caller's mask with the current one: */
87		_thread_run->sigmask |= act.sa_mask;
88
89		/* Wait for a signal: */
90		_thread_kern_sched_state(PS_SIGWAIT, __FILE__, __LINE__);
91
92		/* Return the signal number to the caller: */
93		*sig = _thread_run->signo;
94
95		/* Restore the signal mask: */
96		_thread_run->sigmask = oset;
97	}
98
99	/* Restore the sigactions: */
100	act.sa_handler = SIG_DFL;
101	for (i = 1; i < NSIG; i++) {
102		if (sigismember(&act.sa_mask, i) &&
103		    (_thread_sigact[i - 1].sa_handler == SIG_DFL)) {
104			if (_thread_sys_sigaction(i,&act,NULL) != 0)
105				ret = -1;
106		}
107	}
108
109	/* Return the completion status: */
110	return (ret);
111}
112#endif
113