Update copyright dates with scripts/update-copyrights.
[glibc.git] / sysdeps / mach / hurd / sigwait.c
blobde024a31896f869c57545118d53cc8b1f80ce1c3
1 /* Copyright (C) 1996-2015 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
14 You should have received a copy of the GNU Lesser General Public
15 License along with the GNU C Library; if not, see
16 <http://www.gnu.org/licenses/>. */
18 #include <errno.h>
19 #include <hurd.h>
20 #include <hurd/signal.h>
21 #include <hurd/msg.h>
22 #include <hurd/sigpreempt.h>
23 #include <assert.h>
25 /* Select any of pending signals from SET or wait for any to arrive. */
26 int
27 __sigwait (const sigset_t *set, int *sig)
29 struct hurd_sigstate *ss;
30 sigset_t mask, ready;
31 int signo = 0;
32 struct hurd_signal_preemptor preemptor;
33 jmp_buf buf;
34 mach_port_t wait;
35 mach_msg_header_t msg;
37 sighandler_t
38 preempt_fun (struct hurd_signal_preemptor *pe,
39 struct hurd_sigstate *ss,
40 int *sigp,
41 struct hurd_signal_detail *detail)
43 if (signo)
44 /* We've already been run; don't interfere. */
45 return SIG_ERR;
47 signo = *sigp;
49 /* Make sure this is all kosher */
50 assert (__sigismember (&mask, signo));
52 /* Make sure this signal is unblocked */
53 __sigdelset (&ss->blocked, signo);
55 return pe->handler;
58 void
59 handler (int sig)
61 assert (sig == signo);
62 longjmp (buf, 1);
65 wait = __mach_reply_port ();
67 if (set != NULL)
68 /* Crash before locking */
69 mask = *set;
70 else
71 __sigemptyset (&mask);
73 ss = _hurd_self_sigstate ();
74 __spin_lock (&ss->lock);
76 /* See if one of these signals is currently pending. */
77 __sigandset (&ready, &ss->pending, &mask);
78 if (! __sigisemptyset (&ready))
80 for (signo = 1; signo < NSIG; signo++)
81 if (__sigismember (&ready, signo))
83 __sigdelset (&ready, signo);
84 goto all_done;
86 /* Huh? Where'd it go? */
87 abort ();
90 /* Wait for one of them to show up. */
92 if (!setjmp (buf))
94 /* Make the preemptor */
95 preemptor.signals = mask;
96 preemptor.first = 0;
97 preemptor.last = -1;
98 preemptor.preemptor = preempt_fun;
99 preemptor.handler = handler;
101 /* Install this preemptor */
102 preemptor.next = ss->preemptors;
103 ss->preemptors = &preemptor;
105 __spin_unlock (&ss->lock);
107 /* Wait. */
108 __mach_msg (&msg, MACH_RCV_MSG, 0, sizeof (msg), wait,
109 MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
110 abort ();
112 else
114 assert (signo);
116 __spin_lock (&ss->lock);
118 /* Delete our preemptor. */
119 assert (ss->preemptors == &preemptor);
120 ss->preemptors = preemptor.next;
124 all_done:
125 spin_unlock (&ss->lock);
127 __mach_port_destroy (__mach_task_self (), wait);
128 *sig = signo;
129 return 0;
132 weak_alias (__sigwait, sigwait)