1
0
Fork 0
mirror of git://git.code.sf.net/p/cdesktopenv/code synced 2025-03-09 15:50:02 +00:00

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)
This commit is contained in:
Martijn Dekker 2021-01-15 19:05:32 +00:00
parent a3f4ef7adf
commit 2f7918deec

View file

@ -1,7 +1,7 @@
/*********************************************************************** /***********************************************************************
* * * *
* This software is part of the ast package * * 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 * * and is licensed under the *
* Eclipse Public License, Version 1.0 * * Eclipse Public License, Version 1.0 *
* by AT&T Intellectual Property * * by AT&T Intellectual Property *
@ -14,34 +14,30 @@
* AT&T Research * * AT&T Research *
* Florham Park NJ * * Florham Park NJ *
* * * *
* Glenn Fowler <gsf@research.att.com> * * Glenn Fowler <glenn.s.fowler@gmail.com> *
* David Korn <dgk@research.att.com> * * David Korn <dgkorn@gmail.com> *
* Phong Vo <kpv@research.att.com> * * Phong Vo <phongvo@gmail.com> *
* * * *
***********************************************************************/ ***********************************************************************/
#pragma prototyped #pragma prototyped
#include <tv.h> #include <tv.h>
#include <tm.h> #include <tm.h>
#include <error.h>
#include "FEATURE/tvlib" #include "FEATURE/tvlib"
#if !_lib_nanosleep #if !_lib_nanosleep && !_lib_usleep
# if _lib_select # if _lib_select
# if _sys_select # if _sys_select
# include <sys/select.h> # include <sys/select.h>
# else # else
# include <sys/socket.h> # include <sys/socket.h>
# endif # endif
# else # elif _lib_poll_notimer
# if !_lib_usleep # undef _lib_poll
# if _lib_poll_notimer # elif _lib_poll
# undef _lib_poll # include <poll.h>
# endif
# if _lib_poll
# include <poll.h>
# endif
# endif
# endif # endif
#endif #endif
@ -49,6 +45,8 @@
* sleep for tv * sleep for tv
* non-zero exit if sleep did not complete * non-zero exit if sleep did not complete
* with remaining time in rv * with remaining time in rv
*
* NOTE: some systems hide nanosleep() outside of libc
*/ */
int int
@ -63,7 +61,7 @@ tvsleep(register const Tv_t* tv, register Tv_t* rv)
stv.tv_sec = tv->tv_sec; stv.tv_sec = tv->tv_sec;
stv.tv_nsec = tv->tv_nsec; 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_sec = srv.tv_sec;
rv->tv_nsec = srv.tv_nsec; rv->tv_nsec = srv.tv_nsec;
@ -72,72 +70,143 @@ tvsleep(register const Tv_t* tv, register Tv_t* rv)
#else #else
Tv_t bv;
tvgettime(&bv);
{
#if _lib_select #if _lib_select
struct timeval stv; struct timeval stv;
stv.tv_sec = tv->tv_sec; stv.tv_sec = tv->tv_sec;
stv.tv_usec = tv->tv_nsec / 1000; if (!(stv.tv_usec = tv->tv_nsec / 1000))
if (select(0, NiL, NiL, NiL, &stv) < 0) stv.tv_usec = 1;
{ if (select(0, NiL, NiL, NiL, &stv) >= 0)
if (rv) return 0;
*rv = *tv;
return -1;
}
if (rv)
{
rv->tv_sec = stv.tv_sec;
rv->tv_nsec = stv.tv_usec * 1000;
}
return 0;
#else #else
unsigned int s = tv->tv_sec; uint32_t s = tv->tv_sec;
uint32_t n = tv->tv_nsec; uint32_t n = tv->tv_nsec;
unsigned int t;
#if _lib_usleep #if _lib_usleep
if (s < (0x7fffffff / 1000000))
unsigned long t;
if (t = (n + 999L) / 1000L)
{ {
usleep(t); int oerrno;
s -= t / 1000000L;
n = 0; 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 #elif _lib_poll
#if _lib_poll
struct pollfd pfd; struct pollfd pfd;
int t; int t;
if ((t = (n + 999999L) / 1000000L) > 0) if (!(t = (n + 999999L) / 1000000L))
{ t = 1;
poll(&pfd, 0, t); if (poll(&pfd, 0, t) >= 0)
s -= t / 1000L; return 0;
n = 0;
#endif
#endif
} }
bad:
#endif if (errno == EINTR && rv)
#endif
if ((s += (n + 999999999L) / 1000000000L) && (s = sleep(s)))
{ {
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; 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; return -1;
#endif
#endif #endif