1 /* timespec -- System time interface
2 
3    Copyright (C) 2000, 2002, 2004-2005, 2007, 2009-2018 Free Software
4    Foundation, Inc.
5 
6    This program is free software: you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10 
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15 
16    You should have received a copy of the GNU General Public License
17    along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
18 
19 #if ! defined TIMESPEC_H
20 # define TIMESPEC_H
21 
22 # include <time.h>
23 
24 #ifndef _GL_INLINE_HEADER_BEGIN
25  #error "Please include config.h first."
26 #endif
27 _GL_INLINE_HEADER_BEGIN
28 #ifndef _GL_TIMESPEC_INLINE
29 # define _GL_TIMESPEC_INLINE _GL_INLINE
30 #endif
31 
32 #ifdef __cplusplus
33 extern "C" {
34 #endif
35 
36 #include "verify.h"
37 
38 /* Resolution of timespec timestamps (in units per second), and log
39    base 10 of the resolution.  */
40 
41 enum { TIMESPEC_RESOLUTION = 1000000000 };
42 enum { LOG10_TIMESPEC_RESOLUTION = 9 };
43 
44 /* Return a timespec with seconds S and nanoseconds NS.  */
45 
46 _GL_TIMESPEC_INLINE struct timespec
make_timespec(time_t s,long int ns)47 make_timespec (time_t s, long int ns)
48 {
49   struct timespec r;
50   r.tv_sec = s;
51   r.tv_nsec = ns;
52   return r;
53 }
54 
55 /* Return negative, zero, positive if A < B, A == B, A > B, respectively.
56 
57    For each timestamp T, this code assumes that either:
58 
59      * T.tv_nsec is in the range 0..999999999; or
60      * T.tv_sec corresponds to a valid leap second on a host that supports
61        leap seconds, and T.tv_nsec is in the range 1000000000..1999999999; or
62      * T.tv_sec is the minimum time_t value and T.tv_nsec is -1; or
63        T.tv_sec is the maximum time_t value and T.tv_nsec is 2000000000.
64        This allows for special struct timespec values that are less or
65        greater than all possible valid timestamps.
66 
67    In all these cases, it is safe to subtract two tv_nsec values and
68    convert the result to integer without worrying about overflow on
69    any platform of interest to the GNU project, since all such
70    platforms have 32-bit int or wider.
71 
72    Replacing "a.tv_nsec - b.tv_nsec" with something like
73    "a.tv_nsec < b.tv_nsec ? -1 : a.tv_nsec > b.tv_nsec" would cause
74    this function to work in some cases where the above assumption is
75    violated, but not in all cases (e.g., a.tv_sec==1, a.tv_nsec==-2,
76    b.tv_sec==0, b.tv_nsec==999999999) and is arguably not worth the
77    extra instructions.  Using a subtraction has the advantage of
78    detecting some invalid cases on platforms that detect integer
79    overflow.  */
80 
81 _GL_TIMESPEC_INLINE int _GL_ATTRIBUTE_PURE
timespec_cmp(struct timespec a,struct timespec b)82 timespec_cmp (struct timespec a, struct timespec b)
83 {
84   if (a.tv_sec < b.tv_sec)
85     return -1;
86   if (a.tv_sec > b.tv_sec)
87     return 1;
88 
89   /* Pacify gcc -Wstrict-overflow (bleeding-edge circa 2017-10-02).  See:
90      https://lists.gnu.org/r/bug-gnulib/2017-10/msg00006.html  */
91   assume (-1 <= a.tv_nsec && a.tv_nsec <= 2 * TIMESPEC_RESOLUTION);
92   assume (-1 <= b.tv_nsec && b.tv_nsec <= 2 * TIMESPEC_RESOLUTION);
93 
94   return a.tv_nsec - b.tv_nsec;
95 }
96 
97 /* Return -1, 0, 1, depending on the sign of A.  A.tv_nsec must be
98    nonnegative.  */
99 _GL_TIMESPEC_INLINE int _GL_ATTRIBUTE_PURE
timespec_sign(struct timespec a)100 timespec_sign (struct timespec a)
101 {
102   return a.tv_sec < 0 ? -1 : a.tv_sec || a.tv_nsec;
103 }
104 
105 struct timespec timespec_add (struct timespec, struct timespec)
106   _GL_ATTRIBUTE_CONST;
107 struct timespec timespec_sub (struct timespec, struct timespec)
108   _GL_ATTRIBUTE_CONST;
109 struct timespec dtotimespec (double)
110   _GL_ATTRIBUTE_CONST;
111 
112 /* Return an approximation to A, of type 'double'.  */
113 _GL_TIMESPEC_INLINE double
timespectod(struct timespec a)114 timespectod (struct timespec a)
115 {
116   return a.tv_sec + a.tv_nsec / 1e9;
117 }
118 
119 void gettime (struct timespec *);
120 int settime (struct timespec const *);
121 
122 #ifdef __cplusplus
123 }
124 #endif
125 
126 _GL_INLINE_HEADER_END
127 
128 #endif
129