]> git.ozlabs.org Git - ccan/blob - ccan/time/time.h
time: make trivial functions inline
[ccan] / ccan / time / time.h
1 /* Licensed under BSD-MIT - see LICENSE file for details */
2 #ifndef CCAN_TIME_H
3 #define CCAN_TIME_H
4 #include "config.h"
5 #include <sys/time.h>
6 #if HAVE_STRUCT_TIMESPEC
7 #include <time.h>
8 #else
9 struct timespec {
10         time_t   tv_sec;        /* seconds */
11         long     tv_nsec;       /* nanoseconds */
12 };
13 #endif
14 #include <stdint.h>
15 #include <stdbool.h>
16
17 #ifdef DEBUG
18 #include <ccan/str/str.h>
19 #define TIME_CHECK(t) \
20         time_check((t), __FILE__ ":" stringify(__LINE__) " (" stringify(t) ") ")
21 #else
22 #define TIME_CHECK(t) (t)
23 #endif
24
25 /**
26  * time_check - check if a time is malformed.
27  * @in: the time to check (returned)
28  * @abortstr: the string to print to stderr before aborting (if set).
29  *
30  * This can be used to make sure a time isn't negative and doesn't
31  * have a tv_nsec >= 1000000000.  If it is, and @abortstr is non-NULL,
32  * that will be printed and abort() is called.  Otherwise, if
33  * @abortstr is NULL then the returned timespec will be normalized and
34  * tv_sec set to 0 if it was negative.
35  *
36  * Note that if ccan/time is compiled with DEBUG, then it will call this
37  * for all passed and returned times.
38  *
39  * Example:
40  *      printf("Now is %lu seconds since epoch\n",
41  *              (long)time_check(time_now(), "time_now() failed?").tv_sec);
42  */
43 struct timespec time_check(struct timespec in, const char *abortstr);
44
45 /**
46  * time_now - return the current time
47  *
48  * Example:
49  *      printf("Now is %lu seconds since epoch\n", (long)time_now().tv_sec);
50  */
51 struct timespec time_now(void);
52
53 /**
54  * time_greater - is a after b?
55  * @a: one time.
56  * @b: another time.
57  *
58  * Example:
59  *      static bool timed_out(const struct timespec *start)
60  *      {
61  *      #define TIMEOUT time_from_msec(1000)
62  *              return time_greater(time_now(), time_add(*start, TIMEOUT));
63  *      }
64  */
65 static inline bool time_greater(struct timespec a, struct timespec b)
66 {
67         if (TIME_CHECK(a).tv_sec > TIME_CHECK(b).tv_sec)
68                 return true;
69         else if (a.tv_sec < b.tv_sec)
70                  return false;
71
72         return a.tv_nsec > b.tv_nsec;
73 }
74
75 /**
76  * time_less - is a before b?
77  * @a: one time.
78  * @b: another time.
79  *
80  * Example:
81  *      static bool still_valid(const struct timespec *start)
82  *      {
83  *      #define TIMEOUT time_from_msec(1000)
84  *              return time_less(time_now(), time_add(*start, TIMEOUT));
85  *      }
86  */
87 static inline bool time_less(struct timespec a, struct timespec b)
88 {
89         if (TIME_CHECK(a).tv_sec < TIME_CHECK(b).tv_sec)
90                 return true;
91         else if (a.tv_sec > b.tv_sec)
92                  return false;
93
94         return a.tv_nsec < b.tv_nsec;
95 }
96
97 /**
98  * time_eq - is a equal to b?
99  * @a: one time.
100  * @b: another time.
101  *
102  * Example:
103  *      #include <sys/types.h>
104  *      #include <sys/wait.h>
105  *
106  *      // Can we fork in under a nanosecond?
107  *      static bool fast_fork(void)
108  *      {
109  *              struct timespec start = time_now();
110  *              if (fork() != 0) {
111  *                      exit(0);
112  *              }
113  *              wait(NULL);
114  *              return time_eq(start, time_now());
115  *      }
116  */
117 static inline bool time_eq(struct timespec a, struct timespec b)
118 {
119         return TIME_CHECK(a).tv_sec == TIME_CHECK(b).tv_sec
120                 && a.tv_nsec == b.tv_nsec;
121 }
122
123 /**
124  * time_sub - subtract two times
125  * @recent: the larger (more recent) time.
126  * @old: the smaller (less recent) time.
127  *
128  * This returns a well formed struct timespec.
129  *
130  * Example:
131  *      static bool was_recent(const struct timespec *start)
132  *      {
133  *              return time_sub(time_now(), *start).tv_sec < 1;
134  *      }
135  */
136 static inline struct timespec time_sub(struct timespec recent,
137                                        struct timespec old)
138 {
139         struct timespec diff;
140
141         diff.tv_sec = TIME_CHECK(recent).tv_sec - TIME_CHECK(old).tv_sec;
142         if (old.tv_nsec > recent.tv_nsec) {
143                 diff.tv_sec--;
144                 diff.tv_nsec = 1000000000 + recent.tv_nsec - old.tv_nsec;
145         } else
146                 diff.tv_nsec = recent.tv_nsec - old.tv_nsec;
147
148         return TIME_CHECK(diff);
149 }
150
151 /**
152  * time_add - add two times
153  * @a: one time.
154  * @b: another time.
155  *
156  * The times must not overflow, or the results are undefined.
157  *
158  * Example:
159  *      // We do one every second.
160  *      static struct timespec next_time(void)
161  *      {
162  *              return time_add(time_now(), time_from_msec(1000));
163  *      }
164  */
165 static inline struct timespec time_add(struct timespec a, struct timespec b)
166 {
167         struct timespec sum;
168
169         sum.tv_sec = TIME_CHECK(a).tv_sec + TIME_CHECK(b).tv_sec;
170         sum.tv_nsec = a.tv_nsec + b.tv_nsec;
171         if (sum.tv_nsec >= 1000000000) {
172                 sum.tv_sec++;
173                 sum.tv_nsec -= 1000000000;
174         }
175         return TIME_CHECK(sum);
176 }
177
178 /**
179  * time_divide - divide a time by a value.
180  * @t: a time.
181  * @div: number to divide it by.
182  *
183  * Example:
184  *      // How long does it take to do a fork?
185  *      static struct timespec forking_time(void)
186  *      {
187  *              struct timespec start = time_now();
188  *              unsigned int i;
189  *
190  *              for (i = 0; i < 1000; i++) {
191  *                      if (fork() != 0) {
192  *                              exit(0);
193  *                      }
194  *                      wait(NULL);
195  *              }
196  *              return time_divide(time_sub(time_now(), start), i);
197  *      }
198  */
199 struct timespec time_divide(struct timespec t, unsigned long div);
200
201 /**
202  * time_multiply - multiply a time by a value.
203  * @t: a time.
204  * @mult: number to multiply it by.
205  *
206  * Example:
207  *      ...
208  *      printf("Time to do 100000 forks would be %u sec\n",
209  *             (unsigned)time_multiply(forking_time(), 1000000).tv_sec);
210  */
211 struct timespec time_multiply(struct timespec t, unsigned long mult);
212
213 /**
214  * time_to_msec - return number of milliseconds
215  * @t: a time
216  *
217  * It's often more convenient to deal with time values as
218  * milliseconds.  Note that this will fit into a 32-bit variable if
219  * it's a time difference of less than ~7 weeks.
220  *
221  * Example:
222  *      ...
223  *      printf("Forking time is %u msec\n",
224  *             (unsigned)time_to_msec(forking_time()));
225  */
226 static inline uint64_t time_to_msec(struct timespec t)
227 {
228         uint64_t msec;
229
230         msec = TIME_CHECK(t).tv_nsec / 1000000 + (uint64_t)t.tv_sec * 1000;
231         return msec;
232 }
233
234 /**
235  * time_to_usec - return number of microseconds
236  * @t: a time
237  *
238  * It's often more convenient to deal with time values as
239  * microseconds.  Note that this will fit into a 32-bit variable if
240  * it's a time difference of less than ~1 hour.
241  *
242  * Example:
243  *      ...
244  *      printf("Forking time is %u usec\n",
245  *             (unsigned)time_to_usec(forking_time()));
246  *
247  */
248 static inline uint64_t time_to_usec(struct timespec t)
249 {
250         uint64_t usec;
251
252         usec = TIME_CHECK(t).tv_nsec / 1000 + (uint64_t)t.tv_sec * 1000000;
253         return usec;
254 }
255
256 /**
257  * time_to_nsec - return number of nanoseconds
258  * @t: a time
259  *
260  * It's sometimes more convenient to deal with time values as
261  * nanoseconds.  Note that this will fit into a 32-bit variable if
262  * it's a time difference of less than ~4 seconds.
263  *
264  * Example:
265  *      ...
266  *      printf("Forking time is %u nsec\n",
267  *             (unsigned)time_to_nsec(forking_time()));
268  *
269  */
270 static inline uint64_t time_to_nsec(struct timespec t)
271 {
272         uint64_t nsec;
273
274         nsec = TIME_CHECK(t).tv_nsec + (uint64_t)t.tv_sec * 1000000000;
275         return nsec;
276 }
277
278 /**
279  * time_from_msec - convert milliseconds to a timespec
280  * @msec: time in milliseconds
281  *
282  * Example:
283  *      // 1/2 second timeout
284  *      #define TIMEOUT time_from_msec(500)
285  */
286 static inline struct timespec time_from_msec(uint64_t msec)
287 {
288         struct timespec t;
289
290         t.tv_nsec = (msec % 1000) * 1000000;
291         t.tv_sec = msec / 1000;
292         return TIME_CHECK(t);
293 }
294
295 /**
296  * time_from_usec - convert microseconds to a timespec
297  * @usec: time in microseconds
298  *
299  * Example:
300  *      // 1/2 second timeout
301  *      #define TIMEOUT time_from_usec(500000)
302  */
303 static inline struct timespec time_from_usec(uint64_t usec)
304 {
305         struct timespec t;
306
307         t.tv_nsec = (usec % 1000000) * 1000;
308         t.tv_sec = usec / 1000000;
309         return TIME_CHECK(t);
310 }
311
312 /**
313  * time_from_nsec - convert nanoseconds to a timespec
314  * @nsec: time in nanoseconds
315  *
316  * Example:
317  *      // 1/2 second timeout
318  *      #define TIMEOUT time_from_nsec(500000000)
319  */
320 static inline struct timespec time_from_nsec(uint64_t nsec)
321 {
322         struct timespec t;
323
324         t.tv_nsec = nsec % 1000000000;
325         t.tv_sec = nsec / 1000000000;
326         return TIME_CHECK(t);
327 }
328
329 /**
330  * timespec_to_timeval - convert a timespec to a timeval.
331  * @ts: a timespec.
332  *
333  * Example:
334  *      struct timeval tv;
335  *
336  *      tv = timespec_to_timeval(time_now());
337  */
338 static inline struct timeval timespec_to_timeval(struct timespec ts)
339 {
340         struct timeval tv;
341         tv.tv_sec = ts.tv_sec;
342         tv.tv_usec = ts.tv_nsec / 1000;
343         return tv;
344 }
345
346 /**
347  * timeval_to_timespec - convert a timeval to a timespec.
348  * @tv: a timeval.
349  *
350  * Example:
351  *      struct timeval tv = { 0, 500 };
352  *      struct timespec ts;
353  *
354  *      ts = timeval_to_timespec(tv);
355  */
356 static inline struct timespec timeval_to_timespec(struct timeval tv)
357 {
358         struct timespec ts;
359         ts.tv_sec = tv.tv_sec;
360         ts.tv_nsec = tv.tv_usec * 1000;
361         return ts;
362 }
363 #endif /* CCAN_TIME_H */