From 2f7918deec140ef837070bb749a35ed19bfcd0ec Mon Sep 17 00:00:00 2001 From: Martijn Dekker Date: Fri, 15 Jan 2021 19:05:32 +0000 Subject: [PATCH] libast: backport tvsleep(3) from ksh 93v- (re: 2db9953a) src/lib/libast/tm/tvsleep.c: - Since the 'sleep' builtin was backported/fixed from ksh93v- and ksh2020, it makes sense to use the latest/last tvsleep(3), too. Looks like this added an interrupt check (errno == EINTR). Also, new fallback versions for systems without nanosleep(2). Documentation: src/lib/libast/man/tv.3 (unchanged) --- src/lib/libast/tm/tvsleep.c | 183 +++++++++++++++++++++++++----------- 1 file changed, 126 insertions(+), 57 deletions(-) diff --git a/src/lib/libast/tm/tvsleep.c b/src/lib/libast/tm/tvsleep.c index 78da80247..3a1b9aefe 100644 --- a/src/lib/libast/tm/tvsleep.c +++ b/src/lib/libast/tm/tvsleep.c @@ -1,7 +1,7 @@ /*********************************************************************** * * * This software is part of the ast package * -* Copyright (c) 1985-2011 AT&T Intellectual Property * +* Copyright (c) 1985-2013 AT&T Intellectual Property * * and is licensed under the * * Eclipse Public License, Version 1.0 * * by AT&T Intellectual Property * @@ -14,34 +14,30 @@ * AT&T Research * * Florham Park NJ * * * -* Glenn Fowler * -* David Korn * -* Phong Vo * +* Glenn Fowler * +* David Korn * +* Phong Vo * * * ***********************************************************************/ #pragma prototyped #include #include +#include #include "FEATURE/tvlib" -#if !_lib_nanosleep +#if !_lib_nanosleep && !_lib_usleep # if _lib_select # if _sys_select # include # else # include # endif -# else -# if !_lib_usleep -# if _lib_poll_notimer -# undef _lib_poll -# endif -# if _lib_poll -# include -# endif -# endif +# elif _lib_poll_notimer +# undef _lib_poll +# elif _lib_poll +# include # endif #endif @@ -49,6 +45,8 @@ * sleep for tv * non-zero exit if sleep did not complete * with remaining time in rv + * + * NOTE: some systems hide nanosleep() outside of libc */ int @@ -63,7 +61,7 @@ tvsleep(register const Tv_t* tv, register Tv_t* rv) stv.tv_sec = tv->tv_sec; stv.tv_nsec = tv->tv_nsec; - if ((r = nanosleep(&stv, &srv)) && rv) + if ((r = nanosleep(&stv, &srv)) && errno == EINTR && rv) { rv->tv_sec = srv.tv_sec; rv->tv_nsec = srv.tv_nsec; @@ -72,72 +70,143 @@ tvsleep(register const Tv_t* tv, register Tv_t* rv) #else + Tv_t bv; + + tvgettime(&bv); + { + #if _lib_select struct timeval stv; stv.tv_sec = tv->tv_sec; - stv.tv_usec = tv->tv_nsec / 1000; - if (select(0, NiL, NiL, NiL, &stv) < 0) - { - if (rv) - *rv = *tv; - return -1; - } - if (rv) - { - rv->tv_sec = stv.tv_sec; - rv->tv_nsec = stv.tv_usec * 1000; - } - return 0; + if (!(stv.tv_usec = tv->tv_nsec / 1000)) + stv.tv_usec = 1; + if (select(0, NiL, NiL, NiL, &stv) >= 0) + return 0; #else - unsigned int s = tv->tv_sec; - uint32_t n = tv->tv_nsec; + uint32_t s = tv->tv_sec; + uint32_t n = tv->tv_nsec; + unsigned int t; #if _lib_usleep - - unsigned long t; - - if (t = (n + 999L) / 1000L) + if (s < (0x7fffffff / 1000000)) { - usleep(t); - s -= t / 1000000L; - n = 0; + int oerrno; + + oerrno = errno; + errno = 0; + usleep(s * 1000000 + n / 1000); + if (!errno) + { + errno = oerrno; + return 0; + } + } + else + { + +#endif + + if (s += (n + 999999999L) / 1000000000L) + { + while (s) + { + if (s > UINT_MAX) + { + t = UINT_MAX; + s -= UINT_MAX; + } + else + { + t = s; + s = 0; + } + if (t = sleep(t)) + { + if (rv) + { + rv->tv_sec = s + t; + rv->tv_nsec = 0; + } + return -1; + } + } + return 0; + } + +#if _lib_usleep + + if (t = (n + 999L) / 1000L) + { + int oerrno; + + oerrno = errno; + errno = 0; + usleep(t); + if (!errno) + { + errno = oerrno; + return 0; + } + } } -#else - -#if _lib_poll +#elif _lib_poll struct pollfd pfd; int t; - if ((t = (n + 999999L) / 1000000L) > 0) - { - poll(&pfd, 0, t); - s -= t / 1000L; - n = 0; + if (!(t = (n + 999999L) / 1000000L)) + t = 1; + if (poll(&pfd, 0, t) >= 0) + return 0; + +#endif + +#endif + } - -#endif - -#endif - - if ((s += (n + 999999999L) / 1000000000L) && (s = sleep(s))) + bad: + if (errno == EINTR && rv) { - if (rv) + tvgettime(rv); + if (rv->tv_nsec < bv.tv_nsec) { - rv->tv_sec = s; + rv->tv_nsec += 1000000000L; + rv->tv_sec--; + } + rv->tv_nsec -= bv.tv_nsec; + rv->tv_sec -= bv.tv_sec; + if (rv->tv_sec > tv->tv_sec) + { + rv->tv_sec = 0; rv->tv_nsec = 0; } - return -1; + else + { + rv->tv_sec = tv->tv_sec - rv->tv_sec; + if (rv->tv_nsec > tv->tv_nsec) + { + if (!rv->tv_sec) + { + rv->tv_sec = 0; + rv->tv_nsec = 0; + } + else + { + rv->tv_sec--; + rv->tv_nsec = 1000000000L - rv->tv_nsec + tv->tv_nsec; + } + } + else + rv->tv_nsec = tv->tv_nsec - rv->tv_nsec; + } } - return 0; - -#endif + return -1; #endif