1
0
Fork 0
mirror of git://git.code.sf.net/p/cdesktopenv/code synced 2025-02-15 04:32:24 +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 *
* 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 <gsf@research.att.com> *
* David Korn <dgk@research.att.com> *
* Phong Vo <kpv@research.att.com> *
* Glenn Fowler <glenn.s.fowler@gmail.com> *
* David Korn <dgkorn@gmail.com> *
* Phong Vo <phongvo@gmail.com> *
* *
***********************************************************************/
#pragma prototyped
#include <tv.h>
#include <tm.h>
#include <error.h>
#include "FEATURE/tvlib"
#if !_lib_nanosleep
#if !_lib_nanosleep && !_lib_usleep
# if _lib_select
# if _sys_select
# include <sys/select.h>
# else
# include <sys/socket.h>
# endif
# else
# if !_lib_usleep
# if _lib_poll_notimer
# undef _lib_poll
# endif
# if _lib_poll
# include <poll.h>
# endif
# endif
# elif _lib_poll_notimer
# undef _lib_poll
# elif _lib_poll
# include <poll.h>
# 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