about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--include/time.h9
-rw-r--r--sysdeps/unix/sysv/linux/timer_settime.c68
2 files changed, 71 insertions, 6 deletions
diff --git a/include/time.h b/include/time.h
index 51c0fce580..e5e8246eac 100644
--- a/include/time.h
+++ b/include/time.h
@@ -186,6 +186,15 @@ extern int __timer_gettime64 (timer_t timerid, struct __itimerspec64 *value);
 libc_hidden_proto (__timer_gettime64);
 #endif
 
+#if __TIMESIZE == 64
+# define __timer_settime64 __timer_settime
+#else
+extern int __timer_settime64 (timer_t timerid, int flags,
+                              const struct __itimerspec64 *value,
+                              struct __itimerspec64 *ovalue);
+libc_hidden_proto (__timer_settime64);
+#endif
+
 /* Compute the `struct tm' representation of T,
    offset OFFSET seconds east of UTC,
    and store year, yday, mon, mday, wday, hour, min, sec into *TP.
diff --git a/sysdeps/unix/sysv/linux/timer_settime.c b/sysdeps/unix/sysv/linux/timer_settime.c
index 51f24200aa..402b676f69 100644
--- a/sysdeps/unix/sysv/linux/timer_settime.c
+++ b/sysdeps/unix/sysv/linux/timer_settime.c
@@ -20,17 +20,73 @@
 #include <stdlib.h>
 #include <time.h>
 #include <sysdep.h>
+#include <kernel-features.h>
 #include "kernel-posix-timers.h"
 
 int
-timer_settime (timer_t timerid, int flags, const struct itimerspec *value,
-	       struct itimerspec *ovalue)
+__timer_settime64 (timer_t timerid, int flags,
+                   const struct __itimerspec64 *value,
+                   struct __itimerspec64 *ovalue)
 {
   struct timer *kt = (struct timer *) timerid;
 
-  /* Delete the kernel timer object.  */
-  int res = INLINE_SYSCALL (timer_settime, 4, kt->ktimerid, flags,
-			    value, ovalue);
+#ifdef __ASSUME_TIME64_SYSCALLS
+# ifndef __NR_timer_settime64
+#  define __NR_timer_settime64 __NR_timer_settime
+# endif
+  return INLINE_SYSCALL_CALL (timer_settime64, kt->ktimerid, flags, value,
+                              ovalue);
+#else
+# ifdef __NR_timer_settime64
+  int ret = INLINE_SYSCALL_CALL (timer_settime64, kt->ktimerid, flags, value,
+                                 ovalue);
+  if (ret == 0 || errno != ENOSYS)
+    return ret;
+# endif
+  struct itimerspec its32, oits32;
 
-  return res;
+  if (! in_time_t_range ((value->it_value).tv_sec)
+      || ! in_time_t_range ((value->it_interval).tv_sec))
+    {
+      __set_errno (EOVERFLOW);
+      return -1;
+    }
+
+  its32.it_interval = valid_timespec64_to_timespec (value->it_interval);
+  its32.it_value = valid_timespec64_to_timespec (value->it_value);
+
+  int retval = INLINE_SYSCALL_CALL (timer_settime, kt->ktimerid, flags,
+                                    &its32, ovalue ? &oits32 : NULL);
+  if (retval == 0 && ovalue)
+    {
+      ovalue->it_interval = valid_timespec_to_timespec64 (oits32.it_interval);
+      ovalue->it_value = valid_timespec_to_timespec64 (oits32.it_value);
+    }
+
+  return retval;
+#endif
+}
+
+#if __TIMESIZE != 64
+int
+__timer_settime (timer_t timerid, int flags, const struct itimerspec *value,
+                 struct itimerspec *ovalue)
+{
+  struct __itimerspec64 its64, oits64;
+  int retval;
+
+  its64.it_interval = valid_timespec_to_timespec64 (value->it_interval);
+  its64.it_value = valid_timespec_to_timespec64 (value->it_value);
+
+  retval = __timer_settime64 (timerid, flags, &its64, ovalue ? &oits64 : NULL);
+  if (retval == 0 && ovalue)
+    {
+      ovalue->it_interval = valid_timespec64_to_timespec (oits64.it_interval);
+      ovalue->it_value = valid_timespec64_to_timespec (oits64.it_value);
+    }
+
+  return retval;
 }
+#endif
+weak_alias (__timer_settime, timer_settime)
+libc_hidden_def (timer_settime)