From 8ea0140d5ffd2dc4ec0e36de71b67e6c1955f3cb Mon Sep 17 00:00:00 2001 From: Dmitry Chestnykh Date: Wed, 21 Feb 2024 19:08:28 +0300 Subject: Introduce time64 support. This patch introduces *time64 syscalls support for uClibc-ng. Currently the redirection of syscalls to their *time64 analogs is fully supported for 32bit ARM (ARMv5, ARMv6, ARMv7). The main changes that take effect when time64 feature is enabled are: - sizeof(time_t) is 8. - There is a possibility os setting date beyond year 2038. - some syscalls are redirected: clock_adjtime -> clock_adjtime64 clock_getres -> clock_getres_time64 clock_gettime -> clock_gettime64 clock_nanosleep -> clock_nanosleep_time64 clock_settime -> clock_settime64 futex -> futex_time64 mq_timedreceive -> mq_timedreceive_time64 mq_timedsend -> mq_timedsend_time64 ppoll -> ppoll_time64 pselect6 -> pselect6_time64 recvmmsg -> recvmmsg_time64 rt_sigtimedwait -> rt_sigtimedwait_time64 sched_rr_get_interval -> sched_rr_get_interval_time64 semtimedop -> semtimedop_time64 timer_gettime -> timer_gettime64 timer_settime -> timer_settime64 timerfd_gettime -> timerfd_gettime64 timerfd_settime -> timerfd_settime64 utimensat -> utimensat_time64. - settimeofday uses clock_settime (like in glibc/musl). - gettimeofday uses clock_gettime (like in glibc/musl). - nanosleep uses clock_nanosleep (like in glibc/musl). - There are some fixes in data structures used by libc and kernel for correct data handling both with and without enabled time64 support. Signed-off-by: Dmitry Chestnykh --- libc/inet/socketcalls.c | 4 +- libc/misc/sysvipc/sem.c | 11 ++++- libc/misc/time/time.c | 9 ++++- libc/sysdeps/linux/arm/bits/kernel_stat.h | 24 ++++++++++- libc/sysdeps/linux/common/__rt_sigtimedwait.c | 10 +++++ libc/sysdeps/linux/common/alarm.c | 2 +- libc/sysdeps/linux/common/bits/sem.h | 21 ++++++---- libc/sysdeps/linux/common/bits/syscalls-common.h | 49 +++++++++++++++++++++++ libc/sysdeps/linux/common/bits/typesizes.h | 12 ++++++ libc/sysdeps/linux/common/clock_adjtime.c | 6 ++- libc/sysdeps/linux/common/clock_getres.c | 5 ++- libc/sysdeps/linux/common/clock_gettime.c | 4 +- libc/sysdeps/linux/common/clock_settime.c | 5 ++- libc/sysdeps/linux/common/fstatat.c | 8 ++++ libc/sysdeps/linux/common/gettimeofday.c | 11 ++++- libc/sysdeps/linux/common/nanosleep.c | 16 ++++++-- libc/sysdeps/linux/common/ppoll.c | 7 +++- libc/sysdeps/linux/common/pselect.c | 6 ++- libc/sysdeps/linux/common/sched_rr_get_interval.c | 5 +++ libc/sysdeps/linux/common/setitimer.c | 32 +++++++++++++++ libc/sysdeps/linux/common/settimeofday.c | 21 +++++++--- libc/sysdeps/linux/common/timerfd.c | 14 +++++-- libc/sysdeps/linux/common/utimensat.c | 6 ++- libc/sysdeps/linux/common/wait4.c | 15 +++++++ libc/sysdeps/linux/common/xstatconv.c | 27 +++++++++++++ 25 files changed, 295 insertions(+), 35 deletions(-) (limited to 'libc') diff --git a/libc/inet/socketcalls.c b/libc/inet/socketcalls.c index edb5ab87e..eb0983698 100644 --- a/libc/inet/socketcalls.c +++ b/libc/inet/socketcalls.c @@ -272,7 +272,9 @@ lt_libc_hidden(recvmsg) static ssize_t __NC(recvmmsg)(int sockfd, struct mmsghdr *msg, size_t vlen, int flags, struct timespec *tmo) { -# ifdef __NR_recvmmsg +# if defined(__UCLIBC_USE_TIME64__) && defined(__NR_recvmmsg_time64) + return (ssize_t)INLINE_SYSCALL(recvmmsg_time64, 5, sockfd, msg, vlen, flags, tmo); +# elif defined(__NR_recvmmsg) return (ssize_t)INLINE_SYSCALL(recvmmsg, 5, sockfd, msg, vlen, flags, tmo); # elif __NR_socketcall unsigned long args[5]; diff --git a/libc/misc/sysvipc/sem.c b/libc/misc/sysvipc/sem.c index 64be1cae0..cd541761c 100644 --- a/libc/misc/sysvipc/sem.c +++ b/libc/misc/sysvipc/sem.c @@ -53,7 +53,12 @@ int semctl(int semid, int semnum, int cmd, ...) arg = va_arg (ap, union semun); va_end (ap); #ifdef __NR_semctl - return __semctl(semid, semnum, cmd | __IPC_64, arg.__pad); + int __ret = __semctl(semid, semnum, cmd | __IPC_64, arg.__pad); +#if defined(__UCLIBC_USE_TIME64__) + arg.buf->sem_otime = (__time_t)arg.buf->__sem_otime_internal_1 | (__time_t)(arg.buf->__sem_otime_internal_2) << 32; + arg.buf->sem_ctime = (__time_t)arg.buf->__sem_ctime_internal_1 | (__time_t)(arg.buf->__sem_ctime_internal_2) << 32; +#endif + return __ret; #else return __syscall_ipc(IPCOP_semctl, semid, semnum, cmd|__IPC_64, &arg, NULL); #endif @@ -90,7 +95,9 @@ int semop (int semid, struct sembuf *sops, size_t nsops) #ifdef L_semtimedop -#ifdef __NR_semtimedop +#if defined(__UCLIBC_USE_TIME64__) && defined(__NR_semtimedop_time64) +_syscall4_time64(int, semtimedop, int, semid, struct sembuf *, sops, size_t, nsops, const struct timespec *, timeout) +#elif defined(__NR_semtimedop) _syscall4(int, semtimedop, int, semid, struct sembuf *, sops, size_t, nsops, const struct timespec *, timeout) #else diff --git a/libc/misc/time/time.c b/libc/misc/time/time.c index 0f7c6a33f..b6a5b097d 100644 --- a/libc/misc/time/time.c +++ b/libc/misc/time/time.c @@ -2478,9 +2478,16 @@ DST_CORRECT: + p[3]) + p[7]))); DST_CORRECT: +#if defined(__UCLIBC_USE_TIME64__) + if (((unsigned long long)(secs - LLONG_MIN)) + > (((unsigned long long)LLONG_MAX) - LLONG_MIN) + ) +#else if (((unsigned long long)(secs - LONG_MIN)) > (((unsigned long long)LONG_MAX) - LONG_MIN) - ) { + ) +#endif + { t = ((time_t)(-1)); goto DONE; } diff --git a/libc/sysdeps/linux/arm/bits/kernel_stat.h b/libc/sysdeps/linux/arm/bits/kernel_stat.h index b293dfc05..8bddb4085 100644 --- a/libc/sysdeps/linux/arm/bits/kernel_stat.h +++ b/libc/sysdeps/linux/arm/bits/kernel_stat.h @@ -5,6 +5,17 @@ * struct kernel_stat should look like... It turns out each arch has a * different opinion on the subject... */ +#if defined(__UCLIBC_USE_TIME64__) + +#include + +struct ts32_struct { + __S32_TYPE tv_sec; + __S32_TYPE tv_nsec; +}; + +#endif + struct kernel_stat { #if defined(__ARMEB__) unsigned short st_dev; @@ -26,9 +37,15 @@ struct kernel_stat { unsigned long st_size; unsigned long st_blksize; unsigned long st_blocks; +#if defined(__UCLIBC_USE_TIME64__) + struct ts32_struct __st_atim32; + struct ts32_struct __st_mtim32; + struct ts32_struct __st_ctim32; +#else struct timespec st_atim; struct timespec st_mtim; struct timespec st_ctim; +#endif unsigned long __uclibc_unused4; unsigned long __uclibc_unused5; }; @@ -50,10 +67,15 @@ struct kernel_stat64 { long long st_size; unsigned long st_blksize; unsigned long long st_blocks; /* Number 512-byte blocks allocated. */ - +#if defined(__UCLIBC_USE_TIME64__) + struct ts32_struct __st_atim32; + struct ts32_struct __st_mtim32; + struct ts32_struct __st_ctim32; +#else struct timespec st_atim; struct timespec st_mtim; struct timespec st_ctim; +#endif unsigned long long st_ino; #ifndef __ARM_EABI__ } __attribute__((packed)); diff --git a/libc/sysdeps/linux/common/__rt_sigtimedwait.c b/libc/sysdeps/linux/common/__rt_sigtimedwait.c index f4244148d..bd82ca6d5 100644 --- a/libc/sysdeps/linux/common/__rt_sigtimedwait.c +++ b/libc/sysdeps/linux/common/__rt_sigtimedwait.c @@ -52,8 +52,13 @@ int __NC(sigtimedwait)(const sigset_t *set, siginfo_t *info, /* XXX The size argument hopefully will have to be changed to the real size of the user-level sigset_t. */ /* on uClibc we use the kernel sigset_t size */ +# if defined(__UCLIBC_USE_TIME64__) && defined(__NR_rt_sigtimedwait_time64) + result = INLINE_SYSCALL(rt_sigtimedwait_time64, 4, set, info, + timeout, __SYSCALL_SIGSET_T_SIZE); +# else result = INLINE_SYSCALL(rt_sigtimedwait, 4, set, info, timeout, __SYSCALL_SIGSET_T_SIZE); +# endif /* The kernel generates a SI_TKILL code in si_code in case tkill is used. tkill is transparently used in raise(). Since having @@ -65,9 +70,14 @@ int __NC(sigtimedwait)(const sigset_t *set, siginfo_t *info, return result; # else /* on uClibc we use the kernel sigset_t size */ +# if defined(__UCLIBC_USE_TIME64__) && defined(__NR_rt_sigtimedwait_time64) + return INLINE_SYSCALL(rt_sigtimedwait_time64, 4, set, info, + timeout, __SYSCALL_SIGSET_T_SIZE); +# else return INLINE_SYSCALL(rt_sigtimedwait, 4, set, info, timeout, __SYSCALL_SIGSET_T_SIZE); # endif +# endif } CANCELLABLE_SYSCALL(int, sigtimedwait, (const sigset_t *set, siginfo_t *info, const struct timespec *timeout), diff --git a/libc/sysdeps/linux/common/alarm.c b/libc/sysdeps/linux/common/alarm.c index dc43fe732..4e6e2215b 100644 --- a/libc/sysdeps/linux/common/alarm.c +++ b/libc/sysdeps/linux/common/alarm.c @@ -9,7 +9,7 @@ #include #include -#ifdef __NR_alarm +#ifdef __NR_alarm && !defined(__UCLIBC_USE_TIME64__) _syscall1(unsigned int, alarm, unsigned int, seconds) #else # include diff --git a/libc/sysdeps/linux/common/bits/sem.h b/libc/sysdeps/linux/common/bits/sem.h index 910c4b714..06a256259 100644 --- a/libc/sysdeps/linux/common/bits/sem.h +++ b/libc/sysdeps/linux/common/bits/sem.h @@ -39,17 +39,22 @@ struct semid_ds { struct ipc_perm sem_perm; /* operation permission struct */ - __time_t sem_otime; /* last semop() time */ -#if __WORDSIZE == 32 - unsigned long int __uclibc_unused1; -#endif - __time_t sem_ctime; /* last time changed by semctl() */ -#if __WORDSIZE == 32 - unsigned long int __uclibc_unused2; + + unsigned long int __sem_otime_internal_1; + unsigned long int __sem_otime_internal_2; + unsigned long int __sem_ctime_internal_1; + unsigned long int __sem_ctime_internal_2; +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + unsigned short int sem_nsems; /* number of semaphores in set */ + char __paddind[sizeof(long int) - sizeof(short int)]; +#else + char __padding[sizeof(long int) - sizeof(short int)]; + unsigned short int sem_nsems; /* number of semaphores in set */ #endif - unsigned long int sem_nsems; /* number of semaphores in set */ unsigned long int __uclibc_unused3; unsigned long int __uclibc_unused4; + __time_t sem_otime; /* last semop() time */ + __time_t sem_ctime; /* last time changed by semctl() */ }; /* The user should define a union like the following to use it for arguments diff --git a/libc/sysdeps/linux/common/bits/syscalls-common.h b/libc/sysdeps/linux/common/bits/syscalls-common.h index adae45aac..c3b193e6f 100755 --- a/libc/sysdeps/linux/common/bits/syscalls-common.h +++ b/libc/sysdeps/linux/common/bits/syscalls-common.h @@ -99,14 +99,40 @@ type name(C_DECL_ARGS_##nargs(args)) { \ return (type)INLINE_SYSCALL(name, nargs, C_ARGS_##nargs(args)); \ } +#define SYSCALL_FUNC_TIME64(nargs, type, name, args...) \ +type name(C_DECL_ARGS_##nargs(args)) { \ + return (type)INLINE_SYSCALL(name##_time64, nargs, C_ARGS_##nargs(args)); \ +} + +#define SYSCALL_FUNC_64(nargs, type, name, args...) \ +type name(C_DECL_ARGS_##nargs(args)) { \ + return (type)INLINE_SYSCALL(name##64, nargs, C_ARGS_##nargs(args)); \ +} + + #define SYSCALL_NOERR_FUNC(nargs, type, name, args...) \ type name(C_DECL_ARGS_##nargs(args)) { \ return (type)INLINE_SYSCALL_NOERR(name, nargs, C_ARGS_##nargs(args)); \ } +#define SYSCALL_NOERR_FUNC_TIME64(nargs, type, name, args...) \ +type name(C_DECL_ARGS_##nargs(args)) { \ + return (type)INLINE_SYSCALL_NOERR(name##_time64, nargs, C_ARGS_##nargs(args)); \ +} + +#define SYSCALL_NOERR_FUNC_64(nargs, type, name, args...) \ +type name(C_DECL_ARGS_##nargs(args)) { \ + return (type)INLINE_SYSCALL_NOERR(name##64, nargs, C_ARGS_##nargs(args)); \ +} + #define SYSCALL_FUNC_BODY(nargs, type, name, args...) \ return (type)INLINE_SYSCALL(name, nargs, C_ARGS_##nargs(args)); +#define SYSCALL_FUNC_BODY_TIME64(nargs, type, name, args...) \ + return (type)INLINE_SYSCALL(name##_time64, nargs, C_ARGS_##nargs(args)); + +#define SYSCALL_FUNC_BODY_64(nargs, type, name, args...) \ + return (type)INLINE_SYSCALL(name##64, nargs, C_ARGS_##nargs(args)); #define _syscall0(args...) SYSCALL_FUNC(0, args) #define _syscall_noerr0(args...) SYSCALL_NOERR_FUNC(0, args) @@ -119,6 +145,29 @@ type name(C_DECL_ARGS_##nargs(args)) { \ #define _syscall5(args...) SYSCALL_FUNC(5, args) #define _syscall6(args...) SYSCALL_FUNC(6, args) +#define _syscall0_time64(args...) SYSCALL_FUNC_TIME64(0, args) +#define _syscall_noerr0_time64(args...) SYSCALL_NOERR_FUNC_TIME64(0, args) +#define _syscall1_time64(args...) SYSCALL_FUNC_TIME64(1, args) +#define _syscall_noerr1_time64(args...) SYSCALL_NOERR_FUNC_TIME64(1, args) +#define _syscall2_time64(args...) SYSCALL_FUNC_TIME64(2, args) +#define _syscall2_body_time64(args...) SYSCALL_FUNC_BODY_TIME64(2, args) +#define _syscall3_time64(args...) SYSCALL_FUNC_TIME64(3, args) +#define _syscall4_time64(args...) SYSCALL_FUNC_TIME64(4, args) +#define _syscall5_time64(args...) SYSCALL_FUNC_TIME64(5, args) +#define _syscall6_time64(args...) SYSCALL_FUNC_TIME64(6, args) + +#define _syscall0_64(args...) SYSCALL_FUNC_64(0, args) +#define _syscall_noerr0_64(args...) SYSCALL_NOERR_FUNC_64(0, args) +#define _syscall1_64(args...) SYSCALL_FUNC_64(1, args) +#define _syscall_noerr1_64(args...) SYSCALL_NOERR_FUNC_64(1, args) +#define _syscall2_64(args...) SYSCALL_FUNC_64(2, args) +#define _syscall2_body_64(args...) SYSCALL_FUNC_BODY_64(2, args) +#define _syscall3_64(args...) SYSCALL_FUNC_64(3, args) +#define _syscall4_64(args...) SYSCALL_FUNC_64(4, args) +#define _syscall5_64(args...) SYSCALL_FUNC_64(5, args) +#define _syscall6_64(args...) SYSCALL_FUNC_64(6, args) + + #endif /* _syscall0 */ #endif /* __ASSEMBLER__ */ diff --git a/libc/sysdeps/linux/common/bits/typesizes.h b/libc/sysdeps/linux/common/bits/typesizes.h index e1c5a27bb..dcb2c3b0a 100644 --- a/libc/sysdeps/linux/common/bits/typesizes.h +++ b/libc/sysdeps/linux/common/bits/typesizes.h @@ -46,9 +46,21 @@ #define __FSFILCNT64_T_TYPE __UQUAD_TYPE #define __ID_T_TYPE __U32_TYPE #define __CLOCK_T_TYPE __SLONGWORD_TYPE + +#ifdef __UCLIBC_USE_TIME64__ +#define __TIME_T_TYPE __S64_TYPE +#else #define __TIME_T_TYPE __SLONGWORD_TYPE +#endif /* __UCLIBC_USE_TIME64__ */ + #define __USECONDS_T_TYPE __U32_TYPE + +#ifdef __UCLIBC_USE_TIME64__ +#define __SUSECONDS_T_TYPE __S64_TYPE +#else #define __SUSECONDS_T_TYPE __SLONGWORD_TYPE +#endif + #define __DADDR_T_TYPE __S32_TYPE #define __SWBLK_T_TYPE __SLONGWORD_TYPE #define __KEY_T_TYPE __S32_TYPE diff --git a/libc/sysdeps/linux/common/clock_adjtime.c b/libc/sysdeps/linux/common/clock_adjtime.c index 9f55d4527..53f64e9d5 100644 --- a/libc/sysdeps/linux/common/clock_adjtime.c +++ b/libc/sysdeps/linux/common/clock_adjtime.c @@ -10,6 +10,10 @@ #include #include -#ifdef __NR_clock_adjtime +#if defined(__UCLIBC_USE_TIME64__) && defined(__NR_clock_adjtime64) +_syscall2_64(int, clock_adjtime, clockid_t, clock_id, struct timex*, ntx) +#elif defined(__NR_clock_adjtime) _syscall2(int, clock_adjtime, clockid_t, clock_id, struct timex*, ntx) +#else +#error "clock_adjtime syscall is not defined!" #endif diff --git a/libc/sysdeps/linux/common/clock_getres.c b/libc/sysdeps/linux/common/clock_getres.c index 532047ede..d4b989958 100644 --- a/libc/sysdeps/linux/common/clock_getres.c +++ b/libc/sysdeps/linux/common/clock_getres.c @@ -10,7 +10,10 @@ #include #include -#ifdef __NR_clock_getres + +#if defined(__UCLIBC_USE_TIME64__) && defined(__NR_clock_getres_time64) +_syscall2_time64(int, clock_getres, clockid_t, clock_id, struct timespec*, res) +#elif defined(__NR_clock_getres) _syscall2(int, clock_getres, clockid_t, clock_id, struct timespec*, res) #else # include diff --git a/libc/sysdeps/linux/common/clock_gettime.c b/libc/sysdeps/linux/common/clock_gettime.c index 95d398239..a595bd691 100644 --- a/libc/sysdeps/linux/common/clock_gettime.c +++ b/libc/sysdeps/linux/common/clock_gettime.c @@ -11,7 +11,9 @@ #include #include -#ifdef __NR_clock_gettime +#if defined(__UCLIBC_USE_TIME64__) && defined(__NR_clock_gettime64) +_syscall2_64(int, clock_gettime, clockid_t, clock_id, struct timespec*, tp) +#elif defined(__NR_clock_gettime) _syscall2(int, clock_gettime, clockid_t, clock_id, struct timespec*, tp) #else # include diff --git a/libc/sysdeps/linux/common/clock_settime.c b/libc/sysdeps/linux/common/clock_settime.c index 636f18417..89550af5a 100644 --- a/libc/sysdeps/linux/common/clock_settime.c +++ b/libc/sysdeps/linux/common/clock_settime.c @@ -10,7 +10,10 @@ #include #include -#ifdef __NR_clock_settime + +#if defined(__UCLIBC_USE_TIME64__) && defined(__NR_clock_settime64) +_syscall2_64(int, clock_settime, clockid_t, clock_id, const struct timespec*, tp) +#elif defined(__NR_clock_settime) _syscall2(int, clock_settime, clockid_t, clock_id, const struct timespec*, tp) #else # include diff --git a/libc/sysdeps/linux/common/fstatat.c b/libc/sysdeps/linux/common/fstatat.c index 13611e9d0..8064722d2 100644 --- a/libc/sysdeps/linux/common/fstatat.c +++ b/libc/sysdeps/linux/common/fstatat.c @@ -62,6 +62,14 @@ int fstatat(int fd, const char *file, struct stat *buf, int flag) .st_mtim.tv_nsec = tmp.stx_mtime.tv_nsec, .st_ctim.tv_sec = tmp.stx_ctime.tv_sec, .st_ctim.tv_nsec = tmp.stx_ctime.tv_nsec, +#if defined(__UCLIBC_USE_TIME64__) + .__st_atim32.tv_sec = stx.stx_atime.tv_sec, + .__st_atim32.tv_nsec = stx.stx_atime.tv_nsec, + .__st_mtim32.tv_sec = stx.stx_mtime.tv_sec, + .__st_mtim32.tv_nsec = stx.stx_mtime.tv_nsec, + .__st_ctim32.tv_sec = stx.stx_ctime.tv_sec, + .__st_ctim32.tv_nsec = stx.stx_ctime.tv_nsec, +#endif }; return ret; diff --git a/libc/sysdeps/linux/common/gettimeofday.c b/libc/sysdeps/linux/common/gettimeofday.c index d9cf3bb84..ed18b2be5 100755 --- a/libc/sysdeps/linux/common/gettimeofday.c +++ b/libc/sysdeps/linux/common/gettimeofday.c @@ -8,12 +8,12 @@ #include #include +#include #ifdef __VDSO_SUPPORT__ #include "ldso.h" #endif - #ifdef __VDSO_SUPPORT__ typedef int (*gettimeofday_func)(struct timeval * tv, __timezone_ptr_t tz); #endif @@ -29,7 +29,14 @@ int gettimeofday(struct timeval * tv, __timezone_ptr_t tz) { _syscall2_body(int, gettimeofday, struct timeval *, tv, __timezone_ptr_t, tz) } #else - _syscall2_body(int, gettimeofday, struct timeval *, tv, __timezone_ptr_t, tz) + if (!tv) + return 0; + + struct timespec __ts; + int __ret = clock_gettime(CLOCK_REALTIME, &__ts); + tv->tv_sec = __ts.tv_sec; + tv->tv_usec = (suseconds_t)__ts.tv_nsec / 1000; + return __ret; #endif } diff --git a/libc/sysdeps/linux/common/nanosleep.c b/libc/sysdeps/linux/common/nanosleep.c index 4463e108a..2b59fefef 100644 --- a/libc/sysdeps/linux/common/nanosleep.c +++ b/libc/sysdeps/linux/common/nanosleep.c @@ -10,11 +10,21 @@ #include #include -#define __NR___nanosleep_nocancel __NR_nanosleep -static _syscall2(int, __NC(nanosleep), const struct timespec *, req, - struct timespec *, rem); + +int _NC(nanosleep)(const struct timespec *req, struct timespec *rem) +{ + int __ret = clock_nanosleep(CLOCK_REALTIME, 0, req, rem); + + if (__ret != 0) { + __set_errno(__ret); + return -1; + } + + return __ret; +}; CANCELLABLE_SYSCALL(int, nanosleep, (const struct timespec *req, struct timespec *rem), (req, rem)) + lt_libc_hidden(nanosleep) diff --git a/libc/sysdeps/linux/common/ppoll.c b/libc/sysdeps/linux/common/ppoll.c index 781f1ff1c..cb36149c5 100644 --- a/libc/sysdeps/linux/common/ppoll.c +++ b/libc/sysdeps/linux/common/ppoll.c @@ -18,7 +18,7 @@ #include -#if defined __NR_ppoll && defined __UCLIBC_LINUX_SPECIFIC__ && defined __USE_GNU +#if (defined __NR_ppoll || defined(__NR_ppoll_time64)) && defined __UCLIBC_LINUX_SPECIFIC__ && defined __USE_GNU #define __need_NULL #include @@ -37,11 +37,14 @@ __NC(ppoll)(struct pollfd *fds, nfds_t nfds, const struct timespec *timeout, tval = *timeout; timeout = &tval; } +#if defined(__UCLIBC_USE_TIME64__) && defined(__NR_ppoll_time64) + return INLINE_SYSCALL(ppoll_time64, 5, fds, nfds, timeout, sigmask, __SYSCALL_SIGSET_T_SIZE); +#else return INLINE_SYSCALL(ppoll, 5, fds, nfds, timeout, sigmask, __SYSCALL_SIGSET_T_SIZE); +#endif } CANCELLABLE_SYSCALL(int, ppoll, (struct pollfd *fds, nfds_t nfds, const struct timespec *timeout, const sigset_t *sigmask), (fds, nfds, timeout, sigmask)) - #endif diff --git a/libc/sysdeps/linux/common/pselect.c b/libc/sysdeps/linux/common/pselect.c index bf2c08375..23bdab5cf 100644 --- a/libc/sysdeps/linux/common/pselect.c +++ b/libc/sysdeps/linux/common/pselect.c @@ -56,8 +56,11 @@ static int __NC(pselect)(int nfds, fd_set *readfds, fd_set *writefds, sigmask = (void *)&data; } - +#if defined(__UCLIBC_USE_TIME64__) && defined(__NR_pselect6_time64) + return INLINE_SYSCALL(pselect6_time64, 6, nfds, readfds, writefds, exceptfds, timeout, sigmask); +#else return INLINE_SYSCALL(pselect6, 6, nfds, readfds, writefds, exceptfds, timeout, sigmask); +#endif #else struct timeval tval; int retval; @@ -88,6 +91,7 @@ static int __NC(pselect)(int nfds, fd_set *readfds, fd_set *writefds, return retval; #endif } + CANCELLABLE_SYSCALL(int, pselect, (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, const struct timespec *timeout, const sigset_t *sigmask), (nfds, readfds, writefds, exceptfds, timeout, sigmask)) diff --git a/libc/sysdeps/linux/common/sched_rr_get_interval.c b/libc/sysdeps/linux/common/sched_rr_get_interval.c index 7a7de2bc5..c9be134cb 100644 --- a/libc/sysdeps/linux/common/sched_rr_get_interval.c +++ b/libc/sysdeps/linux/common/sched_rr_get_interval.c @@ -10,7 +10,12 @@ #include #include +#if defined(__UCLIBC_USE_TIME64__) && defined(__NR_sched_rr_get_interval_time64) +#define __NR___syscall_sched_rr_get_interval __NR_sched_rr_get_interval_time64 +#else #define __NR___syscall_sched_rr_get_interval __NR_sched_rr_get_interval +#endif + static __inline__ _syscall2(int, __syscall_sched_rr_get_interval, __kernel_pid_t, pid, struct timespec *, tp) diff --git a/libc/sysdeps/linux/common/setitimer.c b/libc/sysdeps/linux/common/setitimer.c index 2febabbc8..eab541329 100644 --- a/libc/sysdeps/linux/common/setitimer.c +++ b/libc/sysdeps/linux/common/setitimer.c @@ -10,6 +10,38 @@ #include +#if defined(__UCLIBC_USE_TIME64__) + +struct itimerval32_struct { + __S32_TYPE __interval_sec; + __S32_TYPE __interval_usec; + __S32_TYPE __value_sec; + __S32_TYPE __value_usec; +}; + +int setitimer(__itimer_which_t which, const struct itimerval *restrict new, struct itimerval *restrict old) +{ + struct itimerval32_struct __itv32 = { + .__interval_sec = new->it_interval.tv_sec, + .__interval_usec = new->it_interval.tv_usec, + .__value_sec = new->it_value.tv_sec, + .__value_usec = new->it_value.tv_usec + }; + struct itimerval32_struct __itv32_old; + + int __ret = INLINE_SYSCALL(setitimer, 3, which, &__itv32, &__itv32_old); + if (__ret == 0 && old) { + old->it_interval.tv_sec = __itv32_old.__interval_sec; + old->it_interval.tv_usec = __itv32_old.__interval_usec; + old->it_value.tv_sec = __itv32_old.__value_sec; + old->it_value.tv_usec = __itv32_old.__value_usec; + } + + return __ret; +} +#else _syscall3(int, setitimer, __itimer_which_t, which, const struct itimerval *, new, struct itimerval *, old) + +#endif libc_hidden_def(setitimer) diff --git a/libc/sysdeps/linux/common/settimeofday.c b/libc/sysdeps/linux/common/settimeofday.c index 14a261794..75d18ffc2 100644 --- a/libc/sysdeps/linux/common/settimeofday.c +++ b/libc/sysdeps/linux/common/settimeofday.c @@ -10,9 +10,21 @@ #ifdef __USE_BSD # include -# ifdef __NR_settimeofday -_syscall2(int, settimeofday, const struct timeval *, tv, - const struct timezone *, tz) +# include + +int settimeofday(const struct timeval *tv, const struct timezone *tz) +{ + if (!tv) + return 0; + + struct timespec __ts = { + .tv_sec = tv->tv_sec, + .tv_nsec = tv->tv_usec * 1000 + }; + + return clock_settime(CLOCK_REALTIME, &__ts); +} + # elif defined __USE_SVID && defined __NR_stime # define __need_NULL # include @@ -36,7 +48,6 @@ int settimeofday(const struct timeval *tv, const struct timezone *tz) return stime(&when); } # endif -# if defined __NR_settimeofday || (defined __USE_SVID && defined __NR_stime) +# if defined __NR_settimeofday || defined(__UCLIBC_USE_TIME64__) || (defined __USE_SVID && defined __NR_stime) libc_hidden_def(settimeofday) # endif -#endif diff --git a/libc/sysdeps/linux/common/timerfd.c b/libc/sysdeps/linux/common/timerfd.c index f4854ac90..0f19b44ed 100644 --- a/libc/sysdeps/linux/common/timerfd.c +++ b/libc/sysdeps/linux/common/timerfd.c @@ -19,13 +19,21 @@ _syscall2(int, timerfd_create, int, clockid, int, flags) /* * timerfd_settime() */ -#ifdef __NR_timerfd_settime -_syscall4(int,timerfd_settime, int, ufd, int, flags, const struct itimerspec *, utmr, struct itimerspec *, otmr) +#if defined(__NR_timerfd_settime) || defined(__NR_timerfd_settime64) +#if defined(__UCLIBC_USE_TIME64__) && defined(__NR_timerfd_settime64) +_syscall4_64(int, timerfd_settime, int, ufd, int, flags, const struct itimerspec *, utmr, struct itimerspec *, otmr) +#else +_syscall4(int, timerfd_settime, int, ufd, int, flags, const struct itimerspec *, utmr, struct itimerspec *, otmr) +#endif #endif /* * timerfd_gettime() */ -#ifdef __NR_timerfd_gettime +#if defined(__NR_timerfd_gettime) || defined(__NR_timerfd_gettime64) +#if defined(__UCLIBC_USE_TIME64__) && defined(__NR_timerfd_gettime64) +_syscall2_64(int, timerfd_gettime, int, ufd, struct itimerspec *, otmr) +#else _syscall2(int, timerfd_gettime, int, ufd, struct itimerspec *, otmr) #endif +#endif diff --git a/libc/sysdeps/linux/common/utimensat.c b/libc/sysdeps/linux/common/utimensat.c index 2cfb8247d..6a78ebb4f 100644 --- a/libc/sysdeps/linux/common/utimensat.c +++ b/libc/sysdeps/linux/common/utimensat.c @@ -9,8 +9,12 @@ #include #include -#ifdef __NR_utimensat +#if defined(__NR_utimensat) || defined(__NR_utimensat_time64) +#if defined(__UCLIBC_USE_TIME64__) && defined(__NR_utimensat_time64) +_syscall4_time64(int, utimensat, int, fd, const char *, path, const struct timespec *, times, int, flags) +#else _syscall4(int, utimensat, int, fd, const char *, path, const struct timespec *, times, int, flags) +#endif libc_hidden_def(utimensat) #else /* should add emulation with utimens() and /proc/self/fd/ ... */ diff --git a/libc/sysdeps/linux/common/wait4.c b/libc/sysdeps/linux/common/wait4.c index 19f02ae22..cd042d5e7 100644 --- a/libc/sysdeps/linux/common/wait4.c +++ b/libc/sysdeps/linux/common/wait4.c @@ -8,6 +8,7 @@ #include #include +#include # define __NR___syscall_wait4 __NR_wait4 static __always_inline _syscall4(int, __syscall_wait4, __kernel_pid_t, pid, @@ -15,7 +16,21 @@ static __always_inline _syscall4(int, __syscall_wait4, __kernel_pid_t, pid, pid_t __wait4_nocancel(pid_t pid, int *status, int opts, struct rusage *rusage) { +#if defined(__UCLIBC_USE_TIME64__) + char *arg_rusage = rusage ? (char *)&rusage->ru_maxrss - 4 * sizeof(__S32_TYPE) : 0; + int __ret = __syscall_wait4(pid, status, opts, (struct rusage *)arg_rusage); + if (__ret > 0 && rusage) { + __S32_TYPE __rusage[4]; + memcpy(__rusage, arg_rusage, 4 * sizeof(__S32_TYPE)); + struct timeval tv_utime = {.tv_sec = __rusage[0], .tv_usec = __rusage[1]}; + struct timeval tv_stime = {.tv_sec = __rusage[2], .tv_usec = __rusage[2]}; + rusage->ru_utime = tv_utime; + rusage->ru_stime = tv_stime; + } + return __ret; +#else return __syscall_wait4(pid, status, opts, rusage); +#endif } #ifdef __USE_BSD strong_alias(__wait4_nocancel,wait4) diff --git a/libc/sysdeps/linux/common/xstatconv.c b/libc/sysdeps/linux/common/xstatconv.c index d50fbf9c3..4b0a7424e 100644 --- a/libc/sysdeps/linux/common/xstatconv.c +++ b/libc/sysdeps/linux/common/xstatconv.c @@ -37,12 +37,21 @@ void __xstat_conv(struct kernel_stat *kbuf, struct stat *buf) buf->st_size = kbuf->st_size; buf->st_blksize = kbuf->st_blksize; buf->st_blocks = kbuf->st_blocks; +#if defined(__UCLIBC_USE_TIME64__) + buf->st_atim.tv_sec = kbuf->__st_atim32.tv_sec; + buf->st_atim.tv_nsec = kbuf->__st_atim32.tv_nsec; + buf->st_mtim.tv_sec = kbuf->__st_mtim32.tv_sec; + buf->st_mtim.tv_nsec = kbuf->__st_mtim32.tv_nsec; + buf->st_ctim.tv_sec = kbuf->__st_ctim32.tv_sec; + buf->st_ctim.tv_nsec = kbuf->__st_ctim32.tv_nsec; +#else buf->st_atim.tv_sec = kbuf->st_atim.tv_sec; buf->st_atim.tv_nsec = kbuf->st_atim.tv_nsec; buf->st_mtim.tv_sec = kbuf->st_mtim.tv_sec; buf->st_mtim.tv_nsec = kbuf->st_mtim.tv_nsec; buf->st_ctim.tv_sec = kbuf->st_ctim.tv_sec; buf->st_ctim.tv_nsec = kbuf->st_ctim.tv_nsec; +#endif } void __xstat32_conv(struct kernel_stat64 *kbuf, struct stat *buf) @@ -59,12 +68,21 @@ void __xstat32_conv(struct kernel_stat64 *kbuf, struct stat *buf) buf->st_size = kbuf->st_size; buf->st_blksize = kbuf->st_blksize; buf->st_blocks = kbuf->st_blocks; +#if defined(__UCLIBC_USE_TIME64__) + buf->st_atim.tv_sec = kbuf->__st_atim32.tv_sec; + buf->st_atim.tv_nsec = kbuf->__st_atim32.tv_nsec; + buf->st_mtim.tv_sec = kbuf->__st_mtim32.tv_sec; + buf->st_mtim.tv_nsec = kbuf->__st_mtim32.tv_nsec; + buf->st_ctim.tv_sec = kbuf->__st_ctim32.tv_sec; + buf->st_ctim.tv_nsec = kbuf->__st_ctim32.tv_nsec; +#else buf->st_atim.tv_sec = kbuf->st_atim.tv_sec; buf->st_atim.tv_nsec = kbuf->st_atim.tv_nsec; buf->st_mtim.tv_sec = kbuf->st_mtim.tv_sec; buf->st_mtim.tv_nsec = kbuf->st_mtim.tv_nsec; buf->st_ctim.tv_sec = kbuf->st_ctim.tv_sec; buf->st_ctim.tv_nsec = kbuf->st_ctim.tv_nsec; +#endif } void __xstat64_conv(struct kernel_stat64 *kbuf, struct stat64 *buf) @@ -84,10 +102,19 @@ void __xstat64_conv(struct kernel_stat64 *kbuf, struct stat64 *buf) buf->st_size = kbuf->st_size; buf->st_blksize = kbuf->st_blksize; buf->st_blocks = kbuf->st_blocks; +#if defined(__UCLIBC_USE_TIME64__) + buf->st_atim.tv_sec = kbuf->__st_atim32.tv_sec; + buf->st_atim.tv_nsec = kbuf->__st_atim32.tv_nsec; + buf->st_mtim.tv_sec = kbuf->__st_mtim32.tv_sec; + buf->st_mtim.tv_nsec = kbuf->__st_mtim32.tv_nsec; + buf->st_ctim.tv_sec = kbuf->__st_ctim32.tv_sec; + buf->st_ctim.tv_nsec = kbuf->__st_ctim32.tv_nsec; +#else buf->st_atim.tv_sec = kbuf->st_atim.tv_sec; buf->st_atim.tv_nsec = kbuf->st_atim.tv_nsec; buf->st_mtim.tv_sec = kbuf->st_mtim.tv_sec; buf->st_mtim.tv_nsec = kbuf->st_mtim.tv_nsec; buf->st_ctim.tv_sec = kbuf->st_ctim.tv_sec; buf->st_ctim.tv_nsec = kbuf->st_ctim.tv_nsec; +#endif } -- cgit v1.2.3