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 --- .../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 ++ 5 files changed, 80 insertions(+), 4 deletions(-) (limited to 'libpthread/nptl/sysdeps/unix/sysv/linux') 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) -- cgit v1.2.3