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 | |
| parent | 1d4471b1fdfaa042ac48e9d8bcf00842dc529418 (diff) | |
| download | musl-89c5016cbacc8d2ea6c631ce12fae99cee48b62b.tar.gz | |
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.
| -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);  }  | 
