]> git.ozlabs.org Git - ccan/blob - ccan/time/time.h
time: split absolute and relative times.
[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 #define TIMEREL_CHECK(t) \
22         timerel_check((t), __FILE__ ":" stringify(__LINE__) " (" stringify(t) ") ")
23 #define TIMEABS_CHECK(t) \
24         timeabs_check((t), __FILE__ ":" stringify(__LINE__) " (" stringify(t) ") ")
25 #else
26 #define TIME_CHECK(t) (t)
27 #define TIMEREL_CHECK(t) (t)
28 #define TIMEABS_CHECK(t) (t)
29 #endif
30
31 /**
32  * struct timerel - a relative time.
33  * @ts: the actual timespec value.
34  *
35  * For example, 1 second: ts.tv_sec = 1, ts.tv_nsec = 0
36  */
37 struct timerel {
38         struct timespec ts;
39 };
40
41 /**
42  * struct timeabs - an absolue time.
43  * @ts: the actual timespec value.
44  *
45  * For example, Midnight UTC January 1st, 1970: ts.tv_sec = 0, ts.tv_nsec = 0
46  */
47 struct timeabs {
48         struct timespec ts;
49 };
50
51 struct timespec time_check_(struct timespec in, const char *abortstr);
52
53 /**
54  * timerel_check - check if a relative time is malformed.
55  * @in: the relative time to check (returned)
56  * @abortstr: the string to print to stderr before aborting (if set).
57  *
58  * This can be used to make sure a time isn't negative and doesn't
59  * have a tv_nsec >= 1000000000.  If it is, and @abortstr is non-NULL,
60  * that will be printed and abort() is called.  Otherwise, if
61  * @abortstr is NULL then the returned timerel will be normalized and
62  * tv_sec set to 0 if it was negative.
63  *
64  * Note that if ccan/time is compiled with DEBUG, then it will call this
65  * for all passed and returned times.
66  *
67  * Example:
68  *      printf("Time to calc this was %lu nanoseconds\n",
69  *              (long)timerel_check(time_between(time_now(), time_now()),
70  *                                  "time_now() failed?").ts.tv_nsec);
71  */
72 struct timerel timerel_check(struct timerel in, const char *abortstr);
73
74 /**
75  * timeabs_check - check if an absolute time is malformed.
76  * @in: the relative time to check (returned)
77  * @abortstr: the string to print to stderr before aborting (if set).
78  *
79  * This can be used to make sure a time isn't negative and doesn't
80  * have a tv_nsec >= 1000000000.  If it is, and @abortstr is non-NULL,
81  * that will be printed and abort() is called.  Otherwise, if
82  * @abortstr is NULL then the returned timeabs will be normalized and
83  * tv_sec set to 0 if it was negative.
84  *
85  * Note that if ccan/time is compiled with DEBUG, then it will call this
86  * for all passed and returned times.
87  *
88  * Example:
89  *      printf("Now is %lu seconds since epoch\n",
90  *              (long)timeabs_check(time_now(), "time_now failed?").ts.tv_sec);
91  */
92 struct timeabs timeabs_check(struct timeabs in, const char *abortstr);
93
94 /**
95  * time_now - return the current time
96  *
97  * Example:
98  *      printf("Now is %lu seconds since epoch\n", (long)time_now().ts.tv_sec);
99  */
100 struct timeabs time_now(void);
101
102 static inline bool time_greater_(struct timespec a, struct timespec b)
103 {
104         if (TIME_CHECK(a).tv_sec > TIME_CHECK(b).tv_sec)
105                 return true;
106         else if (a.tv_sec < b.tv_sec)
107                  return false;
108
109         return a.tv_nsec > b.tv_nsec;
110 }
111
112 /**
113  * time_after - is a after b?
114  * @a: one abstime.
115  * @b: another abstime.
116  *
117  * Example:
118  *      static bool timed_out(const struct timeabs *start)
119  *      {
120  *      #define TIMEOUT time_from_msec(1000)
121  *              return time_after(time_now(), timeabs_add(*start, TIMEOUT));
122  *      }
123  */
124 static inline bool time_after(struct timeabs a, struct timeabs b)
125 {
126         return time_greater_(a.ts, b.ts);
127 }
128
129 /**
130  * time_greater - is a greater than b?
131  * @a: one reltime.
132  * @b: another reltime.
133  */
134 static inline bool time_greater(struct timerel a, struct timerel b)
135 {
136         return time_greater_(a.ts, b.ts);
137 }
138
139 static inline bool time_less_(struct timespec a, struct timespec b)
140 {
141         if (TIME_CHECK(a).tv_sec < TIME_CHECK(b).tv_sec)
142                 return true;
143         else if (a.tv_sec > b.tv_sec)
144                  return false;
145
146         return a.tv_nsec < b.tv_nsec;
147 }
148
149 /**
150  * time_before - is a before b?
151  * @a: one absolute time.
152  * @b: another absolute time.
153  *
154  * Example:
155  *      static bool still_valid(const struct timeabs *start)
156  *      {
157  *      #define TIMEOUT time_from_msec(1000)
158  *              return time_before(time_now(), timeabs_add(*start, TIMEOUT));
159  *      }
160  */
161 static inline bool time_before(struct timeabs a, struct timeabs b)
162 {
163         return time_less_(a.ts, b.ts);
164 }
165
166 /**
167  * time_less - is a before b?
168  * @a: one relative time.
169  * @b: another relative time.
170  */
171 static inline bool time_less(struct timerel a, struct timerel b)
172 {
173         return time_less_(a.ts, b.ts);
174 }
175
176 /**
177  * timeabs_eq - is a equal to b?
178  * @a: one absolute time.
179  * @b: another absolute time.
180  *
181  * Example:
182  *      #include <sys/types.h>
183  *      #include <sys/wait.h>
184  *
185  *      // Can we fork in under a nanosecond?
186  *      static bool fast_fork(void)
187  *      {
188  *              struct timeabs start = time_now();
189  *              if (fork() != 0) {
190  *                      exit(0);
191  *              }
192  *              wait(NULL);
193  *              return timeabs_eq(start, time_now());
194  *      }
195  */
196 static inline bool timeabs_eq(struct timeabs a, struct timeabs b)
197 {
198         return TIMEABS_CHECK(a).ts.tv_sec == TIMEABS_CHECK(b).ts.tv_sec
199                 && a.ts.tv_nsec == b.ts.tv_nsec;
200 }
201
202 /**
203  * timerel_eq - is a equal to b?
204  * @a: one relative time.
205  * @b: another relative time.
206  *
207  * Example:
208  *      #include <sys/types.h>
209  *      #include <sys/wait.h>
210  *
211  *      // Can we fork in under a nanosecond?
212  *      static bool fast_fork(void)
213  *      {
214  *              struct timeabs start = time_now();
215  *              struct timerel diff, zero = { .ts = { 0, 0 } };
216  *              if (fork() != 0) {
217  *                      exit(0);
218  *              }
219  *              wait(NULL);
220  *              diff = time_between(start, time_now());
221  *              return timerel_eq(diff, zero);
222  *      }
223  */
224 static inline bool timerel_eq(struct timerel a, struct timerel b)
225 {
226         return TIMEREL_CHECK(a).ts.tv_sec == TIMEREL_CHECK(b).ts.tv_sec
227                 && a.ts.tv_nsec == b.ts.tv_nsec;
228 }
229
230 static inline struct timespec time_sub_(struct timespec recent,
231                                         struct timespec old)
232 {
233         struct timespec diff;
234
235         diff.tv_sec = TIME_CHECK(recent).tv_sec - TIME_CHECK(old).tv_sec;
236         if (old.tv_nsec > recent.tv_nsec) {
237                 diff.tv_sec--;
238                 diff.tv_nsec = 1000000000 + recent.tv_nsec - old.tv_nsec;
239         } else
240                 diff.tv_nsec = recent.tv_nsec - old.tv_nsec;
241
242         return TIME_CHECK(diff);
243 }
244
245 /**
246  * time_sub - subtract two relative times
247  * @a: the larger time.
248  * @b: the smaller time.
249  *
250  * This returns a well formed struct timerel of @a - @b.
251  */
252 static inline struct timerel time_sub(struct timerel a, struct timerel b)
253 {
254         struct timerel t;
255
256         t.ts = time_sub_(a.ts, b.ts);
257         return t;
258 }
259
260 /**
261  * time_between - time between two absolute times
262  * @recent: the larger time.
263  * @old: the smaller time.
264  *
265  * This returns a well formed struct timerel of @a - @b.
266  */
267 static inline struct timerel time_between(struct timeabs recent, struct timeabs old)
268 {
269         struct timerel t;
270
271         t.ts = time_sub_(recent.ts, old.ts);
272         return t;
273 }
274
275 /**
276  * timeabs_sub - subtract a relative time from an absolute time
277  * @abs: the absolute time.
278  * @rel: the relative time.
279  *
280  * This returns a well formed struct timeabs of @a - @b.
281  *
282  * Example:
283  *      // We do one every second.
284  *      static struct timeabs previous_time(void)
285  *      {
286  *              return timeabs_sub(time_now(), time_from_msec(1000));
287  *      }
288  */
289 static inline struct timeabs timeabs_sub(struct timeabs abs, struct timerel rel)
290 {
291         struct timeabs t;
292
293         t.ts = time_sub_(abs.ts, rel.ts);
294         return t;
295 }
296
297 static inline struct timespec time_add_(struct timespec a, struct timespec b)
298 {
299         struct timespec sum;
300
301         sum.tv_sec = TIME_CHECK(a).tv_sec + TIME_CHECK(b).tv_sec;
302         sum.tv_nsec = a.tv_nsec + b.tv_nsec;
303         if (sum.tv_nsec >= 1000000000) {
304                 sum.tv_sec++;
305                 sum.tv_nsec -= 1000000000;
306         }
307         return TIME_CHECK(sum);
308 }
309
310 /**
311  * timeabs_add - add a relative to an absolute time
312  * @a: the absolute time.
313  * @b: a relative time.
314  *
315  * The times must not overflow, or the results are undefined.
316  *
317  * Example:
318  *      // We do one every second.
319  *      static struct timeabs next_time(void)
320  *      {
321  *              return timeabs_add(time_now(), time_from_msec(1000));
322  *      }
323  */
324 static inline struct timeabs timeabs_add(struct timeabs a, struct timerel b)
325 {
326         struct timeabs t;
327
328         t.ts = time_add_(a.ts, b.ts);
329         return t;
330 }
331
332 /**
333  * timerel_add - add two relative times
334  * @a: one relative time.
335  * @b: another relative time.
336  *
337  * The times must not overflow, or the results are undefined.
338  *
339  * Example:
340  *      static struct timerel double_time(struct timerel a)
341  *      {
342  *              return timerel_add(a, a);
343  *      }
344  */
345 static inline struct timerel timerel_add(struct timerel a, struct timerel b)
346 {
347         struct timerel t;
348
349         t.ts = time_add_(a.ts, b.ts);
350         return t;
351 }
352
353 /**
354  * time_divide - divide a time by a value.
355  * @t: a time.
356  * @div: number to divide it by.
357  *
358  * Example:
359  *      // How long does it take to do a fork?
360  *      static struct timerel forking_time(void)
361  *      {
362  *              struct timeabs start = time_now();
363  *              unsigned int i;
364  *
365  *              for (i = 0; i < 1000; i++) {
366  *                      if (fork() != 0) {
367  *                              exit(0);
368  *                      }
369  *                      wait(NULL);
370  *              }
371  *              return time_divide(time_between(time_now(), start), i);
372  *      }
373  */
374 struct timerel time_divide(struct timerel t, unsigned long div);
375
376 /**
377  * time_multiply - multiply a time by a value.
378  * @t: a relative time.
379  * @mult: number to multiply it by.
380  *
381  * Example:
382  *      ...
383  *      printf("Time to do 100000 forks would be %u sec\n",
384  *             (unsigned)time_multiply(forking_time(), 1000000).ts.tv_sec);
385  */
386 struct timerel time_multiply(struct timerel t, unsigned long mult);
387
388 /**
389  * time_to_sec - return number of seconds
390  * @t: a time
391  *
392  * It's often more convenient to deal with time values as seconds.
393  * Note that this will fit into an unsigned 32-bit variable if it's a
394  * time of less than about 136 years.
395  *
396  * Example:
397  *      ...
398  *      printf("Forking time is %u sec\n",
399  *             (unsigned)time_to_sec(forking_time()));
400  */
401 static inline uint64_t time_to_sec(struct timerel t)
402 {
403         return t.ts.tv_sec;
404 }
405
406 /**
407  * time_to_msec - return number of milliseconds
408  * @t: a relative time
409  *
410  * It's often more convenient to deal with time values as
411  * milliseconds.  Note that this will fit into a 32-bit variable if
412  * it's a time difference of less than ~7 weeks.
413  *
414  * Example:
415  *      ...
416  *      printf("Forking time is %u msec\n",
417  *             (unsigned)time_to_msec(forking_time()));
418  */
419 static inline uint64_t time_to_msec(struct timerel t)
420 {
421         uint64_t msec;
422
423         msec = TIMEREL_CHECK(t).ts.tv_nsec/1000000 + (uint64_t)t.ts.tv_sec*1000;
424         return msec;
425 }
426
427 /**
428  * time_to_usec - return number of microseconds
429  * @t: a relative time
430  *
431  * It's often more convenient to deal with time values as
432  * microseconds.  Note that this will fit into a 32-bit variable if
433  * it's a time difference of less than ~1 hour.
434  *
435  * Example:
436  *      ...
437  *      printf("Forking time is %u usec\n",
438  *             (unsigned)time_to_usec(forking_time()));
439  *
440  */
441 static inline uint64_t time_to_usec(struct timerel t)
442 {
443         uint64_t usec;
444
445         usec = TIMEREL_CHECK(t).ts.tv_nsec/1000 + (uint64_t)t.ts.tv_sec*1000000;
446         return usec;
447 }
448
449 /**
450  * time_to_nsec - return number of nanoseconds
451  * @t: a relative time
452  *
453  * It's sometimes more convenient to deal with time values as
454  * nanoseconds.  Note that this will fit into a 32-bit variable if
455  * it's a time difference of less than ~4 seconds.
456  *
457  * Example:
458  *      ...
459  *      printf("Forking time is %u nsec\n",
460  *             (unsigned)time_to_nsec(forking_time()));
461  *
462  */
463 static inline uint64_t time_to_nsec(struct timerel t)
464 {
465         uint64_t nsec;
466
467         nsec = TIMEREL_CHECK(t).ts.tv_nsec + (uint64_t)t.ts.tv_sec * 1000000000;
468         return nsec;
469 }
470
471 /**
472  * time_from_sec - convert seconds to a relative time
473  * @msec: time in seconds
474  *
475  * Example:
476  *      // 1 minute timeout
477  *      #define TIMEOUT time_from_sec(60)
478  */
479 static inline struct timerel time_from_sec(uint64_t sec)
480 {
481         struct timerel t;
482
483         t.ts.tv_nsec = 0;
484         t.ts.tv_sec = sec;
485         return TIMEREL_CHECK(t);
486 }
487
488 /**
489  * time_from_msec - convert milliseconds to a relative time
490  * @msec: time in milliseconds
491  *
492  * Example:
493  *      // 1/2 second timeout
494  *      #define TIMEOUT time_from_msec(500)
495  */
496 static inline struct timerel time_from_msec(uint64_t msec)
497 {
498         struct timerel t;
499
500         t.ts.tv_nsec = (msec % 1000) * 1000000;
501         t.ts.tv_sec = msec / 1000;
502         return TIMEREL_CHECK(t);
503 }
504
505 /**
506  * time_from_usec - convert microseconds to a relative time
507  * @usec: time in microseconds
508  *
509  * Example:
510  *      // 1/2 second timeout
511  *      #define TIMEOUT time_from_usec(500000)
512  */
513 static inline struct timerel time_from_usec(uint64_t usec)
514 {
515         struct timerel t;
516
517         t.ts.tv_nsec = (usec % 1000000) * 1000;
518         t.ts.tv_sec = usec / 1000000;
519         return TIMEREL_CHECK(t);
520 }
521
522 /**
523  * time_from_nsec - convert nanoseconds to a relative time
524  * @nsec: time in nanoseconds
525  *
526  * Example:
527  *      // 1/2 second timeout
528  *      #define TIMEOUT time_from_nsec(500000000)
529  */
530 static inline struct timerel time_from_nsec(uint64_t nsec)
531 {
532         struct timerel t;
533
534         t.ts.tv_nsec = nsec % 1000000000;
535         t.ts.tv_sec = nsec / 1000000000;
536         return TIMEREL_CHECK(t);
537 }
538
539 static inline struct timeval timespec_to_timeval(struct timespec ts)
540 {
541         struct timeval tv;
542         tv.tv_sec = ts.tv_sec;
543         tv.tv_usec = ts.tv_nsec / 1000;
544         return tv;
545 }
546
547 /**
548  * timerel_to_timeval - convert a relative time to a timeval.
549  * @t: a relative time.
550  *
551  * Example:
552  *      struct timerel t = { { 100, 0 } }; // 100 seconds
553  *      struct timeval tv;
554  *
555  *      tv = timerel_to_timeval(t);
556  *      printf("time = %lu.%06u\n", (long)tv.tv_sec, (int)tv.tv_usec);
557  */
558 static inline struct timeval timerel_to_timeval(struct timerel t)
559 {
560         return timespec_to_timeval(t.ts);
561 }
562
563 /**
564  * timeabs_to_timeval - convert an absolute time to a timeval.
565  * @t: an absolute time.
566  *
567  * Example:
568  *      struct timeval tv;
569  *
570  *      tv = timeabs_to_timeval(time_now());
571  *      printf("time = %lu.%06u\n", (long)tv.tv_sec, (int)tv.tv_usec);
572  */
573 static inline struct timeval timeabs_to_timeval(struct timeabs t)
574 {
575         return timespec_to_timeval(t.ts);
576 }
577
578 static inline struct timespec timeval_to_timespec(struct timeval tv)
579 {
580         struct timespec ts;
581         ts.tv_sec = tv.tv_sec;
582         ts.tv_nsec = tv.tv_usec * 1000;
583         return ts;
584 }
585
586 /**
587  * timeval_to_timerel - convert a timeval to a relative time.
588  * @tv: a timeval.
589  *
590  * Example:
591  *      struct timeval tv = { 0, 500 };
592  *      struct timerel t;
593  *
594  *      t = timeval_to_timerel(tv);
595  *      printf("timerel = %lu.%09lu\n", (long)t.ts.tv_sec, (long)t.ts.tv_nsec);
596  */
597 static inline struct timerel timeval_to_timerel(struct timeval tv)
598 {
599         struct timerel t;
600         t.ts = timeval_to_timespec(tv);
601         return TIMEREL_CHECK(t);
602 }
603
604 /**
605  * timeval_to_timeabs - convert a timeval to an absolute time.
606  * @tv: a timeval.
607  *
608  * Example:
609  *      struct timeval tv = { 1401762008, 500 };
610  *      struct timeabs t;
611  *
612  *      t = timeval_to_timeabs(tv);
613  *      printf("timeabs = %lu.%09lu\n", (long)t.ts.tv_sec, (long)t.ts.tv_nsec);
614  */
615 static inline struct timeabs timeval_to_timeabs(struct timeval tv)
616 {
617         struct timeabs t;
618         t.ts = timeval_to_timespec(tv);
619         return TIMEABS_CHECK(t);
620 }
621 #endif /* CCAN_TIME_H */