Commit 10ce26c0 authored by Paul Eggert's avatar Paul Eggert

* modules/gethrxtime: New file.

* modules/xnanosleep (Files): Add m4/xnanosleep.m4.
(Depends-on): Add gethrxtime.
(configure.ac): Add gl_XNANOSLEEP.
(Makefile.am): Remove lib_SOURCES line.

* lib/gethrxtime.h, lib/gethrxtime.c, lib/xtime.h: New files.
* lib/timespec.h (gettime): Return void, since it always
succeeds now.  All uses changed.
* lib/gettime.c (gettime) Likewise.
[HAVE_NANOTIME]: Prefer nanotime.
Assume gettimeofday succeeds, as POSIX requires.
Assime time () succeeds, since other code already does.
* lib/xnanosleep.c: Include xtime.h and gethrxtime.h, not xalloc.h.
(timespec_subtract): Remove.
(NANOSLEEP_BUG_WORKAROUND): New constant.
(xnanosleep): Use gethrxtime rather than gettime; this simplifies
things considerably.  Use it only on GNU/Linux hosts, since the
workaround shouldn't be needed elsewhere.

* m4/gethrxtime.m4, m4/xnanosleep.m4: New files.
* m4/gettime.m4 (gl_GETTIME): Check for nanotime.
parent e8cddd65
2005-02-26 Paul Eggert <eggert@cs.ucla.edu>
* modules/gethrxtime: New file.
* modules/xnanosleep (Files): Add m4/xnanosleep.m4.
(Depends-on): Add gethrxtime.
(configure.ac): Add gl_XNANOSLEEP.
(Makefile.am): Remove lib_SOURCES line.
2005-02-24 Bruno Haible <bruno@clisp.org>
* modules/gettext (Files): Add m4/glibc2.m4.
......
2005-02-25 Paul Eggert <eggert@cs.ucla.edu>
* gethrxtime.h, gethrxtime.c, xtime.h: New files.
* timespec.h (gettime): Return void, since it always
succeeds now. All uses changed.
* gettime.c (gettime) Likewise.
[HAVE_NANOTIME]: Prefer nanotime.
Assume gettimeofday succeeds, as POSIX requires.
Assime time () succeeds, since other code already does.
* xnanosleep.c: Include xtime.h and gethrxtime.h, not xalloc.h.
(timespec_subtract): Remove.
(NANOSLEEP_BUG_WORKAROUND): New constant.
(xnanosleep): Use gethrxtime rather than gettime; this simplifies
things considerably. Use it only on GNU/Linux hosts, since the
workaround shouldn't be needed elsewhere.
2005-02-24 Bruno Haible <bruno@clisp.org>
* gettext.h: Update from GNU gettext 0.14.2.
......
%{
/* Parse a string into an internal time stamp.
Copyright (C) 1999, 2000, 2002, 2003, 2004 Free Software Foundation, Inc.
Copyright (C) 1999, 2000, 2002, 2003, 2004, 2005 Free Software
Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -1125,8 +1127,7 @@ get_date (struct timespec *result, char const *p, struct timespec const *now)
if (! now)
{
if (gettime (&gettime_buffer) != 0)
return false;
gettime (&gettime_buffer);
now = &gettime_buffer;
}
......
/* gethrxtime -- get high resolution real time
Copyright (C) 2005 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/* Written by Paul Eggert. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "gethrxtime.h"
#include <sys/types.h>
#if TIME_WITH_SYS_TIME
# include <sys/time.h>
# include <time.h>
#else
# if HAVE_SYS_TIME_H
# include <sys/time.h>
# else
# include <time.h>
# endif
#endif
/* Get the time of a high-resolution clock, preferably one that is not
subject to resetting or drifting. */
xtime_t
gethrxtime (void)
{
#if HAVE_NANOUPTIME
{
struct timespec ts;
nanouptime (&ts);
return xtime_make (ts.tv_sec, ts.tv_nsec);
}
#else
# if defined CLOCK_MONOTONIC && HAVE_CLOCK_GETTIME
{
struct timespec ts;
if (clock_gettime (CLOCK_MONOTONIC, &ts) == 0)
return xtime_make (ts.tv_sec, ts.tv_nsec);
}
# endif
#if HAVE_MICROUPTIME
{
struct timeval tv;
microuptime (&tv);
return xtime_make (tv.tv_sec, 1000 * tv.tv_usec);
}
/* No monotonically increasing clocks are available; fall back on a
clock that might jump backwards, since it's the best we can do. */
# elif HAVE_GETTIMEOFDAY && XTIME_PRECISION != 1
{
struct timeval tv;
gettimeofday (&tv, NULL);
return xtime_make (tv.tv_sec, 1000 * tv.tv_usec);
}
# else
return xtime_make (time (NULL), 0);
# endif
#endif
}
/* gethrxtime -- get high resolution real time
Copyright (C) 2005 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/* Written by Paul Eggert. */
#ifndef GETHRXTIME_H_
#define GETHRXTIME_H_ 1
#include "xtime.h"
/* Get the current time, as a count of the number of nanoseconds since
an arbitrary epoch (e.g., the system boot time). This clock can't
be set, is always increasing, and is nearly linear. */
#if HAVE_ARITHMETIC_HRTIME_T && HAVE_DECL_GETHRTIME
# include <time.h>
static inline xtime_t gethrxtime (void) { return gethrtime (); }
#else
xtime_t gethrxtime (void);
#endif
#endif
/* gettime -- get the system clock
Copyright (C) 2002, 2004 Free Software Foundation, Inc.
Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -23,37 +23,31 @@
#include "timespec.h"
/* Get the system time. */
/* Get the system time into *TS. */
int
void
gettime (struct timespec *ts)
{
#if defined CLOCK_REALTIME && HAVE_CLOCK_GETTIME
#if HAVE_NANOTIME
nanotime (ts);
#else
# if defined CLOCK_REALTIME && HAVE_CLOCK_GETTIME
if (clock_gettime (CLOCK_REALTIME, ts) == 0)
return 0;
#endif
return;
# endif
#if HAVE_GETTIMEOFDAY
# if HAVE_GETTIMEOFDAY
{
struct timeval tv;
if (gettimeofday (&tv, 0) == 0)
{
ts->tv_sec = tv.tv_sec;
ts->tv_nsec = tv.tv_usec * 1000;
return 0;
}
gettimeofday (&tv, NULL);
ts->tv_sec = tv.tv_sec;
ts->tv_nsec = tv.tv_usec * 1000;
}
#endif
# else
ts->tv_sec = time (NULL);
ts->tv_nsec = 0;
# endif
{
time_t t = time (0);
if (t != (time_t) -1)
{
ts->tv_sec = t;
ts->tv_nsec = 0;
return 0;
}
}
return -1;
#endif
}
/* timespec -- System time interface
Copyright (C) 2000, 2002, 2004 Free Software Foundation, Inc.
Copyright (C) 2000, 2002, 2004, 2005 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -65,7 +65,7 @@ struct timespec
int nanosleep ();
# endif
int gettime (struct timespec *);
void gettime (struct timespec *);
int settime (struct timespec const *);
#endif
/* xnanosleep.c -- a more convenient interface to nanosleep
Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -32,6 +32,10 @@
#include <sys/types.h>
#include <time.h>
#include "timespec.h"
#include "gethrxtime.h"
#include "xtime.h"
/* The extra casts work around common compiler bugs. */
#define TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
/* The outer cast is needed to work around a bug in Cray C 5.0.3.0.
......@@ -44,44 +48,18 @@
# define TIME_T_MAX TYPE_MAXIMUM (time_t)
#endif
#include "timespec.h"
#include "xalloc.h"
/* Subtract the `struct timespec' values X and Y by computing X - Y.
If the difference is negative or zero, return false.
Otherwise, return true and store the difference in DIFF.
X and Y must have valid ts_nsec values, in the range 0 to 999999999.
If the difference would overflow, store the maximum possible difference. */
static bool
timespec_subtract (struct timespec *diff,
struct timespec const *x, struct timespec const *y)
{
time_t sec = x->tv_sec - y->tv_sec;
long int nsec = x->tv_nsec - y->tv_nsec;
if (x->tv_sec < y->tv_sec)
return false;
if (sec < 0)
{
/* The difference has overflowed. */
sec = TIME_T_MAX;
nsec = 999999999;
}
else if (sec == 0 && nsec <= 0)
return false;
if (nsec < 0)
{
sec--;
nsec += 1000000000;
}
diff->tv_sec = sec;
diff->tv_nsec = nsec;
return true;
}
/* POSIX.1-2001 requires that when a process is suspended, then
resumed, nanosleep (A, B) returns -1, sets errno to EINTR, and sets
*B to the time remaining at the point of resumption. However, some
versions of the Linux kernel incorrectly return the time remaining
at the point of suspension. Work around this bug on GNU/Linux
hosts by computing the remaining time here after nanosleep returns,
rather than by relying on nanosleep's computation. */
#ifdef __linux__
enum { NANOSLEEP_BUG_WORKAROUND = true };
#else
enum { NANOSLEEP_BUG_WORKAROUND = false };
#endif
/* Sleep until the time (call it WAKE_UP_TIME) specified as
SECONDS seconds after the time this function is called.
......@@ -93,22 +71,29 @@ timespec_subtract (struct timespec *diff,
int
xnanosleep (double seconds)
{
bool overflow;
enum { BILLION = 1000000000 };
bool overflow = false;
double ns;
struct timespec ts_start;
struct timespec ts_sleep;
struct timespec ts_stop;
xtime_t stop = 0;
assert (0 <= seconds);
if (gettime (&ts_start) != 0)
return -1;
if (NANOSLEEP_BUG_WORKAROUND)
{
xtime_t now = gethrxtime ();
double increment = XTIME_PRECISION * seconds;
xtime_t incr = increment;
stop = now + incr + (incr < increment);
overflow = (stop < now);
}
/* Separate whole seconds from nanoseconds.
Be careful to detect any overflow. */
ts_sleep.tv_sec = seconds;
ns = 1e9 * (seconds - ts_sleep.tv_sec);
overflow = ! (ts_sleep.tv_sec <= seconds && 0 <= ns && ns <= 1e9);
ns = BILLION * (seconds - ts_sleep.tv_sec);
overflow |= ! (ts_sleep.tv_sec <= seconds && 0 <= ns && ns <= BILLION);
ts_sleep.tv_nsec = ns;
/* Round up to the next whole number, if necessary, so that we
......@@ -119,7 +104,7 @@ xnanosleep (double seconds)
ts_sleep.tv_nsec += (ts_sleep.tv_nsec < ns);
/* Normalize the interval length. nanosleep requires this. */
if (1000000000 <= ts_sleep.tv_nsec)
if (BILLION <= ts_sleep.tv_nsec)
{
time_t t = ts_sleep.tv_sec + 1;
......@@ -127,45 +112,34 @@ xnanosleep (double seconds)
overflow |= (t < ts_sleep.tv_sec);
ts_sleep.tv_sec = t;
ts_sleep.tv_nsec -= 1000000000;
}
/* Compute the time until which we should sleep. */
ts_stop.tv_sec = ts_start.tv_sec + ts_sleep.tv_sec;
ts_stop.tv_nsec = ts_start.tv_nsec + ts_sleep.tv_nsec;
if (1000000000 <= ts_stop.tv_nsec)
{
++ts_stop.tv_sec;
ts_stop.tv_nsec -= 1000000000;
ts_sleep.tv_nsec -= BILLION;
}
/* Detect integer overflow. */
overflow |= (ts_stop.tv_sec < ts_start.tv_sec
|| (ts_stop.tv_sec == ts_start.tv_sec
&& ts_stop.tv_nsec < ts_start.tv_nsec));
if (overflow)
for (;;)
{
/* Fix ts_sleep and ts_stop, which may be garbage due to overflow. */
ts_sleep.tv_sec = ts_stop.tv_sec = TIME_T_MAX;
ts_sleep.tv_nsec = ts_stop.tv_nsec = 999999999;
}
if (overflow)
{
ts_sleep.tv_sec = TIME_T_MAX;
ts_sleep.tv_nsec = BILLION - 1;
}
while (nanosleep (&ts_sleep, NULL) != 0)
{
if (errno != EINTR || gettime (&ts_start) != 0)
if (nanosleep (&ts_sleep, NULL) == 0)
break;
if (errno != EINTR)
return -1;
/* POSIX.1-2001 requires that when a process is suspended, then
resumed, nanosleep (A, B) returns -1, sets errno to EINTR,
and sets *B to the time remaining at the point of resumption.
However, some versions of the Linux kernel incorrectly return
the time remaining at the point of suspension. Work around
this bug by computing the remaining time here, rather than by
relying on nanosleep's computation. */
if (! timespec_subtract (&ts_sleep, &ts_stop, &ts_start))
break;
if (NANOSLEEP_BUG_WORKAROUND)
{
xtime_t now = gethrxtime ();
if (stop <= now)
break;
else
{
xtime_t remaining = stop - now;
ts_sleep.tv_sec = xtime_nonnegative_sec (remaining);
ts_sleep.tv_nsec = xtime_nonnegative_nsec (remaining);
}
}
}
return 0;
......
/* xtime -- extended-resolution integer time stamps
Copyright (C) 2005 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/* Written by Paul Eggert. */
#ifndef XTIME_H_
#define XTIME_H_ 1
/* xtime_t is a signed type used for time stamps. It is an integer
type that is a count of nanoseconds -- except for obsolescent hosts
without sufficiently-wide integers, where it is a count of
seconds. */
#if HAVE_LONG_LONG
typedef long long int xtime_t;
# define XTIME_PRECISION 1000000000LL
#else
# include <limits.h>
typedef long int xtime_t;
# if LONG_MAX >> 31 >> 31 == 0
# define XTIME_PRECISION 1L
# else
# define XTIME_PRECISION 1000000000L
# endif
#endif
/* Return an extended time value that contains S seconds and NS
nanoseconds, without any overflow checking. */
static inline xtime_t
xtime_make (xtime_t s, int ns)
{
if (XTIME_PRECISION == 1)
return s;
else
return XTIME_PRECISION * s + ns;
}
/* Return the number of seconds in T, which must be nonnegative. */
static inline xtime_t
xtime_nonnegative_sec (xtime_t t)
{
return t / XTIME_PRECISION;
}
/* Return the number of seconds in T. */
static inline xtime_t
xtime_sec (xtime_t t)
{
return (XTIME_PRECISION == 1
? t
: t < 0
? (t + XTIME_PRECISION - 1) / XTIME_PRECISION - 1
: xtime_nonnegative_sec (t));
}
/* Return the number of nanoseconds in T, which must be nonnegative. */
static inline int
xtime_nonnegative_nsec (xtime_t t)
{
return t % XTIME_PRECISION;
}
/* Return the number of nanoseconds in T. */
static inline int
xtime_nsec (xtime_t t)
{
int ns = t % XTIME_PRECISION;
if (ns < 0)
ns += XTIME_PRECISION;
return ns;
}
#endif
2005-02-25 Paul Eggert <eggert@cs.ucla.edu>
* gethrxtime.m4, xnanosleep.m4: New files.
* gettime.m4 (gl_GETTIME): Check for nanotime.
2005-02-24 Bruno Haible <bruno@clisp.org>
* gettext.m4, intdiv0.m4, intmax.m4, inttypes-pri.m4, lcmessage.m4:
......
# gethrxtime.m4 serial 2
dnl Copyright (C) 2005 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
dnl with or without modifications, as long as this notice is preserved.
dnl Written by Paul Eggert.
AC_DEFUN([gl_GETHRXTIME],
[
AC_LIBSOURCES([gethrxtime.c, gethrxtime.h, xtime.h])
AC_REQUIRE([gl_ARITHMETIC_HRTIME_T])
AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
AC_REQUIRE([gl_XTIME])
AC_CHECK_DECLS([gethrtime], [], [], [#include <time.h>])
case $ac_cv_have_decl_gethrtime,$gl_cv_arithmetic_hrtime_t in
yes,yes) ;;
*)
AC_LIBOBJ([gethrxtime])
gl_PREREQ_GETHRXTIME;;
esac
])
# Test whether hrtime_t is an arithmetic type.
# It is not arithmetic in older Solaris c89 (which insists on
# not having a long long int type).
AC_DEFUN([gl_ARITHMETIC_HRTIME_T],
[
AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
AC_CACHE_CHECK([for arithmetic hrtime_t], gl_cv_arithmetic_hrtime_t,
[AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM([#include <time.h>],
[hrtime_t x = 0; return x/x;])],
[gl_cv_arithmetic_hrtime_t=yes],
[gl_cv_arithmetic_hrtime_t=no])])
if test $gl_cv_arithmetic_hrtime_t = yes; then
AC_DEFINE([HAVE_ARITHMETIC_HRTIME_T], 1,
[Define if you have an arithmetic hrtime_t type.])
fi
])
# Prerequisites of lib/xtime.h.
AC_DEFUN([gl_XTIME],
[
AC_REQUIRE([AC_C_INLINE])
AC_REQUIRE([gl_AC_TYPE_LONG_LONG])
:
])
# Prerequisites of lib/gethrxtime.c.
AC_DEFUN([gl_PREREQ_GETHRXTIME],
[
AC_REQUIRE([AC_HEADER_TIME])
AC_REQUIRE([gl_CLOCK_TIME])
AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
AC_CHECK_FUNCS_ONCE(gettimeofday microuptime nanouptime)
if test $ac_cv_func_nanouptime != yes; then
LIB_GETHRXTIME=
AC_CACHE_CHECK([whether CLOCK_MONOTONIC is defined],
gl_cv_have_CLOCK_MONOTONIC,
[AC_EGREP_CPP([have_CLOCK_MONOTONIC],
[
# include <time.h>
# ifdef CLOCK_MONOTONIC
have_CLOCK_MONOTONIC
# endif
],
gl_cv_have_CLOCK_MONOTONIC=yes,
gl_cv_have_CLOCK_MONOTONIC=no)])
if test $gl_cv_have_CLOCK_MONOTONIC = yes; then
LIB_GETHRXTIME=$LIB_CLOCK_GETTIME
fi
AC_SUBST([LIB_GETHRXTIME])
fi
])
# gettime.m4 serial 3
dnl Copyright (C) 2002, 2004 Free Software Foundation, Inc.
# gettime.m4 serial 5
dnl Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
dnl with or without modifications, as long as this notice is preserved.
AC_DEFUN([gl_GETTIME],
[
AC_LIBSOURCES([gettime.c])
AC_LIBOBJ([gettime])
dnl Prerequisites of lib/gettime.c.
AC_REQUIRE([gl_CLOCK_TIME])
AC_REQUIRE([gl_TIMESPEC])
AC_CHECK_FUNCS_ONCE(gettimeofday)
AC_CHECK_FUNCS_ONCE(gettimeofday nanotime)
])
# xnanosleep.m4 serial 1
dnl Copyright (C) 2005 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
dnl with or without modifications, as long as this notice is preserved.
dnl Written by Paul Eggert.
AC_DEFUN([gl_XNANOSLEEP],
[
AC_LIBSOURCES([xnanosleep.c, xnanosleep.h])
AC_LIBOBJ([xnanosleep])
dnl Prerequisites of lib/xnanosleep.c.
AC_REQUIRE([gl_PREREQ_GETHRXTIME])
LIB_XNANOSLEEP=
case $LIB_GETHRXTIME in
?*)
AC_CACHE_CHECK([whether __linux__ is defined],
gl_cv_have___linux__,
[AC_EGREP_CPP([have___linux__],
[
# ifdef __linux__
have___linux__
# endif
],
gl_cv_have___linux__=yes,
gl_cv_have___linux__=no)])
if test $gl_cv_have___linux__ = yes; then
LIB_XNANOSLEEP=$LIB_GETHRXTIME
fi;;
esac
AC_SUBST([LIB_XNANOSLEEP])
])
Description:
Get high resolution real time.
Files:
lib/xtime.h
lib/gethrxtime.c
m4/gethrxtime.m4
m4/clock_time.m4
m4/longlong.m4
Depends-on:
extensions
configure.ac:
gl_GETHRXTIME
Makefile.am:
Include:
#include "xtime.h"
License:
GPL
Maintainer:
Paul Eggert
......@@ -4,15 +4,16 @@ a more convenient interface to nanosleep
Files:
lib/xnanosleep.h
lib/xnanosleep.c
m4/xnanosleep.m4
Depends-on:
timespec
xalloc
gethrxtime
configure.ac:
gl_XNANOSLEEP
Makefile.am:
lib_SOURCES += xnanosleep.h xnanosleep.c
Include:
"xnanosleep.h"
......@@ -22,4 +23,3 @@ GPL
Maintainer:
Paul Eggert, Jim Meyering
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment