1 /* Implementation of sigtimedwait function from POSIX.1b.
2 Copyright (C) 1996-2024 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
21 #include <hurd/signal.h>
23 #include <hurd/sigpreempt.h>
25 #include <sysdep-cancel.h>
28 __sigtimedwait (const sigset_t
*set
, siginfo_t
*info
,
29 const struct timespec
*timeout
)
31 struct hurd_sigstate
*ss
;
32 sigset_t mask
, ready
, blocked
;
34 struct hurd_signal_preemptor preemptor
;
37 mach_msg_header_t msg
;
39 mach_msg_option_t option
= 0;
40 mach_msg_timeout_t ms
= MACH_MSG_TIMEOUT_NONE
;
43 preempt_fun (struct hurd_signal_preemptor
*pe
,
44 struct hurd_sigstate
*ss
,
46 struct hurd_signal_detail
*detail
)
49 /* We've already been run; don't interfere. */
56 info
->si_signo
= signo
;
57 info
->si_errno
= detail
->error
;
58 info
->si_code
= detail
->code
;
63 info
->si_addr
= (void *) NULL
;
66 info
->si_value
.sival_int
= 0;
69 /* Make sure this is all kosher */
70 assert (__sigismember (&mask
, signo
));
72 /* Restore the blocking mask. */
73 ss
->blocked
= blocked
;
81 assert (sig
== signo
);
85 wait
= __mach_reply_port ();
88 /* Crash before locking */
91 __sigemptyset (&mask
);
93 ss
= _hurd_self_sigstate ();
94 cancel_oldtype
= LIBC_CANCEL_ASYNC();
95 _hurd_sigstate_lock (ss
);
97 /* See if one of these signals is currently pending. */
98 sigset_t pending
= _hurd_sigstate_pending (ss
);
99 __sigandset (&ready
, &pending
, &mask
);
100 if (! __sigisemptyset (&ready
))
102 for (signo
= 1; signo
< NSIG
; signo
++)
103 if (__sigismember (&ready
, signo
))
105 __sigdelset (&ready
, signo
);
108 /* Huh? Where'd it go? */
112 /* Wait for one of them to show up. */
116 /* Make the preemptor */
117 preemptor
.signals
= mask
;
120 preemptor
.preemptor
= preempt_fun
;
121 preemptor
.handler
= handler
;
123 /* Install this preemptor */
124 preemptor
.next
= ss
->preemptors
;
125 ss
->preemptors
= &preemptor
;
127 /* Unblock the expected signals */
128 blocked
= ss
->blocked
;
129 ss
->blocked
&= ~mask
;
131 _hurd_sigstate_unlock (ss
);
135 option
|= MACH_RCV_TIMEOUT
,
136 ms
= timeout
->tv_sec
* 1000
137 + (timeout
->tv_nsec
+ 999999) / 1000000;
141 __mach_msg (&msg
, MACH_RCV_MSG
| option
, 0, sizeof (msg
), wait
,
144 if (!(option
& MACH_RCV_TIMEOUT
))
148 signo
= __hurd_fail (EAGAIN
);
154 _hurd_sigstate_lock (ss
);
156 /* Delete our preemptor. */
157 assert (ss
->preemptors
== &preemptor
);
158 ss
->preemptors
= preemptor
.next
;
163 _hurd_sigstate_unlock (ss
);
164 LIBC_CANCEL_RESET (cancel_oldtype
);
166 __mach_port_destroy (__mach_task_self (), wait
);
169 libc_hidden_def (__sigtimedwait
)
170 weak_alias (__sigtimedwait
, sigtimedwait
)