]> git.ipfire.org Git - thirdparty/glibc.git/blob - sysdeps/mach/hurd/sigwait.c
Merge glibc-ports into ports/ directory.
[thirdparty/glibc.git] / sysdeps / mach / hurd / sigwait.c
1 /* Copyright (C) 1996,97,2001,02 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3
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.
8
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.
13
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/>. */
17
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>
24
25 /* Select any of pending signals from SET or wait for any to arrive. */
26 int
27 __sigwait (const sigset_t *set, int *sig)
28 {
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;
36
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)
42 {
43 if (signo)
44 /* We've already been run; don't interfere. */
45 return SIG_ERR;
46
47 signo = *sigp;
48
49 /* Make sure this is all kosher */
50 assert (__sigismember (&mask, signo));
51
52 /* Make sure this signal is unblocked */
53 __sigdelset (&ss->blocked, signo);
54
55 return pe->handler;
56 }
57
58 void
59 handler (int sig)
60 {
61 assert (sig == signo);
62 longjmp (buf, 1);
63 }
64
65 wait = __mach_reply_port ();
66
67 if (set != NULL)
68 /* Crash before locking */
69 mask = *set;
70 else
71 __sigemptyset (&mask);
72
73 ss = _hurd_self_sigstate ();
74 __spin_lock (&ss->lock);
75
76 /* See if one of these signals is currently pending. */
77 __sigandset (&ready, &ss->pending, &mask);
78 if (! __sigisemptyset (&ready))
79 {
80 for (signo = 1; signo < NSIG; signo++)
81 if (__sigismember (&ready, signo))
82 {
83 __sigdelset (&ready, signo);
84 goto all_done;
85 }
86 /* Huh? Where'd it go? */
87 abort ();
88 }
89
90 /* Wait for one of them to show up. */
91
92 if (!setjmp (buf))
93 {
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;
100
101 /* Install this preemptor */
102 preemptor.next = ss->preemptors;
103 ss->preemptors = &preemptor;
104
105 __spin_unlock (&ss->lock);
106
107 /* Wait. */
108 __mach_msg (&msg, MACH_RCV_MSG, 0, sizeof (msg), wait,
109 MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
110 abort ();
111 }
112 else
113 {
114 assert (signo);
115
116 __spin_lock (&ss->lock);
117
118 /* Delete our preemptor. */
119 assert (ss->preemptors == &preemptor);
120 ss->preemptors = preemptor.next;
121 }
122
123
124 all_done:
125 spin_unlock (&ss->lock);
126
127 __mach_port_destroy (__mach_task_self (), wait);
128 *sig = signo;
129 return 0;
130 }
131
132 weak_alias (__sigwait, sigwait)