diff options
authorRich Felker <>2019-07-28 18:43:51 -0400
committerRich Felker <>2019-07-29 00:17:02 -0400
commit7aeecf3e0b5462a05f7173993618eb59ba1a86d5 (patch)
parente1501091c404a74f3966441dbf8f6b85bae905c2 (diff)
clock_settime: add time64 syscall support, decouple 32-bit time_t
time64 syscall is used only if it's the only one defined for the arch, or if the requested time does not fit in 32 bits. on current 32-bit archs where time_t is a 32-bit type, this makes it statically unreachable. if the time64 syscall is needed because the requested time does not fit in 32 bits, we define this as an error ENOTSUP, for "The implementation does not support the requested feature or value". on 64-bit archs, there is no change to the code after preprocessing. on current 32-bit archs, the time is moved through an intermediate copy to remove the assumption that time_t is a 32-bit type.
1 files changed, 17 insertions, 0 deletions
diff --git a/src/time/clock_settime.c b/src/time/clock_settime.c
index 66b8162d..5fdaeb9e 100644
--- a/src/time/clock_settime.c
+++ b/src/time/clock_settime.c
@@ -1,7 +1,24 @@
#include <time.h>
+#include <errno.h>
#include "syscall.h"
+#define IS32BIT(x) !((x)+0x80000000ULL>>32)
int clock_settime(clockid_t clk, const struct timespec *ts)
+#ifdef SYS_clock_settime64
+ time_t s = ts->tv_sec;
+ long ns = ts->tv_nsec;
+ int r = -ENOSYS;
+ if (SYS_clock_settime == SYS_clock_settime64 || !IS32BIT(s))
+ r = __syscall(SYS_clock_settime64, clk,
+ ((long long[]){s, ns}));
+ if (SYS_clock_settime == SYS_clock_settime64 || r!=-ENOSYS)
+ return __syscall_ret(r);
+ if (!IS32BIT(s))
+ return __syscall_ret(-ENOTSUP);
+ return syscall(SYS_clock_settime, clk, ts ? ((long[]){s, ns}) : 0);
return syscall(SYS_clock_settime, clk, ts);