1 /* Copyright (C) 1997-2021 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    <https://www.gnu.org/licenses/>.  */
17 
18 #include <signal.h>
19 #include <sysdep.h>
20 
21 int
__sigtimedwait64(const sigset_t * set,siginfo_t * info,const struct __timespec64 * timeout)22 __sigtimedwait64 (const sigset_t *set, siginfo_t *info,
23 		  const struct __timespec64 *timeout)
24 {
25 #ifndef __NR_rt_sigtimedwait_time64
26 # define __NR_rt_sigtimedwait_time64 __NR_rt_sigtimedwait
27 #endif
28 
29   int result;
30 #ifdef __ASSUME_TIME64_SYSCALLS
31   result = SYSCALL_CANCEL (rt_sigtimedwait_time64, set, info, timeout,
32 			   __NSIG_BYTES);
33 #else
34   bool need_time64 = timeout != NULL && !in_time_t_range (timeout->tv_sec);
35   if (need_time64)
36     {
37       result = SYSCALL_CANCEL (rt_sigtimedwait_time64, set, info, timeout,
38 			       __NSIG_BYTES);
39       if (result == 0 || errno != ENOSYS)
40 	return result;
41       __set_errno (EOVERFLOW);
42       return -1;
43     }
44   else
45     {
46       struct timespec ts32, *pts32 = NULL;
47       if (timeout != NULL)
48 	{
49 	  ts32 = valid_timespec64_to_timespec (*timeout);
50 	  pts32 = &ts32;
51 	}
52       result = SYSCALL_CANCEL (rt_sigtimedwait, set, info, pts32,
53 			       __NSIG_BYTES);
54     }
55 #endif
56 
57   /* The kernel generates a SI_TKILL code in si_code in case tkill is
58      used.  tkill is transparently used in raise().  Since having
59      SI_TKILL as a code is useful in general we fold the results
60      here.  */
61   if (result != -1 && info != NULL && info->si_code == SI_TKILL)
62     info->si_code = SI_USER;
63 
64   return result;
65 }
66 #if __TIMESIZE != 64
libc_hidden_def(__sigtimedwait64)67 libc_hidden_def (__sigtimedwait64)
68 
69 int
70 __sigtimedwait (const sigset_t *set, siginfo_t *info,
71 		const struct timespec *timeout)
72 {
73   struct __timespec64 ts64, *pts64 = NULL;
74   if (timeout != NULL)
75     {
76       ts64 = valid_timespec_to_timespec64 (*timeout);
77       pts64 = &ts64;
78     }
79   return __sigtimedwait64 (set, info, pts64);
80 }
81 #endif
82 libc_hidden_def (__sigtimedwait)
83 weak_alias (__sigtimedwait, sigtimedwait)
84