aboutsummaryrefslogtreecommitdiff
path: root/sysdeps/unix/sysv/linux/timer_settime.c
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/unix/sysv/linux/timer_settime.c')
-rw-r--r--sysdeps/unix/sysv/linux/timer_settime.c50
1 files changed, 50 insertions, 0 deletions
diff --git a/sysdeps/unix/sysv/linux/timer_settime.c b/sysdeps/unix/sysv/linux/timer_settime.c
index 7c938bd4a4..bc876a9e64 100644
--- a/sysdeps/unix/sysv/linux/timer_settime.c
+++ b/sysdeps/unix/sysv/linux/timer_settime.c
@@ -20,6 +20,7 @@
#include <stdlib.h>
#include <time.h>
#include <sysdep.h>
+#include <y2038-support.h>
#include "kernel-posix-timers.h"
@@ -41,3 +42,52 @@ timer_settime (timer_t timerid, int flags, const struct itimerspec *value,
return res;
}
+
+/* 64-bit time version */
+
+int
+__timer_settime64 (timer_t timerid, int flags, const struct itimerspec *value,
+ struct itimerspec *ovalue)
+{
+ int res;
+ struct timer *kt = (struct timer *) timerid;
+ struct itimerspec value32, ovalue32;
+
+ if (value == NULL)
+ {
+ __set_errno(EFAULT);
+ return -1;
+ }
+
+#ifdef __NR_timer_settime64
+ if (__y2038_get_kernel_support () > 0)
+ {
+ res = INLINE_SYSCALL (timer_settime, 3, kt->ktimerid, value, ovalue);
+ if (res == 0 || errno != ENOSYS)
+ return res;
+ __y2038_set_kernel_support (-1);
+ }
+#endif
+
+ if (value->it_value.tv_sec > INT_MAX
+ || value->it_interval.tv_sec > INT_MAX)
+ return EOVERFLOW;
+
+ value32.it_value.tv_sec = value->it_value.tv_sec;
+ value32.it_value.tv_nsec = value->it_value.tv_nsec;
+ value32.it_interval.tv_sec = value->it_interval.tv_sec;
+ value32.it_interval.tv_nsec = value->it_interval.tv_nsec;
+
+ res = INLINE_SYSCALL (timer_settime, 4, kt->ktimerid, flags,
+ &value32, &ovalue32);
+
+ if (res == 0 && ovalue != NULL)
+ {
+ ovalue->it_value.tv_sec = ovalue32.it_value.tv_sec;
+ ovalue->it_value.tv_nsec = ovalue32.it_value.tv_nsec;
+ ovalue->it_interval.tv_sec = ovalue32.it_interval.tv_sec;
+ ovalue->it_interval.tv_nsec = ovalue32.it_interval.tv_nsec;
+ }
+
+ return res;
+}