aboutsummaryrefslogtreecommitdiff
path: root/sysdeps/unix/sysv/linux/sigtimedwait.c
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/unix/sysv/linux/sigtimedwait.c')
-rw-r--r--sysdeps/unix/sysv/linux/sigtimedwait.c81
1 files changed, 81 insertions, 0 deletions
diff --git a/sysdeps/unix/sysv/linux/sigtimedwait.c b/sysdeps/unix/sysv/linux/sigtimedwait.c
index b4de8856dd..6cfe8f082e 100644
--- a/sysdeps/unix/sysv/linux/sigtimedwait.c
+++ b/sysdeps/unix/sysv/linux/sigtimedwait.c
@@ -18,7 +18,11 @@
#include <errno.h>
#include <signal.h>
#include <string.h>
+//#include <stdint.h>
+
+//#include <nptl/pthreadP.h>
#include <sysdep-cancel.h>
+#include <y2038-support.h>
int
__sigtimedwait (const sigset_t *set, siginfo_t *info,
@@ -39,3 +43,80 @@ __sigtimedwait (const sigset_t *set, siginfo_t *info,
}
libc_hidden_def (__sigtimedwait)
weak_alias (__sigtimedwait, sigtimedwait)
+
+/* 64-bit time version */
+
+int
+__sigtimedwait_time64 (const sigset_t *set, siginfo_t *info,
+ const struct __timespec64 *timeout)
+{
+ int result;
+ struct timespec ts32;
+#ifdef __NR_rt_sigtimedwait_time64
+ struct __timespec64 ts64;
+#endif
+
+#ifdef SIGCANCEL
+ sigset_t tmpset;
+ if (set != NULL
+ && (__builtin_expect (__sigismember (set, SIGCANCEL), 0)
+# ifdef SIGSETXID
+ || __builtin_expect (__sigismember (set, SIGSETXID), 0)
+# endif
+ ))
+ {
+ /* Create a temporary mask without the bit for SIGCANCEL set. */
+ // We are not copying more than we have to.
+ memcpy (&tmpset, set, _NSIG / 8);
+ __sigdelset (&tmpset, SIGCANCEL);
+# ifdef SIGSETXID
+ __sigdelset (&tmpset, SIGSETXID);
+# endif
+ set = &tmpset;
+ }
+#endif
+
+ /* XXX The size argument hopefully will have to be changed to the
+ real size of the user-level sigset_t. */
+#ifdef __NR_rt_sigtimedwait_time64
+ if (__y2038_linux_support > 0)
+ {
+ if (timeout)
+ {
+ ts64.tv_sec = timeout->tv_sec;
+ ts64.tv_nsec = timeout->tv_nsec;
+ ts64.tv_pad = 0;
+ result = SYSCALL_CANCEL (rt_sigtimedwait_time64, set, info, &ts64, _NSIG / 8);
+ if (result == -1 && errno==ENOSYS)
+ {
+ __y2038_linux_support = -1;
+ }
+ }
+ else
+ result = SYSCALL_CANCEL (rt_sigtimedwait, set, info, NULL, _NSIG / 8);
+ }
+ else
+#endif
+ {
+ if (timeout)
+ {
+ if (! timespec64_to_timespec(timeout, &ts32))
+ {
+ errno = EOVERFLOW;
+ return -1;
+ }
+ result = SYSCALL_CANCEL (rt_sigtimedwait, set, info, &ts32, _NSIG / 8);
+ }
+ else
+ result = SYSCALL_CANCEL (rt_sigtimedwait, set, info, NULL, _NSIG / 8);
+ }
+
+ /* The kernel generates a SI_TKILL code in si_code in case tkill is
+ used. tkill is transparently used in raise(). Since having
+ SI_TKILL as a code is useful in general we fold the results
+ here. */
+ if (result != -1 && info != NULL && info->si_code == SI_TKILL)
+ info->si_code = SI_USER;
+
+ return result;
+}