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 --- extra/Configs/Config.in | 9 ++++ 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 ++++++++++ libpthread/linuxthreads/condvar.c | 4 ++ libpthread/nptl/init.c | 13 +++++ libpthread/nptl/pthread_condattr_setclock.c | 6 ++- libpthread/nptl/pthread_mutex_init.c | 5 ++ libpthread/nptl/pthread_mutex_lock.c | 13 +++++ libpthread/nptl/pthread_mutex_timedlock.c | 19 +++++++ libpthread/nptl/pthread_mutex_trylock.c | 13 +++++ libpthread/nptl/pthread_mutex_unlock.c | 5 ++ .../nptl/sysdeps/pthread/pthread_cond_timedwait.c | 8 +++ .../nptl/sysdeps/unix/sysv/linux/lowlevellock.h | 58 +++++++++++++++++++++- .../nptl/sysdeps/unix/sysv/linux/nanosleep.c | 12 +++-- .../nptl/sysdeps/unix/sysv/linux/timer_create.c | 5 ++ .../nptl/sysdeps/unix/sysv/linux/timer_gettime.c | 4 ++ .../nptl/sysdeps/unix/sysv/linux/timer_settime.c | 5 ++ librt/clock_getcpuclockid.c | 15 +++++- librt/clock_gettime.c | 7 ++- librt/clock_nanosleep.c | 10 +++- librt/mq_timedreceive.c | 6 +++ librt/mq_timedsend.c | 6 ++- librt/timer_gettime.c | 6 ++- librt/timer_settime.c | 7 ++- 47 files changed, 519 insertions(+), 47 deletions(-) diff --git a/extra/Configs/Config.in b/extra/Configs/Config.in index 18748d54b..831b9f689 100644 --- a/extra/Configs/Config.in +++ b/extra/Configs/Config.in @@ -1024,6 +1024,15 @@ config UCLIBC_FALLBACK_TO_ETC_LOCALTIME Most people will answer Y. +config UCLIBC_USE_TIME64 + bool "Use *time64 syscalls instead of 32bit ones (if possible)" + depends on TARGET_arm + # TODO: add support for other architectures + default n + + help + Replace 32bit syscalls to their 64/time64 analog if possible. + endmenu menu "Advanced Library Settings" 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 } diff --git a/libpthread/linuxthreads/condvar.c b/libpthread/linuxthreads/condvar.c index 6ac1622da..949991ad7 100644 --- a/libpthread/linuxthreads/condvar.c +++ b/libpthread/linuxthreads/condvar.c @@ -328,7 +328,11 @@ int pthread_condattr_setclock (pthread_condattr_t *attr, clockid_t clock_id) INTERNAL_SYSCALL_DECL (err); int val; +#if defined(__UCLIBC_USE_TIME64__) && defined(__NR_clock_getres_time64) + val = INTERNAL_SYSCALL (clock_getres_time64, err, 2, CLOCK_MONOTONIC, &ts); +#else val = INTERNAL_SYSCALL (clock_getres, err, 2, CLOCK_MONOTONIC, &ts); +#endif avail = INTERNAL_SYSCALL_ERROR_P (val, err) ? -1 : 1; } diff --git a/libpthread/nptl/init.c b/libpthread/nptl/init.c index ddc552f2e..a6c0ec6af 100644 --- a/libpthread/nptl/init.c +++ b/libpthread/nptl/init.c @@ -195,8 +195,14 @@ __pthread_initialize_minimal_internal (void) doing the test once this early is beneficial. */ { int word = 0; +#if defined(__UCLIBC_USE_TIME64__) && defined(__NR_futex_time64) + word = INTERNAL_SYSCALL (futex_time64, err, 3, &word, + FUTEX_WAKE | FUTEX_PRIVATE_FLAG, 1); +#else word = INTERNAL_SYSCALL (futex, err, 3, &word, FUTEX_WAKE | FUTEX_PRIVATE_FLAG, 1); +#endif + if (!INTERNAL_SYSCALL_ERROR_P (word, err)) THREAD_SETMEM (pd, header.private_futex, FUTEX_PRIVATE_FLAG); } @@ -215,9 +221,16 @@ __pthread_initialize_minimal_internal (void) is irrelevant. Given that passing six parameters is difficult on some architectures we just pass whatever random value the calling convention calls for to the kernel. It causes no harm. */ +#if defined(__UCLIBC_USE_TIME64__) && defined(__NR_futex_time64) + word = INTERNAL_SYSCALL (futex_time64, err, 5, &word, + FUTEX_WAIT_BITSET | FUTEX_CLOCK_REALTIME + | FUTEX_PRIVATE_FLAG, 1, NULL, 0); +#else word = INTERNAL_SYSCALL (futex, err, 5, &word, FUTEX_WAIT_BITSET | FUTEX_CLOCK_REALTIME | FUTEX_PRIVATE_FLAG, 1, NULL, 0); +#endif + assert (INTERNAL_SYSCALL_ERROR_P (word, err)); if (INTERNAL_SYSCALL_ERRNO (word, err) != ENOSYS) __set_futex_clock_realtime (); diff --git a/libpthread/nptl/pthread_condattr_setclock.c b/libpthread/nptl/pthread_condattr_setclock.c index b2f4aaf29..e7f3539d6 100644 --- a/libpthread/nptl/pthread_condattr_setclock.c +++ b/libpthread/nptl/pthread_condattr_setclock.c @@ -35,7 +35,7 @@ pthread_condattr_setclock ( if (clock_id == CLOCK_MONOTONIC) { #ifndef __ASSUME_POSIX_TIMERS -# ifdef __NR_clock_getres +# if defined(__NR_clock_getres) || defined(__NR_clock_getres_time64) /* Check whether the clock is available. */ static int avail; @@ -45,7 +45,11 @@ pthread_condattr_setclock ( INTERNAL_SYSCALL_DECL (err); int val; +#if defined(__UCLIBC_USE_TIME64__) && defined(__NR_clock_getres_time64) + val = INTERNAL_SYSCALL (clock_getres_time64, err, 2, CLOCK_MONOTONIC, &ts); +#else val = INTERNAL_SYSCALL (clock_getres, err, 2, CLOCK_MONOTONIC, &ts); +#endif avail = INTERNAL_SYSCALL_ERROR_P (val, err) ? -1 : 1; } diff --git a/libpthread/nptl/pthread_mutex_init.c b/libpthread/nptl/pthread_mutex_init.c index bf4c4d151..ba5c916eb 100644 --- a/libpthread/nptl/pthread_mutex_init.c +++ b/libpthread/nptl/pthread_mutex_init.c @@ -62,8 +62,13 @@ __pthread_mutex_init ( { int lock = 0; INTERNAL_SYSCALL_DECL (err); +#if defined(__UCLIBC_USE_TIME64__) && defined(__NR_futex_time64) + int ret = INTERNAL_SYSCALL (futex_time64, err, 4, &lock, FUTEX_UNLOCK_PI, + 0, 0); +#else int ret = INTERNAL_SYSCALL (futex, err, 4, &lock, FUTEX_UNLOCK_PI, 0, 0); +#endif assert (INTERNAL_SYSCALL_ERROR_P (ret, err)); tpi_supported = INTERNAL_SYSCALL_ERRNO (ret, err) == ENOSYS ? -1 : 1; } diff --git a/libpthread/nptl/pthread_mutex_lock.c b/libpthread/nptl/pthread_mutex_lock.c index 8353e8cd3..6e98a9760 100644 --- a/libpthread/nptl/pthread_mutex_lock.c +++ b/libpthread/nptl/pthread_mutex_lock.c @@ -300,9 +300,15 @@ __pthread_mutex_lock_full (pthread_mutex_t *mutex) ? PTHREAD_ROBUST_MUTEX_PSHARED (mutex) : PTHREAD_MUTEX_PSHARED (mutex)); INTERNAL_SYSCALL_DECL (__err); +#if defined(__UCLIBC_USE_TIME64__) && defined(__NR_futex_time64) + int e = INTERNAL_SYSCALL (futex_time64, __err, 4, &mutex->__data.__lock, + __lll_private_flag (FUTEX_LOCK_PI, + private), 1, 0); +#else int e = INTERNAL_SYSCALL (futex, __err, 4, &mutex->__data.__lock, __lll_private_flag (FUTEX_LOCK_PI, private), 1, 0); +#endif if (INTERNAL_SYSCALL_ERROR_P (e, __err) && (INTERNAL_SYSCALL_ERRNO (e, __err) == ESRCH @@ -357,10 +363,17 @@ __pthread_mutex_lock_full (pthread_mutex_t *mutex) mutex->__data.__count = 0; INTERNAL_SYSCALL_DECL (__err); +#if defined(__UCLIBC_USE_TIME64__) && defined(__NR_futex_time64) + INTERNAL_SYSCALL (futex_time64, __err, 4, &mutex->__data.__lock, + __lll_private_flag (FUTEX_UNLOCK_PI, + PTHREAD_ROBUST_MUTEX_PSHARED (mutex)), + 0, 0); +#else INTERNAL_SYSCALL (futex, __err, 4, &mutex->__data.__lock, __lll_private_flag (FUTEX_UNLOCK_PI, PTHREAD_ROBUST_MUTEX_PSHARED (mutex)), 0, 0); +#endif THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); return ENOTRECOVERABLE; diff --git a/libpthread/nptl/pthread_mutex_timedlock.c b/libpthread/nptl/pthread_mutex_timedlock.c index f56f6c55e..25f9ec3b2 100644 --- a/libpthread/nptl/pthread_mutex_timedlock.c +++ b/libpthread/nptl/pthread_mutex_timedlock.c @@ -264,10 +264,17 @@ pthread_mutex_timedlock ( : PTHREAD_MUTEX_PSHARED (mutex)); INTERNAL_SYSCALL_DECL (__err); +#if defined(__UCLIBC_USE_TIME64__) && defined(__NR_futex_time64) + int e = INTERNAL_SYSCALL (futex_time64, __err, 4, &mutex->__data.__lock, + __lll_private_flag (FUTEX_LOCK_PI, + private), 1, + abstime); +#else int e = INTERNAL_SYSCALL (futex, __err, 4, &mutex->__data.__lock, __lll_private_flag (FUTEX_LOCK_PI, private), 1, abstime); +#endif if (INTERNAL_SYSCALL_ERROR_P (e, __err)) { if (INTERNAL_SYSCALL_ERRNO (e, __err) == ETIMEDOUT) @@ -289,8 +296,13 @@ pthread_mutex_timedlock ( struct timespec reltime; struct timespec now; +#if defined(__UCLIBC_USE_TIME64__) && defined(__NR_clock_gettime64) + INTERNAL_SYSCALL (clock_gettime64, __err, 2, CLOCK_REALTIME, + &now); +#else INTERNAL_SYSCALL (clock_gettime, __err, 2, CLOCK_REALTIME, &now); +#endif reltime.tv_sec = abstime->tv_sec - now.tv_sec; reltime.tv_nsec = abstime->tv_nsec - now.tv_nsec; if (reltime.tv_nsec < 0) @@ -340,10 +352,17 @@ pthread_mutex_timedlock ( mutex->__data.__count = 0; INTERNAL_SYSCALL_DECL (__err); +#if defined(__UCLIBC_USE_TIME64__) && defined(__NR_futex_time64) + INTERNAL_SYSCALL (futex_time64, __err, 4, &mutex->__data.__lock, + __lll_private_flag (FUTEX_UNLOCK_PI, + PTHREAD_ROBUST_MUTEX_PSHARED (mutex)), + 0, 0); +#else INTERNAL_SYSCALL (futex, __err, 4, &mutex->__data.__lock, __lll_private_flag (FUTEX_UNLOCK_PI, PTHREAD_ROBUST_MUTEX_PSHARED (mutex)), 0, 0); +#endif THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); return ENOTRECOVERABLE; diff --git a/libpthread/nptl/pthread_mutex_trylock.c b/libpthread/nptl/pthread_mutex_trylock.c index e0d54bda7..ca02109ee 100644 --- a/libpthread/nptl/pthread_mutex_trylock.c +++ b/libpthread/nptl/pthread_mutex_trylock.c @@ -234,9 +234,15 @@ __pthread_mutex_trylock ( ? PTHREAD_ROBUST_MUTEX_PSHARED (mutex) : PTHREAD_MUTEX_PSHARED (mutex)); INTERNAL_SYSCALL_DECL (__err); +#if defined(__UCLIBC_USE_TIME64__) && defined(__NR_futex_time64) + int e = INTERNAL_SYSCALL (futex_time64, __err, 4, &mutex->__data.__lock, + __lll_private_flag (FUTEX_TRYLOCK_PI, + private), 0, 0); +#else int e = INTERNAL_SYSCALL (futex, __err, 4, &mutex->__data.__lock, __lll_private_flag (FUTEX_TRYLOCK_PI, private), 0, 0); +#endif if (INTERNAL_SYSCALL_ERROR_P (e, __err) && INTERNAL_SYSCALL_ERRNO (e, __err) == EWOULDBLOCK) @@ -276,10 +282,17 @@ __pthread_mutex_trylock ( mutex->__data.__count = 0; INTERNAL_SYSCALL_DECL (__err); +#if defined(__UCLIBC_USE_TIME64__) && defined(__NR_futex_time64) + INTERNAL_SYSCALL (futex_time64, __err, 4, &mutex->__data.__lock, + __lll_private_flag (FUTEX_UNLOCK_PI, + PTHREAD_ROBUST_MUTEX_PSHARED (mutex)), + 0, 0); +#else INTERNAL_SYSCALL (futex, __err, 4, &mutex->__data.__lock, __lll_private_flag (FUTEX_UNLOCK_PI, PTHREAD_ROBUST_MUTEX_PSHARED (mutex)), 0, 0); +#endif THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); return ENOTRECOVERABLE; diff --git a/libpthread/nptl/pthread_mutex_unlock.c b/libpthread/nptl/pthread_mutex_unlock.c index 1123e3c42..6f3ed8c44 100644 --- a/libpthread/nptl/pthread_mutex_unlock.c +++ b/libpthread/nptl/pthread_mutex_unlock.c @@ -222,8 +222,13 @@ __pthread_mutex_unlock_full (pthread_mutex_t *mutex, int decr) ? PTHREAD_ROBUST_MUTEX_PSHARED (mutex) : PTHREAD_MUTEX_PSHARED (mutex)); INTERNAL_SYSCALL_DECL (__err); +#if defined(__UCLIBC_USE_TIME64__) && defined(__NR_futex_time64) + INTERNAL_SYSCALL (futex_time64, __err, 2, &mutex->__data.__lock, + __lll_private_flag (FUTEX_UNLOCK_PI, private)); +#else INTERNAL_SYSCALL (futex, __err, 2, &mutex->__data.__lock, __lll_private_flag (FUTEX_UNLOCK_PI, private)); +#endif } THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); diff --git a/libpthread/nptl/sysdeps/pthread/pthread_cond_timedwait.c b/libpthread/nptl/sysdeps/pthread/pthread_cond_timedwait.c index f06b69e2f..49aab0293 100644 --- a/libpthread/nptl/sysdeps/pthread/pthread_cond_timedwait.c +++ b/libpthread/nptl/sysdeps/pthread/pthread_cond_timedwait.c @@ -102,10 +102,18 @@ __pthread_cond_timedwait ( # ifndef __ASSUME_POSIX_TIMERS int ret = # endif +#if defined(__UCLIBC_USE_TIME64__) && defined(__NR_clock_gettime64) + INTERNAL_SYSCALL (clock_gettime64, err, 2, + (cond->__data.__nwaiters + & ((1 << COND_NWAITERS_SHIFT) - 1)), + &rt); +#else INTERNAL_SYSCALL (clock_gettime, err, 2, (cond->__data.__nwaiters & ((1 << COND_NWAITERS_SHIFT) - 1)), &rt); +#endif + # ifndef __ASSUME_POSIX_TIMERS if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (ret, err), 0)) { diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevellock.h b/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevellock.h index b5b0afdf8..e72fe5234 100644 --- a/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevellock.h +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevellock.h @@ -71,10 +71,33 @@ # endif #endif - #define lll_futex_wait(futexp, val, private) \ lll_futex_timed_wait(futexp, val, NULL, private) +#if defined(__UCLIBC_USE_TIME64__) && defined(__NR_futex_time64) + +#define lll_futex_timed_wait(futexp, val, timespec, private) \ + ({ \ + INTERNAL_SYSCALL_DECL (__err); \ + long int __ret; \ + __ret = INTERNAL_SYSCALL (futex_time64, __err, 4, (futexp), \ + __lll_private_flag (FUTEX_WAIT, private), \ + (val), (timespec)); \ + __ret; \ + }) + +#define lll_futex_wake(futexp, nr, private) \ + ({ \ + INTERNAL_SYSCALL_DECL (__err); \ + long int __ret; \ + __ret = INTERNAL_SYSCALL (futex_time64, __err, 4, (futexp), \ + __lll_private_flag (FUTEX_WAKE, private), \ + (nr), 0); \ + __ret; \ + }) + +#else + #define lll_futex_timed_wait(futexp, val, timespec, private) \ ({ \ INTERNAL_SYSCALL_DECL (__err); \ @@ -95,6 +118,8 @@ __ret; \ }) +#endif + #define lll_robust_dead(futexv, private) \ do \ { \ @@ -105,6 +130,35 @@ while (0) /* Returns non-zero if error happened, zero if success. */ + +#if defined(__UCLIBC_USE_TIME64__) && defined(__NR_futex_time64) + +#define lll_futex_requeue(futexp, nr_wake, nr_move, mutex, val, private) \ + ({ \ + INTERNAL_SYSCALL_DECL (__err); \ + long int __ret; \ + __ret = INTERNAL_SYSCALL (futex_time64, __err, 6, (futexp), \ + __lll_private_flag (FUTEX_CMP_REQUEUE, private),\ + (nr_wake), (nr_move), (mutex), (val)); \ + INTERNAL_SYSCALL_ERROR_P (__ret, __err); \ + }) + + +/* Returns non-zero if error happened, zero if success. */ +#define lll_futex_wake_unlock(futexp, nr_wake, nr_wake2, futexp2, private) \ + ({ \ + INTERNAL_SYSCALL_DECL (__err); \ + long int __ret; \ + __ret = INTERNAL_SYSCALL (futex_time64, __err, 6, (futexp), \ + __lll_private_flag (FUTEX_WAKE_OP, private), \ + (nr_wake), (nr_wake2), (futexp2), \ + FUTEX_OP_CLEAR_WAKE_IF_GT_ONE); \ + INTERNAL_SYSCALL_ERROR_P (__ret, __err); \ + }) + +#else + + #define lll_futex_requeue(futexp, nr_wake, nr_move, mutex, val, private) \ ({ \ INTERNAL_SYSCALL_DECL (__err); \ @@ -128,6 +182,8 @@ INTERNAL_SYSCALL_ERROR_P (__ret, __err); \ }) +#endif + #define lll_trylock(lock) \ atomic_compare_and_exchange_val_acq(&(lock), 1, 0) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/nanosleep.c b/libpthread/nptl/sysdeps/unix/sysv/linux/nanosleep.c index 73fae44bc..9c7230934 100644 --- a/libpthread/nptl/sysdeps/unix/sysv/linux/nanosleep.c +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/nanosleep.c @@ -8,11 +8,17 @@ /* Pause execution for a number of nanoseconds. */ int -nanosleep (const struct timespec *requested_time, +_NC(nanosleep) (const struct timespec *requested_time, struct timespec *remaining) { - return _syscall2(int, __NC(nanosleep), const struct timespec*, - requested_time, struct timespec* remaining) + int __ret = clock_nanosleep(CLOCK_REALTIME, 0, requested_time, remaining); + + if (__ret != 0) { + __set_errno(__ret); + return -1; + } + + return __ret; } CANCELLABLE_SYSCALL(int, nanosleep, (const struct timespec *requested_time, diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/timer_create.c b/libpthread/nptl/sysdeps/unix/sysv/linux/timer_create.c index 93e4e6070..cd8d2f84f 100644 --- a/libpthread/nptl/sysdeps/unix/sysv/linux/timer_create.c +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/timer_create.c @@ -140,8 +140,13 @@ timer_create ( INTERNAL_SYSCALL_DECL (err); struct timespec ts; int res; +#if defined(__UCLIBC_USE_TIME64__) && defined(__NR_clock_getres_time64) + res = INTERNAL_SYSCALL (clock_getres_time64, err, 2, + CLOCK_REALTIME, &ts); +#else res = INTERNAL_SYSCALL (clock_getres, err, 2, CLOCK_REALTIME, &ts); +#endif __no_posix_timers = (INTERNAL_SYSCALL_ERROR_P (res, err) ? -1 : 1); } diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/timer_gettime.c b/libpthread/nptl/sysdeps/unix/sysv/linux/timer_gettime.c index 699874f3f..220df0c37 100644 --- a/libpthread/nptl/sysdeps/unix/sysv/linux/timer_gettime.c +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/timer_gettime.c @@ -50,7 +50,11 @@ timer_gettime ( struct timer *kt = (struct timer *) timerid; /* Delete the kernel timer object. */ +# if defined(__UCLIBC_USE_TIME64__) && defined(__NR_timer_gettime64) + int res = INLINE_SYSCALL (timer_gettime64, 2, kt->ktimerid, value); +# else int res = INLINE_SYSCALL (timer_gettime, 2, kt->ktimerid, value); +# endif # ifndef __ASSUME_POSIX_TIMERS if (res != -1 || errno != ENOSYS) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/timer_settime.c b/libpthread/nptl/sysdeps/unix/sysv/linux/timer_settime.c index 81a0fa568..80d242f21 100644 --- a/libpthread/nptl/sysdeps/unix/sysv/linux/timer_settime.c +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/timer_settime.c @@ -54,8 +54,13 @@ timer_settime ( struct timer *kt = (struct timer *) timerid; /* Delete the kernel timer object. */ +# if defined(__UCLIBC_USE_TIME64__) && defined(__NR_timer_settime64) + int res = INLINE_SYSCALL (timer_settime64, 4, kt->ktimerid, flags, + value, ovalue); +# else int res = INLINE_SYSCALL (timer_settime, 4, kt->ktimerid, flags, value, ovalue); +# endif # ifndef __ASSUME_POSIX_TIMERS if (res != -1 || errno != ENOSYS) diff --git a/librt/clock_getcpuclockid.c b/librt/clock_getcpuclockid.c index b6142a78a..a402e56d7 100644 --- a/librt/clock_getcpuclockid.c +++ b/librt/clock_getcpuclockid.c @@ -30,7 +30,7 @@ int clock_getcpuclockid (pid_t pid, clockid_t *clock_id) { -#ifdef __NR_clock_getres +#if defined(__NR_clock_getres) || defined(__NR_clock_getres_time64) /* The clockid_t value is a simple computation from the PID. But we do a clock_getres call to validate it. */ @@ -47,7 +47,11 @@ clock_getcpuclockid (pid_t pid, clockid_t *clock_id) # endif { INTERNAL_SYSCALL_DECL (err); +# if defined(__UCLIBC_USE_TIME64__) && defined(__NR_clock_getres_time64) + int r = INTERNAL_SYSCALL (clock_getres_time64, err, 2, pidclock, NULL); +# else int r = INTERNAL_SYSCALL (clock_getres, err, 2, pidclock, NULL); +# endif if (!INTERNAL_SYSCALL_ERROR_P (r, err)) { *clock_id = pidclock; @@ -66,12 +70,21 @@ clock_getcpuclockid (pid_t pid, clockid_t *clock_id) if (INTERNAL_SYSCALL_ERRNO (r, err) == EINVAL) { # if !(__ASSUME_POSIX_CPU_TIMERS > 0) +# if defined(__UCLIBC_USE_TIME64__) && defined(__NR_clock_getres_time64) + if (pidclock == MAKE_PROCESS_CPUCLOCK (0, CPUCLOCK_SCHED) + || INTERNAL_SYSCALL_ERROR_P (INTERNAL_SYSCALL + (clock_getres_time64, err, 2, + MAKE_PROCESS_CPUCLOCK + (0, CPUCLOCK_SCHED), NULL), + err)) +# else if (pidclock == MAKE_PROCESS_CPUCLOCK (0, CPUCLOCK_SCHED) || INTERNAL_SYSCALL_ERROR_P (INTERNAL_SYSCALL (clock_getres, err, 2, MAKE_PROCESS_CPUCLOCK (0, CPUCLOCK_SCHED), NULL), err)) +# endif /* The kernel doesn't support these clocks at all. */ __libc_missing_posix_cpu_timers = 1; else diff --git a/librt/clock_gettime.c b/librt/clock_gettime.c index e65d39d44..b66b60231 100644 --- a/librt/clock_gettime.c +++ b/librt/clock_gettime.c @@ -22,10 +22,15 @@ #include #include "kernel-posix-cpu-timers.h" - +#if defined(__UCLIBC_USE_TIME64__) && defined(__NR_clock_gettime64) +#define SYSCALL_GETTIME \ + retval = INLINE_SYSCALL (clock_gettime64, 2, clock_id, tp); \ + break +#else #define SYSCALL_GETTIME \ retval = INLINE_SYSCALL (clock_gettime, 2, clock_id, tp); \ break +#endif /* The REALTIME and MONOTONIC clock are definitely supported in the kernel. */ #define SYSDEP_GETTIME \ diff --git a/librt/clock_nanosleep.c b/librt/clock_nanosleep.c index 85db72fb3..eaae75720 100644 --- a/librt/clock_nanosleep.c +++ b/librt/clock_nanosleep.c @@ -37,15 +37,21 @@ clock_nanosleep (clockid_t clock_id, int flags, const struct timespec *req, clock_id = MAKE_PROCESS_CPUCLOCK (0, CPUCLOCK_SCHED); if (SINGLE_THREAD_P) +#if defined(__UCLIBC_USE_TIME64__) && defined(__NR_clock_nanosleep_time64) + r = INTERNAL_SYSCALL (clock_nanosleep_time64, err, 4, clock_id, flags, req, rem); +#else r = INTERNAL_SYSCALL (clock_nanosleep, err, 4, clock_id, flags, req, rem); +#endif else { #ifdef __NEW_THREADS int oldstate = LIBC_CANCEL_ASYNC (); - +#if defined(__UCLIBC_USE_TIME64__) && defined(__NR_clock_nanosleep_time64) + r = INTERNAL_SYSCALL (clock_nanosleep_time64, err, 4, clock_id, flags, req, rem); +#else r = INTERNAL_SYSCALL (clock_nanosleep, err, 4, clock_id, flags, req, rem); - +#endif LIBC_CANCEL_RESET (oldstate); #endif } diff --git a/librt/mq_timedreceive.c b/librt/mq_timedreceive.c index 9f5efc4fa..db1ae1aa8 100644 --- a/librt/mq_timedreceive.c +++ b/librt/mq_timedreceive.c @@ -8,9 +8,15 @@ #include #include +#if defined(__UCLIBC_USE_TIME64__) && defined(__NR_mq_timedreceive_time64) +#define __NR___mq_timedreceive_nocancel __NR_mq_timedreceive_time64 +#else #define __NR___mq_timedreceive_nocancel __NR_mq_timedreceive +#endif + _syscall5(ssize_t, __NC(mq_timedreceive), mqd_t, mqdes, char *__restrict, msg_ptr, size_t, msg_len, unsigned int *__restrict, msq_prio, const struct timespec *__restrict, abs_timeout) CANCELLABLE_SYSCALL(ssize_t, mq_timedreceive, (mqd_t mqdes, char *__restrict msg_ptr, size_t msq_len, unsigned int *__restrict msq_prio, const struct timespec *__restrict abs_timeout), (mqdes, msg_ptr, msq_len, msq_prio, abs_timeout)) + lt_libc_hidden(mq_timedreceive) diff --git a/librt/mq_timedsend.c b/librt/mq_timedsend.c index 7c2e97ee3..6afaf5157 100644 --- a/librt/mq_timedsend.c +++ b/librt/mq_timedsend.c @@ -8,9 +8,13 @@ #include #include +#if defined(__UCLIBC_USE_TIME64__) && defined(__NR_mq_timedsend_time64) +#define __NR___mq_timedsend_nocancel __NR_mq_timedsend_time64 +#else #define __NR___mq_timedsend_nocancel __NR_mq_timedsend -_syscall5(int, __NC(mq_timedsend), mqd_t, mqdes, const char *, msg_ptr, size_t, msg_len, unsigned int, msq_prio, const struct timespec *, abs_timeout) +#endif +_syscall5(int, __NC(mq_timedsend), mqd_t, mqdes, const char *, msg_ptr, size_t, msg_len, unsigned int, msq_prio, const struct timespec *, abs_timeout) CANCELLABLE_SYSCALL(int, mq_timedsend, (mqd_t mqdes, const char *msg_ptr, size_t msq_len, unsigned int msq_prio, const struct timespec *abs_timeout), (mqdes, msg_ptr, msq_len, msq_prio, abs_timeout)) lt_libc_hidden(mq_timedsend) diff --git a/librt/timer_gettime.c b/librt/timer_gettime.c index e13f44642..9495c802d 100644 --- a/librt/timer_gettime.c +++ b/librt/timer_gettime.c @@ -9,9 +9,13 @@ #include "kernel-posix-timers.h" -#ifdef __NR_timer_gettime +#if defined(__NR_timer_gettime) || defined(__NR_timer_gettime64) +#if defined(__UCLIBC_USE_TIME64__) && defined(__NR_timer_gettime64) +#define __NR___syscall_timer_gettime __NR_timer_gettime64 +#else #define __NR___syscall_timer_gettime __NR_timer_gettime +#endif static __inline__ _syscall2(int, __syscall_timer_gettime, kernel_timer_t, ktimerid, void *, value); diff --git a/librt/timer_settime.c b/librt/timer_settime.c index 2703fa913..022880297 100644 --- a/librt/timer_settime.c +++ b/librt/timer_settime.c @@ -9,9 +9,14 @@ #include "kernel-posix-timers.h" -#ifdef __NR_timer_settime +#if defined(__NR_timer_settime) || defined(__NR_timer_settime64) +#if defined(__UCLIBC_USE_TIME64__) && defined(__NR_timer_settime64) +#define __NR___syscall_timer_settime __NR_timer_settime64 +#else #define __NR___syscall_timer_settime __NR_timer_settime +#endif + static __inline__ _syscall4(int, __syscall_timer_settime, kernel_timer_t, ktimerid, int, flags, const void *, value, void *, ovalue); -- cgit v1.2.3