Blame src/gl/timespec.h

Packit aea12f
/* timespec -- System time interface
Packit aea12f
Packit Service 991b93
   Copyright (C) 2000, 2002, 2004-2005, 2007, 2009-2020 Free Software
Packit aea12f
   Foundation, Inc.
Packit aea12f
Packit aea12f
   This program is free software: you can redistribute it and/or modify
Packit aea12f
   it under the terms of the GNU General Public License as published by
Packit aea12f
   the Free Software Foundation; either version 3 of the License, or
Packit aea12f
   (at your option) any later version.
Packit aea12f
Packit aea12f
   This program is distributed in the hope that it will be useful,
Packit aea12f
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit aea12f
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit aea12f
   GNU General Public License for more details.
Packit aea12f
Packit aea12f
   You should have received a copy of the GNU General Public License
Packit aea12f
   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
Packit aea12f
Packit aea12f
#if ! defined TIMESPEC_H
Packit aea12f
#define TIMESPEC_H
Packit aea12f
Packit aea12f
#include <time.h>
Packit aea12f
Packit aea12f
#ifndef _GL_INLINE_HEADER_BEGIN
Packit aea12f
 #error "Please include config.h first."
Packit aea12f
#endif
Packit aea12f
_GL_INLINE_HEADER_BEGIN
Packit aea12f
#ifndef _GL_TIMESPEC_INLINE
Packit aea12f
# define _GL_TIMESPEC_INLINE _GL_INLINE
Packit aea12f
#endif
Packit aea12f
Packit aea12f
#ifdef __cplusplus
Packit aea12f
extern "C" {
Packit aea12f
#endif
Packit aea12f
Packit aea12f
#include "arg-nonnull.h"
Packit aea12f
#include "verify.h"
Packit aea12f
Packit aea12f
/* Inverse resolution of timespec timestamps (in units per second),
Packit aea12f
   and log base 10 of the inverse resolution.  */
Packit aea12f
Packit aea12f
enum { TIMESPEC_HZ = 1000000000 };
Packit aea12f
enum { LOG10_TIMESPEC_HZ = 9 };
Packit aea12f
Packit aea12f
/* Obsolescent names for backward compatibility.
Packit aea12f
   They are misnomers, because TIMESPEC_RESOLUTION is not a resolution.  */
Packit aea12f
Packit aea12f
enum { TIMESPEC_RESOLUTION = TIMESPEC_HZ };
Packit aea12f
enum { LOG10_TIMESPEC_RESOLUTION = LOG10_TIMESPEC_HZ };
Packit aea12f
Packit aea12f
/* Return a timespec with seconds S and nanoseconds NS.  */
Packit aea12f
Packit aea12f
_GL_TIMESPEC_INLINE struct timespec
Packit aea12f
make_timespec (time_t s, long int ns)
Packit aea12f
{
Packit aea12f
  struct timespec r;
Packit aea12f
  r.tv_sec = s;
Packit aea12f
  r.tv_nsec = ns;
Packit aea12f
  return r;
Packit aea12f
}
Packit aea12f
Packit aea12f
/* Return negative, zero, positive if A < B, A == B, A > B, respectively.
Packit aea12f
Packit aea12f
   For each timestamp T, this code assumes that either:
Packit aea12f
Packit aea12f
     * T.tv_nsec is in the range 0..999999999; or
Packit aea12f
     * T.tv_sec corresponds to a valid leap second on a host that supports
Packit aea12f
       leap seconds, and T.tv_nsec is in the range 1000000000..1999999999; or
Packit aea12f
     * T.tv_sec is the minimum time_t value and T.tv_nsec is -1; or
Packit aea12f
       T.tv_sec is the maximum time_t value and T.tv_nsec is 2000000000.
Packit aea12f
       This allows for special struct timespec values that are less or
Packit aea12f
       greater than all possible valid timestamps.
Packit aea12f
Packit aea12f
   In all these cases, it is safe to subtract two tv_nsec values and
Packit aea12f
   convert the result to integer without worrying about overflow on
Packit aea12f
   any platform of interest to the GNU project, since all such
Packit aea12f
   platforms have 32-bit int or wider.
Packit aea12f
Packit aea12f
   Replacing "a.tv_nsec - b.tv_nsec" with something like
Packit aea12f
   "a.tv_nsec < b.tv_nsec ? -1 : a.tv_nsec > b.tv_nsec" would cause
Packit aea12f
   this function to work in some cases where the above assumption is
Packit aea12f
   violated, but not in all cases (e.g., a.tv_sec==1, a.tv_nsec==-2,
Packit aea12f
   b.tv_sec==0, b.tv_nsec==999999999) and is arguably not worth the
Packit aea12f
   extra instructions.  Using a subtraction has the advantage of
Packit aea12f
   detecting some invalid cases on platforms that detect integer
Packit aea12f
   overflow.  */
Packit aea12f
Packit aea12f
_GL_TIMESPEC_INLINE int _GL_ATTRIBUTE_PURE
Packit aea12f
timespec_cmp (struct timespec a, struct timespec b)
Packit aea12f
{
Packit aea12f
  if (a.tv_sec < b.tv_sec)
Packit aea12f
    return -1;
Packit aea12f
  if (a.tv_sec > b.tv_sec)
Packit aea12f
    return 1;
Packit aea12f
Packit aea12f
  /* Pacify gcc -Wstrict-overflow (bleeding-edge circa 2017-10-02).  See:
Packit aea12f
     https://lists.gnu.org/r/bug-gnulib/2017-10/msg00006.html  */
Packit aea12f
  assume (-1 <= a.tv_nsec && a.tv_nsec <= 2 * TIMESPEC_HZ);
Packit aea12f
  assume (-1 <= b.tv_nsec && b.tv_nsec <= 2 * TIMESPEC_HZ);
Packit aea12f
Packit aea12f
  return a.tv_nsec - b.tv_nsec;
Packit aea12f
}
Packit aea12f
Packit aea12f
/* Return -1, 0, 1, depending on the sign of A.  A.tv_nsec must be
Packit aea12f
   nonnegative.  */
Packit aea12f
_GL_TIMESPEC_INLINE int _GL_ATTRIBUTE_PURE
Packit aea12f
timespec_sign (struct timespec a)
Packit aea12f
{
Packit aea12f
  return a.tv_sec < 0 ? -1 : a.tv_sec || a.tv_nsec;
Packit aea12f
}
Packit aea12f
Packit aea12f
struct timespec timespec_add (struct timespec, struct timespec)
Packit aea12f
  _GL_ATTRIBUTE_CONST;
Packit aea12f
struct timespec timespec_sub (struct timespec, struct timespec)
Packit aea12f
  _GL_ATTRIBUTE_CONST;
Packit aea12f
struct timespec dtotimespec (double)
Packit aea12f
  _GL_ATTRIBUTE_CONST;
Packit aea12f
Packit aea12f
/* Return an approximation to A, of type 'double'.  */
Packit aea12f
_GL_TIMESPEC_INLINE double
Packit aea12f
timespectod (struct timespec a)
Packit aea12f
{
Packit aea12f
  return a.tv_sec + a.tv_nsec / 1e9;
Packit aea12f
}
Packit aea12f
Packit aea12f
struct timespec current_timespec (void);
Packit aea12f
void gettime (struct timespec *) _GL_ARG_NONNULL ((1));
Packit aea12f
int settime (struct timespec const *) _GL_ARG_NONNULL ((1));
Packit aea12f
Packit aea12f
#ifdef __cplusplus
Packit aea12f
}
Packit aea12f
#endif
Packit aea12f
Packit aea12f
_GL_INLINE_HEADER_END
Packit aea12f
Packit aea12f
#endif