diff options
author | Rich Felker <dalias@aerifal.cx> | 2019-07-28 23:53:38 -0400 |
---|---|---|
committer | Rich Felker <dalias@aerifal.cx> | 2019-07-29 12:31:46 -0400 |
commit | 89c5016cbacc8d2ea6c631ce12fae99cee48b62b (patch) | |
tree | 0c2af3dab0389b874f8e4dde349316e9613e56e4 /src | |
parent | 1d4471b1fdfaa042ac48e9d8bcf00842dc529418 (diff) | |
download | musl-89c5016cbacc8d2ea6c631ce12fae99cee48b62b.tar.gz musl-89c5016cbacc8d2ea6c631ce12fae99cee48b62b.tar.xz musl-89c5016cbacc8d2ea6c631ce12fae99cee48b62b.zip |
timerfd: add time64 syscall support, decouple 32-bit time_t
the changes here are semantically and structurally identical to those made to timer_settime and timer_gettime for time64 support.
Diffstat (limited to 'src')
-rw-r--r-- | src/linux/timerfd.c | 42 |
1 files changed, 42 insertions, 0 deletions
diff --git a/src/linux/timerfd.c b/src/linux/timerfd.c index 62cc2773..5bdfaf16 100644 --- a/src/linux/timerfd.c +++ b/src/linux/timerfd.c @@ -1,6 +1,9 @@ #include <sys/timerfd.h> +#include <errno.h> #include "syscall.h" +#define IS32BIT(x) !((x)+0x80000000ULL>>32) + int timerfd_create(int clockid, int flags) { return syscall(SYS_timerfd_create, clockid, flags); @@ -8,10 +11,49 @@ int timerfd_create(int clockid, int flags) int timerfd_settime(int fd, int flags, const struct itimerspec *new, struct itimerspec *old) { +#ifdef SYS_timerfd_settime64 + time_t is = new->it_interval.tv_sec, vs = new->it_value.tv_sec; + long ins = new->it_interval.tv_nsec, vns = new->it_value.tv_nsec; + int r = -ENOSYS; + if (SYS_timerfd_settime == SYS_timerfd_settime64 + || !IS32BIT(is) || !IS32BIT(vs) || (sizeof(time_t)>4 && old)) + r = __syscall(SYS_timerfd_settime64, fd, flags, + ((long long[]){is, ins, vs, vns}), old); + if (SYS_timerfd_settime == SYS_timerfd_settime64 || r!=-ENOSYS) + return __syscall_ret(r); + if (!IS32BIT(is) || !IS32BIT(vs)) + return __syscall_ret(-ENOTSUP); + long old32[4]; + r = __syscall(SYS_timerfd_settime, fd, flags, + ((long[]){is, ins, vs, vns}), old32); + if (!r && old) { + old->it_interval.tv_sec = old32[0]; + old->it_interval.tv_nsec = old32[1]; + old->it_value.tv_sec = old32[2]; + old->it_value.tv_nsec = old32[3]; + } + return __syscall_ret(r); +#endif return syscall(SYS_timerfd_settime, fd, flags, new, old); } int timerfd_gettime(int fd, struct itimerspec *cur) { +#ifdef SYS_timerfd_gettime64 + int r = -ENOSYS; + if (sizeof(time_t) > 4) + r = __syscall(SYS_timerfd_gettime64, fd, cur); + if (SYS_timerfd_gettime == SYS_timerfd_gettime64 || r!=-ENOSYS) + return __syscall_ret(r); + long cur32[4]; + r = __syscall(SYS_timerfd_gettime, fd, cur32); + if (!r) { + cur->it_interval.tv_sec = cur32[0]; + cur->it_interval.tv_nsec = cur32[1]; + cur->it_value.tv_sec = cur32[2]; + cur->it_value.tv_nsec = cur32[3]; + } + return __syscall_ret(r); +#endif return syscall(SYS_timerfd_gettime, fd, cur); } |