From ceb2371ada673d258328a019691bff014ea3abca Mon Sep 17 00:00:00 2001 From: Martin Vajnar Date: Tue, 8 Jun 2021 23:36:11 +0200 Subject: [PATCH] store fallback paths for kernels without time64/statx syscalls --- src/ipc/semtimedop.c | 12 ++-- src/linux/clock_adjtime.c | 100 ++++++++++++++------------- src/linux/ppoll.c | 16 +++-- src/linux/timerfd.c | 28 +++++--- src/misc/getrusage.c | 28 ++++---- src/mq/mq_timedreceive.c | 14 ++-- src/mq/mq_timedsend.c | 14 ++-- src/network/recvmmsg.c | 13 ++-- src/select/pselect.c | 14 ++-- src/select/select.c | 16 +++-- src/signal/sigtimedwait.c | 14 ++-- src/stat/fstatat.c | 10 ++- src/stat/utimensat.c | 14 ++-- src/thread/__timedwait.c | 12 ++-- src/thread/pthread_mutex_timedlock.c | 12 ++-- src/time/clock_gettime.c | 12 ++-- src/time/clock_nanosleep.c | 14 ++-- src/time/clock_settime.c | 14 ++-- 18 files changed, 217 insertions(+), 140 deletions(-) diff --git a/src/ipc/semtimedop.c b/src/ipc/semtimedop.c index 1632e7b0..d9fe404d 100644 --- a/src/ipc/semtimedop.c +++ b/src/ipc/semtimedop.c @@ -16,13 +16,17 @@ int semtimedop(int id, struct sembuf *buf, size_t n, const struct timespec *ts) { #ifdef SYS_semtimedop_time64 + static int use_semtimedop_time64 = 1; time_t s = ts ? ts->tv_sec : 0; long ns = ts ? ts->tv_nsec : 0; int r = -ENOSYS; - if (NO_TIME32 || !IS32BIT(s)) - r = __syscall(SYS_semtimedop_time64, id, buf, n, - ts ? ((long long[]){s, ns}) : 0); - if (NO_TIME32 || r!=-ENOSYS) return __syscall_ret(r); + if (use_semtimedop_time64) { + if (NO_TIME32 || !IS32BIT(s)) + r = __syscall(SYS_semtimedop_time64, id, buf, n, + ts ? ((long long[]){s, ns}) : 0); + if (NO_TIME32 || r!=-ENOSYS) return __syscall_ret(r); + else use_semtimedop_time64 = 0; + } ts = ts ? (void *)(long[]){CLAMP(s), ns} : 0; #endif #if defined(SYS_ipc) diff --git a/src/linux/clock_adjtime.c b/src/linux/clock_adjtime.c index d4d03d24..a4d43406 100644 --- a/src/linux/clock_adjtime.c +++ b/src/linux/clock_adjtime.c @@ -38,55 +38,59 @@ int clock_adjtime (clockid_t clock_id, struct timex *utx) { int r = -ENOSYS; #ifdef SYS_clock_adjtime64 - struct ktimex64 ktx = { - .modes = utx->modes, - .offset = utx->offset, - .freq = utx->freq, - .maxerror = utx->maxerror, - .esterror = utx->esterror, - .status = utx->status, - .constant = utx->constant, - .precision = utx->precision, - .tolerance = utx->tolerance, - .time_sec = utx->time.tv_sec, - .time_usec = utx->time.tv_usec, - .tick = utx->tick, - .ppsfreq = utx->ppsfreq, - .jitter = utx->jitter, - .shift = utx->shift, - .stabil = utx->stabil, - .jitcnt = utx->jitcnt, - .calcnt = utx->calcnt, - .errcnt = utx->errcnt, - .stbcnt = utx->stbcnt, - .tai = utx->tai, - }; - r = __syscall(SYS_clock_adjtime64, clock_id, &ktx); - if (r>=0) { - utx->modes = ktx.modes; - utx->offset = ktx.offset; - utx->freq = ktx.freq; - utx->maxerror = ktx.maxerror; - utx->esterror = ktx.esterror; - utx->status = ktx.status; - utx->constant = ktx.constant; - utx->precision = ktx.precision; - utx->tolerance = ktx.tolerance; - utx->time.tv_sec = ktx.time_sec; - utx->time.tv_usec = ktx.time_usec; - utx->tick = ktx.tick; - utx->ppsfreq = ktx.ppsfreq; - utx->jitter = ktx.jitter; - utx->shift = ktx.shift; - utx->stabil = ktx.stabil; - utx->jitcnt = ktx.jitcnt; - utx->calcnt = ktx.calcnt; - utx->errcnt = ktx.errcnt; - utx->stbcnt = ktx.stbcnt; - utx->tai = ktx.tai; + static int use_clock_adjtime64 = 1; + if (use_clock_adjtime64) { + struct ktimex64 ktx = { + .modes = utx->modes, + .offset = utx->offset, + .freq = utx->freq, + .maxerror = utx->maxerror, + .esterror = utx->esterror, + .status = utx->status, + .constant = utx->constant, + .precision = utx->precision, + .tolerance = utx->tolerance, + .time_sec = utx->time.tv_sec, + .time_usec = utx->time.tv_usec, + .tick = utx->tick, + .ppsfreq = utx->ppsfreq, + .jitter = utx->jitter, + .shift = utx->shift, + .stabil = utx->stabil, + .jitcnt = utx->jitcnt, + .calcnt = utx->calcnt, + .errcnt = utx->errcnt, + .stbcnt = utx->stbcnt, + .tai = utx->tai, + }; + r = __syscall(SYS_clock_adjtime64, clock_id, &ktx); + if (r>=0) { + utx->modes = ktx.modes; + utx->offset = ktx.offset; + utx->freq = ktx.freq; + utx->maxerror = ktx.maxerror; + utx->esterror = ktx.esterror; + utx->status = ktx.status; + utx->constant = ktx.constant; + utx->precision = ktx.precision; + utx->tolerance = ktx.tolerance; + utx->time.tv_sec = ktx.time_sec; + utx->time.tv_usec = ktx.time_usec; + utx->tick = ktx.tick; + utx->ppsfreq = ktx.ppsfreq; + utx->jitter = ktx.jitter; + utx->shift = ktx.shift; + utx->stabil = ktx.stabil; + utx->jitcnt = ktx.jitcnt; + utx->calcnt = ktx.calcnt; + utx->errcnt = ktx.errcnt; + utx->stbcnt = ktx.stbcnt; + utx->tai = ktx.tai; + } + if (SYS_clock_adjtime == SYS_clock_adjtime64 || r!=-ENOSYS) + return __syscall_ret(r); + else use_clock_adjtime64 = 0; } - if (SYS_clock_adjtime == SYS_clock_adjtime64 || r!=-ENOSYS) - return __syscall_ret(r); if ((utx->modes & ADJ_SETOFFSET) && !IS32BIT(utx->time.tv_sec)) return __syscall_ret(-ENOTSUP); #endif diff --git a/src/linux/ppoll.c b/src/linux/ppoll.c index e614600a..939f3f1d 100644 --- a/src/linux/ppoll.c +++ b/src/linux/ppoll.c @@ -12,13 +12,17 @@ int ppoll(struct pollfd *fds, nfds_t n, const struct timespec *to, const sigset_ time_t s = to ? to->tv_sec : 0; long ns = to ? to->tv_nsec : 0; #ifdef SYS_ppoll_time64 + static int use_ppoll_time64 = 1; int r = -ENOSYS; - if (SYS_ppoll == SYS_ppoll_time64 || !IS32BIT(s)) - r = __syscall_cp(SYS_ppoll_time64, fds, n, - to ? ((long long[]){s, ns}) : 0, - mask, _NSIG/8); - if (SYS_ppoll == SYS_ppoll_time64 || r != -ENOSYS) - return __syscall_ret(r); + if (use_ppoll_time64) { + if (SYS_ppoll == SYS_ppoll_time64 || !IS32BIT(s)) + r = __syscall_cp(SYS_ppoll_time64, fds, n, + to ? ((long long[]){s, ns}) : 0, + mask, _NSIG/8); + if (SYS_ppoll == SYS_ppoll_time64 || r != -ENOSYS) + return __syscall_ret(r); + else use_ppoll_time64 = 0; + } s = CLAMP(s); #endif return syscall_cp(SYS_ppoll, fds, n, diff --git a/src/linux/timerfd.c b/src/linux/timerfd.c index 5bdfaf16..65bda29b 100644 --- a/src/linux/timerfd.c +++ b/src/linux/timerfd.c @@ -14,13 +14,17 @@ int timerfd_settime(int fd, int flags, const struct itimerspec *new, struct itim #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; + static int use_timerfd_settime64 = 1; 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 (use_timerfd_settime64) { + 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); + else use_timerfd_settime64 = 0; + } if (!IS32BIT(is) || !IS32BIT(vs)) return __syscall_ret(-ENOTSUP); long old32[4]; @@ -40,11 +44,15 @@ int timerfd_settime(int fd, int flags, const struct itimerspec *new, struct itim int timerfd_gettime(int fd, struct itimerspec *cur) { #ifdef SYS_timerfd_gettime64 + static int use_timerfd_gettime64 = 1; 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); + if (use_timerfd_gettime64) { + 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); + else use_timerfd_gettime64 = 0; + } long cur32[4]; r = __syscall(SYS_timerfd_gettime, fd, cur32); if (!r) { diff --git a/src/misc/getrusage.c b/src/misc/getrusage.c index 8e03e2e3..47d87981 100644 --- a/src/misc/getrusage.c +++ b/src/misc/getrusage.c @@ -7,19 +7,23 @@ int getrusage(int who, struct rusage *ru) { int r; #ifdef SYS_getrusage_time64 - long long kru64[18]; - r = __syscall(SYS_getrusage_time64, who, kru64); - if (!r) { - ru->ru_utime = (struct timeval) - { .tv_sec = kru64[0], .tv_usec = kru64[1] }; - ru->ru_stime = (struct timeval) - { .tv_sec = kru64[2], .tv_usec = kru64[3] }; - char *slots = (char *)&ru->ru_maxrss; - for (int i=0; i<14; i++) - *(long *)(slots + i*sizeof(long)) = kru64[4+i]; + static int use_getrusage_time64 = 1; + if (use_getrusage_time64) { + long long kru64[18]; + r = __syscall(SYS_getrusage_time64, who, kru64); + if (!r) { + ru->ru_utime = (struct timeval) + { .tv_sec = kru64[0], .tv_usec = kru64[1] }; + ru->ru_stime = (struct timeval) + { .tv_sec = kru64[2], .tv_usec = kru64[3] }; + char *slots = (char *)&ru->ru_maxrss; + for (int i=0; i<14; i++) + *(long *)(slots + i*sizeof(long)) = kru64[4+i]; + } + if (SYS_getrusage_time64 == SYS_getrusage || r != -ENOSYS) + return __syscall_ret(r); + else use_getrusage_time64 = 0; } - if (SYS_getrusage_time64 == SYS_getrusage || r != -ENOSYS) - return __syscall_ret(r); #endif char *dest = (char *)&ru->ru_maxrss - 4*sizeof(long); r = __syscall(SYS_getrusage, who, dest); diff --git a/src/mq/mq_timedreceive.c b/src/mq/mq_timedreceive.c index f41b6642..43c4fef6 100644 --- a/src/mq/mq_timedreceive.c +++ b/src/mq/mq_timedreceive.c @@ -8,14 +8,18 @@ ssize_t mq_timedreceive(mqd_t mqd, char *restrict msg, size_t len, unsigned *restrict prio, const struct timespec *restrict at) { #ifdef SYS_mq_timedreceive_time64 + static int use_mq_timedreceive_time64 = 1; time_t s = at ? at->tv_sec : 0; long ns = at ? at->tv_nsec : 0; long r = -ENOSYS; - if (SYS_mq_timedreceive == SYS_mq_timedreceive_time64 || !IS32BIT(s)) - r = __syscall_cp(SYS_mq_timedreceive_time64, mqd, msg, len, prio, - at ? ((long long []){at->tv_sec, at->tv_nsec}) : 0); - if (SYS_mq_timedreceive == SYS_mq_timedreceive_time64 || r != -ENOSYS) - return __syscall_ret(r); + if (use_mq_timedreceive_time64) { + if (SYS_mq_timedreceive == SYS_mq_timedreceive_time64 || !IS32BIT(s)) + r = __syscall_cp(SYS_mq_timedreceive_time64, mqd, msg, len, prio, + at ? ((long long []){at->tv_sec, at->tv_nsec}) : 0); + if (SYS_mq_timedreceive == SYS_mq_timedreceive_time64 || r != -ENOSYS) + return __syscall_ret(r); + else use_mq_timedreceive_time64 = 0; + } return syscall_cp(SYS_mq_timedreceive, mqd, msg, len, prio, at ? ((long[]){CLAMP(s), ns}) : 0); #else diff --git a/src/mq/mq_timedsend.c b/src/mq/mq_timedsend.c index 56cfcbb8..77164093 100644 --- a/src/mq/mq_timedsend.c +++ b/src/mq/mq_timedsend.c @@ -8,14 +8,18 @@ int mq_timedsend(mqd_t mqd, const char *msg, size_t len, unsigned prio, const struct timespec *at) { #ifdef SYS_mq_timedsend_time64 + static int use_mq_timedsend_time64 = 1; time_t s = at ? at->tv_sec : 0; long ns = at ? at->tv_nsec : 0; long r = -ENOSYS; - if (SYS_mq_timedsend == SYS_mq_timedsend_time64 || !IS32BIT(s)) - r = __syscall_cp(SYS_mq_timedsend_time64, mqd, msg, len, prio, - at ? ((long long []){at->tv_sec, at->tv_nsec}) : 0); - if (SYS_mq_timedsend == SYS_mq_timedsend_time64 || r != -ENOSYS) - return __syscall_ret(r); + if (use_mq_timedsend_time64) { + if (SYS_mq_timedsend == SYS_mq_timedsend_time64 || !IS32BIT(s)) + r = __syscall_cp(SYS_mq_timedsend_time64, mqd, msg, len, prio, + at ? ((long long []){at->tv_sec, at->tv_nsec}) : 0); + if (SYS_mq_timedsend == SYS_mq_timedsend_time64 || r != -ENOSYS) + return __syscall_ret(r); + else use_mq_timedsend_time64 = 0; + } return syscall_cp(SYS_mq_timedsend, mqd, msg, len, prio, at ? ((long[]){CLAMP(s), ns}) : 0); #else diff --git a/src/network/recvmmsg.c b/src/network/recvmmsg.c index 2978e2f6..ea603854 100644 --- a/src/network/recvmmsg.c +++ b/src/network/recvmmsg.c @@ -19,12 +19,17 @@ int recvmmsg(int fd, struct mmsghdr *msgvec, unsigned int vlen, unsigned int fla mh->msg_hdr.__pad1 = mh->msg_hdr.__pad2 = 0; #endif #ifdef SYS_recvmmsg_time64 + static int use_recvmmsg_time64 = 1; time_t s = timeout ? timeout->tv_sec : 0; long ns = timeout ? timeout->tv_nsec : 0; - int r = __syscall_cp(SYS_recvmmsg_time64, fd, msgvec, vlen, flags, - timeout ? ((long long[]){s, ns}) : 0); - if (SYS_recvmmsg == SYS_recvmmsg_time64 || r!=-ENOSYS) - return __syscall_ret(r); + int r; + if (use_recvmmsg_time64) { + r = __syscall_cp(SYS_recvmmsg_time64, fd, msgvec, vlen, flags, + timeout ? ((long long[]){s, ns}) : 0); + if (SYS_recvmmsg == SYS_recvmmsg_time64 || r!=-ENOSYS) + return __syscall_ret(r); + else use_recvmmsg_time64 = 0; + } if (vlen > IOV_MAX) vlen = IOV_MAX; socklen_t csize[vlen]; for (int i=0; itv_sec : 0; long ns = ts ? ts->tv_nsec : 0; #ifdef SYS_pselect6_time64 + static int use_pselect6_time64 = 1; int r = -ENOSYS; - if (SYS_pselect6 == SYS_pselect6_time64 || !IS32BIT(s)) - r = __syscall_cp(SYS_pselect6_time64, n, rfds, wfds, efds, - ts ? ((long long[]){s, ns}) : 0, data); - if (SYS_pselect6 == SYS_pselect6_time64 || r!=-ENOSYS) - return __syscall_ret(r); + if (use_pselect6_time64) { + if (SYS_pselect6 == SYS_pselect6_time64 || !IS32BIT(s)) + r = __syscall_cp(SYS_pselect6_time64, n, rfds, wfds, efds, + ts ? ((long long[]){s, ns}) : 0, data); + if (SYS_pselect6 == SYS_pselect6_time64 || r!=-ENOSYS) + return __syscall_ret(r); + else use_pselect6_time64 = 0; + } s = CLAMP(s); #endif return syscall_cp(SYS_pselect6, n, rfds, wfds, efds, diff --git a/src/select/select.c b/src/select/select.c index 8a786884..810cf450 100644 --- a/src/select/select.c +++ b/src/select/select.c @@ -26,13 +26,17 @@ int select(int n, fd_set *restrict rfds, fd_set *restrict wfds, fd_set *restrict } #ifdef SYS_pselect6_time64 + static int use_pselect6_time64 = 1; int r = -ENOSYS; - if (SYS_pselect6 == SYS_pselect6_time64 || !IS32BIT(s)) - r = __syscall_cp(SYS_pselect6_time64, n, rfds, wfds, efds, - tv ? ((long long[]){s, ns}) : 0, - ((syscall_arg_t[]){ 0, _NSIG/8 })); - if (SYS_pselect6 == SYS_pselect6_time64 || r!=-ENOSYS) - return __syscall_ret(r); + if (use_pselect6_time64) { + if (SYS_pselect6 == SYS_pselect6_time64 || !IS32BIT(s)) + r = __syscall_cp(SYS_pselect6_time64, n, rfds, wfds, efds, + tv ? ((long long[]){s, ns}) : 0, + ((syscall_arg_t[]){ 0, _NSIG/8 })); + if (SYS_pselect6 == SYS_pselect6_time64 || r!=-ENOSYS) + return __syscall_ret(r); + else use_pselect6_time64 = 0; + } #endif #ifdef SYS_select return syscall_cp(SYS_select, n, rfds, wfds, efds, diff --git a/src/signal/sigtimedwait.c b/src/signal/sigtimedwait.c index 1287174e..efc786db 100644 --- a/src/signal/sigtimedwait.c +++ b/src/signal/sigtimedwait.c @@ -8,14 +8,18 @@ static int do_sigtimedwait(const sigset_t *restrict mask, siginfo_t *restrict si, const struct timespec *restrict ts) { #ifdef SYS_rt_sigtimedwait_time64 + static int use_rt_sigtimedwait_time64 = 1; time_t s = ts ? ts->tv_sec : 0; long ns = ts ? ts->tv_nsec : 0; int r = -ENOSYS; - if (SYS_rt_sigtimedwait == SYS_rt_sigtimedwait_time64 || !IS32BIT(s)) - r = __syscall_cp(SYS_rt_sigtimedwait_time64, mask, si, - ts ? ((long long[]){s, ns}) : 0, _NSIG/8); - if (SYS_rt_sigtimedwait == SYS_rt_sigtimedwait_time64 || r!=-ENOSYS) - return r; + if (use_rt_sigtimedwait_time64) { + if (SYS_rt_sigtimedwait == SYS_rt_sigtimedwait_time64 || !IS32BIT(s)) + r = __syscall_cp(SYS_rt_sigtimedwait_time64, mask, si, + ts ? ((long long[]){s, ns}) : 0, _NSIG/8); + if (SYS_rt_sigtimedwait == SYS_rt_sigtimedwait_time64 || r!=-ENOSYS) + return r; + else use_rt_sigtimedwait_time64 = 0; + } return __syscall_cp(SYS_rt_sigtimedwait, mask, si, ts ? ((long[]){CLAMP(s), ns}) : 0, _NSIG/8);; #else diff --git a/src/stat/fstatat.c b/src/stat/fstatat.c index de165b5c..e8e8c866 100644 --- a/src/stat/fstatat.c +++ b/src/stat/fstatat.c @@ -133,10 +133,14 @@ static int fstatat_kstat(int fd, const char *restrict path, struct stat *restric int fstatat(int fd, const char *restrict path, struct stat *restrict st, int flag) { + static int use_statx = 1; int ret; - if (sizeof((struct kstat){0}.st_atime_sec) < sizeof(time_t)) { - ret = fstatat_statx(fd, path, st, flag); - if (ret!=-ENOSYS) return __syscall_ret(ret); + if (use_statx) { + if (sizeof((struct kstat){0}.st_atime_sec) < sizeof(time_t)) { + ret = fstatat_statx(fd, path, st, flag); + if (ret!=-ENOSYS) return __syscall_ret(ret); + else use_statx = 0; + } } ret = fstatat_kstat(fd, path, st, flag); return __syscall_ret(ret); diff --git a/src/stat/utimensat.c b/src/stat/utimensat.c index 730723a9..adde7e4e 100644 --- a/src/stat/utimensat.c +++ b/src/stat/utimensat.c @@ -13,6 +13,7 @@ int utimensat(int fd, const char *path, const struct timespec times[2], int flag if (times && times[0].tv_nsec==UTIME_NOW && times[1].tv_nsec==UTIME_NOW) times = 0; #ifdef SYS_utimensat_time64 + static int use_utimensat_time64 = 1; r = -ENOSYS; time_t s0=0, s1=0; long ns0=0, ns1=0; @@ -22,11 +23,14 @@ int utimensat(int fd, const char *path, const struct timespec times[2], int flag if (!NS_SPECIAL(ns0)) s0 = times[0].tv_sec; if (!NS_SPECIAL(ns1)) s1 = times[1].tv_sec; } - if (SYS_utimensat == SYS_utimensat_time64 || !IS32BIT(s0) || !IS32BIT(s1)) - r = __syscall(SYS_utimensat_time64, fd, path, times ? - ((long long[]){s0, ns0, s1, ns1}) : 0, flags); - if (SYS_utimensat == SYS_utimensat_time64 || r!=-ENOSYS) - return __syscall_ret(r); + if (use_utimensat_time64) { + if (SYS_utimensat == SYS_utimensat_time64 || !IS32BIT(s0) || !IS32BIT(s1)) + r = __syscall(SYS_utimensat_time64, fd, path, times ? + ((long long[]){s0, ns0, s1, ns1}) : 0, flags); + if (SYS_utimensat == SYS_utimensat_time64 || r!=-ENOSYS) + return __syscall_ret(r); + else use_utimensat_time64 = 0; + } if (!IS32BIT(s0) || !IS32BIT(s1)) return __syscall_ret(-ENOTSUP); r = __syscall(SYS_utimensat, fd, path, diff --git a/src/thread/__timedwait.c b/src/thread/__timedwait.c index 666093be..2c417837 100644 --- a/src/thread/__timedwait.c +++ b/src/thread/__timedwait.c @@ -12,13 +12,17 @@ static int __futex4_cp(volatile void *addr, int op, int val, const struct timesp { int r; #ifdef SYS_futex_time64 + static int use_futex_time64 = 1; time_t s = to ? to->tv_sec : 0; long ns = to ? to->tv_nsec : 0; r = -ENOSYS; - if (SYS_futex == SYS_futex_time64 || !IS32BIT(s)) - r = __syscall_cp(SYS_futex_time64, addr, op, val, - to ? ((long long[]){s, ns}) : 0); - if (SYS_futex == SYS_futex_time64 || r!=-ENOSYS) return r; + if (use_futex_time64) { + if (SYS_futex == SYS_futex_time64 || !IS32BIT(s)) + r = __syscall_cp(SYS_futex_time64, addr, op, val, + to ? ((long long[]){s, ns}) : 0); + if (SYS_futex == SYS_futex_time64 || r!=-ENOSYS) return r; + else use_futex_time64 = 0; + } to = to ? (void *)(long[]){CLAMP(s), ns} : 0; #endif r = __syscall_cp(SYS_futex, addr, op, val, to); diff --git a/src/thread/pthread_mutex_timedlock.c b/src/thread/pthread_mutex_timedlock.c index 9279fc54..dcf15945 100644 --- a/src/thread/pthread_mutex_timedlock.c +++ b/src/thread/pthread_mutex_timedlock.c @@ -6,13 +6,17 @@ static int __futex4(volatile void *addr, int op, int val, const struct timespec *to) { #ifdef SYS_futex_time64 + static int use_futex_time64 = 1; time_t s = to ? to->tv_sec : 0; long ns = to ? to->tv_nsec : 0; int r = -ENOSYS; - if (SYS_futex == SYS_futex_time64 || !IS32BIT(s)) - r = __syscall(SYS_futex_time64, addr, op, val, - to ? ((long long[]){s, ns}) : 0); - if (SYS_futex == SYS_futex_time64 || r!=-ENOSYS) return r; + if (use_futex_time64) { + if (SYS_futex == SYS_futex_time64 || !IS32BIT(s)) + r = __syscall(SYS_futex_time64, addr, op, val, + to ? ((long long[]){s, ns}) : 0); + if (SYS_futex == SYS_futex_time64 || r!=-ENOSYS) return r; + else use_futex_time64 = 0; + } to = to ? (void *)(long[]){CLAMP(s), ns} : 0; #endif return __syscall(SYS_futex, addr, op, val, to); diff --git a/src/time/clock_gettime.c b/src/time/clock_gettime.c index 3e1d0975..736fde8b 100644 --- a/src/time/clock_gettime.c +++ b/src/time/clock_gettime.c @@ -73,11 +73,15 @@ int __clock_gettime(clockid_t clk, struct timespec *ts) #endif #ifdef SYS_clock_gettime64 + static int use_clock_gettime64 = 1; r = -ENOSYS; - if (sizeof(time_t) > 4) - r = __syscall(SYS_clock_gettime64, clk, ts); - if (SYS_clock_gettime == SYS_clock_gettime64 || r!=-ENOSYS) - return __syscall_ret(r); + if (use_clock_gettime64) { + if (sizeof(time_t) > 4) + r = __syscall(SYS_clock_gettime64, clk, ts); + if (SYS_clock_gettime == SYS_clock_gettime64 || r!=-ENOSYS) + return __syscall_ret(r); + else use_clock_gettime64 = 0; + } long ts32[2]; r = __syscall(SYS_clock_gettime, clk, ts32); if (r==-ENOSYS && clk==CLOCK_REALTIME) { diff --git a/src/time/clock_nanosleep.c b/src/time/clock_nanosleep.c index e195499c..bbb657b6 100644 --- a/src/time/clock_nanosleep.c +++ b/src/time/clock_nanosleep.c @@ -9,14 +9,18 @@ int __clock_nanosleep(clockid_t clk, int flags, const struct timespec *req, stru { if (clk == CLOCK_THREAD_CPUTIME_ID) return EINVAL; #ifdef SYS_clock_nanosleep_time64 + static int use_clock_nanosleep_time64 = 1; time_t s = req->tv_sec; long ns = req->tv_nsec; int r = -ENOSYS; - if (SYS_clock_nanosleep == SYS_clock_nanosleep_time64 || !IS32BIT(s)) - r = __syscall_cp(SYS_clock_nanosleep_time64, clk, flags, - ((long long[]){s, ns}), rem); - if (SYS_clock_nanosleep == SYS_clock_nanosleep_time64 || r!=-ENOSYS) - return -r; + if (use_clock_nanosleep_time64) { + if (SYS_clock_nanosleep == SYS_clock_nanosleep_time64 || !IS32BIT(s)) + r = __syscall_cp(SYS_clock_nanosleep_time64, clk, flags, + ((long long[]){s, ns}), rem); + if (SYS_clock_nanosleep == SYS_clock_nanosleep_time64 || r!=-ENOSYS) + return -r; + else use_clock_nanosleep_time64 = 0; + } long long extra = s - CLAMP(s); long ts32[2] = { CLAMP(s), ns }; if (clk == CLOCK_REALTIME && !flags) diff --git a/src/time/clock_settime.c b/src/time/clock_settime.c index 1004ed15..aa137fa7 100644 --- a/src/time/clock_settime.c +++ b/src/time/clock_settime.c @@ -7,14 +7,18 @@ int clock_settime(clockid_t clk, const struct timespec *ts) { #ifdef SYS_clock_settime64 + static int use_clock_settime64 = 1; time_t s = ts->tv_sec; long ns = ts->tv_nsec; int r = -ENOSYS; - if (SYS_clock_settime == SYS_clock_settime64 || !IS32BIT(s)) - r = __syscall(SYS_clock_settime64, clk, - ((long long[]){s, ns})); - if (SYS_clock_settime == SYS_clock_settime64 || r!=-ENOSYS) - return __syscall_ret(r); + if (use_clock_settime64) { + if (SYS_clock_settime == SYS_clock_settime64 || !IS32BIT(s)) + r = __syscall(SYS_clock_settime64, clk, + ((long long[]){s, ns})); + if (SYS_clock_settime == SYS_clock_settime64 || r!=-ENOSYS) + return __syscall_ret(r); + else use_clock_settime64 = 0; + } if (!IS32BIT(s)) return __syscall_ret(-ENOTSUP); return syscall(SYS_clock_settime, clk, ((long[]){s, ns})); -- 2.20.1