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 "arg-nonnull.h" 37 #include "verify.h" 38 39 /* Inverse resolution of timespec timestamps (in units per second), 40 and log base 10 of the inverse resolution. */ 41 42 enum { TIMESPEC_HZ = 1000000000 }; 43 enum { LOG10_TIMESPEC_HZ = 9 }; 44 45 /* Obsolescent names for backward compatibility. 46 They are misnomers, because TIMESPEC_RESOLUTION is not a resolution. */ 47 48 enum { TIMESPEC_RESOLUTION = TIMESPEC_HZ }; 49 enum { LOG10_TIMESPEC_RESOLUTION = LOG10_TIMESPEC_HZ }; 50 51 /* Return a timespec with seconds S and nanoseconds NS. */ 52 53 _GL_TIMESPEC_INLINE struct timespec 54 make_timespec (time_t s, long int ns) 55 { 56 struct timespec r; 57 r.tv_sec = s; 58 r.tv_nsec = ns; 59 return r; 60 } 61 62 /* Return negative, zero, positive if A < B, A == B, A > B, respectively. 63 64 For each timestamp T, this code assumes that either: 65 66 * T.tv_nsec is in the range 0..999999999; or 67 * T.tv_sec corresponds to a valid leap second on a host that supports 68 leap seconds, and T.tv_nsec is in the range 1000000000..1999999999; or 69 * T.tv_sec is the minimum time_t value and T.tv_nsec is -1; or 70 T.tv_sec is the maximum time_t value and T.tv_nsec is 2000000000. 71 This allows for special struct timespec values that are less or 72 greater than all possible valid timestamps. 73 74 In all these cases, it is safe to subtract two tv_nsec values and 75 convert the result to integer without worrying about overflow on 76 any platform of interest to the GNU project, since all such 77 platforms have 32-bit int or wider. 78 79 Replacing "a.tv_nsec - b.tv_nsec" with something like 80 "a.tv_nsec < b.tv_nsec ? -1 : a.tv_nsec > b.tv_nsec" would cause 81 this function to work in some cases where the above assumption is 82 violated, but not in all cases (e.g., a.tv_sec==1, a.tv_nsec==-2, 83 b.tv_sec==0, b.tv_nsec==999999999) and is arguably not worth the 84 extra instructions. Using a subtraction has the advantage of 85 detecting some invalid cases on platforms that detect integer 86 overflow. */ 87 88 _GL_TIMESPEC_INLINE int _GL_ATTRIBUTE_PURE 89 timespec_cmp (struct timespec a, struct timespec b) 90 { 91 if (a.tv_sec < b.tv_sec) 92 return -1; 93 if (a.tv_sec > b.tv_sec) 94 return 1; 95 96 /* Pacify gcc -Wstrict-overflow (bleeding-edge circa 2017-10-02). See: 97 https://lists.gnu.org/r/bug-gnulib/2017-10/msg00006.html */ 98 assume (-1 <= a.tv_nsec && a.tv_nsec <= 2 * TIMESPEC_HZ); 99 assume (-1 <= b.tv_nsec && b.tv_nsec <= 2 * TIMESPEC_HZ); 100 101 return a.tv_nsec - b.tv_nsec; 102 } 103 104 /* Return -1, 0, 1, depending on the sign of A. A.tv_nsec must be 105 nonnegative. */ 106 _GL_TIMESPEC_INLINE int _GL_ATTRIBUTE_PURE 107 timespec_sign (struct timespec a) 108 { 109 return a.tv_sec < 0 ? -1 : a.tv_sec || a.tv_nsec; 110 } 111 112 struct timespec timespec_add (struct timespec, struct timespec) 113 _GL_ATTRIBUTE_CONST; 114 struct timespec timespec_sub (struct timespec, struct timespec) 115 _GL_ATTRIBUTE_CONST; 116 struct timespec dtotimespec (double) 117 _GL_ATTRIBUTE_CONST; 118 119 /* Return an approximation to A, of type 'double'. */ 120 _GL_TIMESPEC_INLINE double 121 timespectod (struct timespec a) 122 { 123 return a.tv_sec + a.tv_nsec / 1e9; 124 } 125 126 struct timespec current_timespec (void); 127 void gettime (struct timespec *) _GL_ARG_NONNULL ((1)); 128 int settime (struct timespec const *) _GL_ARG_NONNULL ((1)); 129 130 #ifdef __cplusplus 131 } 132 #endif 133 134 _GL_INLINE_HEADER_END 135 136 #endif 137