The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
time.h
Go to the documentation of this file.
1#pragma once
2/*
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
16 */
17
18/**
19 * $Id: 8b88a88bde62d1f04e9478da459d19c419a206b7 $
20 *
21 * @file lib/util/time.h
22 * @brief Simple time functions
23 *
24 * @copyright 2016-2019 Alan DeKok (aland@freeradius.org)
25 * @copyright 2019-2021 Arran Cudbard-Bell (a.cudbardb@freeradius.org)
26 */
27RCSIDH(time_h, "$Id: 8b88a88bde62d1f04e9478da459d19c419a206b7 $")
28
29#include <stdint.h>
30#include <inttypes.h>
31#include <stdatomic.h>
32#include <stdio.h>
33#include <sys/time.h>
34
35/*
36 * Avoid too many ifdef's later in the code.
37 */
38#if !defined(HAVE_CLOCK_GETTIME)
39#error clock_gettime is required
40#endif
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46/** The base resolution for print parse operations
47 */
62
63/** "server local" time. This is the time in nanoseconds since the application started.
64 *
65 * This time is our *private* view of time. It should only be used
66 * for internal timers, events, etc. It can skew randomly as NTP
67 * plays with the local clock.
68 */
69typedef struct fr_time_s {
70 int64_t value; //!< Signed because we need times before the server started
71 ///< for things like certificate validity checks and cache
72 ///< entries.
74
75/** A time delta, a difference in time measured in nanoseconds.
76 *
77 * This is easier to distinguish where server epoch time is being
78 * used, and where relative time is being used.
79 */
80typedef struct fr_time_delta_s {
81 int64_t value;
83
84/** "Unix" time. This is the time in nanoseconds since midnight January 1, 1970
85 *
86 * Note that it is *unsigned*, as we don't use dates before 1970. Having it
87 * unsigned also allows the compiler to catch issues where people confuse the
88 * two types of time.
89 *
90 * The unix times are *public* times. i.e. times that we get from
91 * the network, or send to the network. We have no idea if the other
92 * parties idea of time is correct (or if ours is wrong), so we don't
93 * mangle unix time based on clock skew.
94 */
95typedef struct fr_unix_time_s {
96 uint64_t value;
98
99#ifdef __cplusplus
100}
101#endif
102
103/*
104 * For sys/time.h and time.h
105 */
106#include <freeradius-devel/missing.h>
107#include <freeradius-devel/util/debug.h>
108#include <freeradius-devel/util/sbuff.h>
109#include <freeradius-devel/util/math.h>
110
111#ifdef __cplusplus
112extern "C" {
113#endif
114
115extern int64_t const fr_time_multiplier_by_res[];
117extern size_t fr_time_precision_table_len;
118
119static bool fr_time_op_ispos(bool a, bool op, bool b)
120{
121 return ((a == op) == b);
122}
123
124/** Determine, if an overflow has occurred, which direction it occurred in
125 *
126 * @param[in] _a First operand.
127 * @param[in] _op Operator, true if add or multiply, false if subtract.
128 * @param[in] _b Second operand.
129 */
130#define fr_time_overflow_ispos(_a, _op, _b) \
131fr_time_op_ispos( \
132 _Generic(&(_a), \
133 fr_time_t *: (fr_time_unwrap(*((fr_time_t *)&(_a))) >= 0), \
134 fr_time_delta_t *: (fr_time_delta_unwrap(*((fr_time_delta_t *)&(_a))) >= 0), \
135 fr_unix_time_t *: true), \
136 _op, \
137 _Generic(&(_b), \
138 fr_time_t *: (fr_time_unwrap(*((fr_time_t *)&(_b))) >= 0), \
139 fr_time_delta_t *: (fr_time_delta_unwrap(*((fr_time_delta_t *)&(_b))) >= 0), \
140 fr_unix_time_t *: true)\
141 )
142
143#define fr_time_max() (fr_time_t){ .value = INT64_MAX }
144#define fr_time_min() (fr_time_t){ .value = INT64_MIN }
145#define fr_time_wrap(_time) (fr_time_t){ .value = (_time) }
146static inline int64_t fr_time_unwrap(fr_time_t time) { return time.value; } /* func to stop mixing with fr_time_delta_t */
147#define fr_time_overflow_add(_a, _b) (fr_time_overflow_ispos(_a, true, _b) ? fr_time_max() : fr_time_min())
148#define fr_time_overflow_sub(_a, _b) (fr_time_overflow_ispos(_a, false, _b) ? fr_time_max() : fr_time_min())
149
150#define fr_time_delta_max() (fr_time_delta_t){ .value = INT64_MAX }
151#define fr_time_delta_min() (fr_time_delta_t){ .value = INT64_MIN }
152#define fr_time_delta_wrap(_time) (fr_time_delta_t){ .value = (_time) }
153/** @hidecallergraph */
154static inline int64_t fr_time_delta_unwrap(fr_time_delta_t time) { return time.value; } /* func to stop mixing with fr_time_t */
155#define fr_time_delta_overflow_add(_a, _b) (fr_time_overflow_ispos(_a, true, _b) ? fr_time_delta_max() : fr_time_delta_min())
156#define fr_time_delta_overflow_sub(_a, _b) (fr_time_overflow_ispos(_a, false, _b) ? fr_time_delta_max() : fr_time_delta_min())
157
158#define fr_unix_time_max() (fr_unix_time_t){ .value = UINT64_MAX }
159#define fr_unix_time_min() (fr_unix_time_t){ .value = 0 }
160#define fr_unix_time_wrap(_time) (fr_unix_time_t){ .value = (_time) }
161static inline uint64_t fr_unix_time_unwrap(fr_unix_time_t time) { return time.value; } /* func to stop mixing with fr_time_t */
162#define fr_unix_time_overflow_add(_a, _b) (fr_time_overflow_ispos(_a, true, _b) ? fr_unix_time_max() : fr_unix_time_min())
163#define fr_unix_time_overflow_sub(_a, _b) (fr_time_overflow_ispos(_a, false, _b) ? fr_unix_time_max() : fr_unix_time_min())
164
165/** @name fr_time_t arithmetic and comparison macros
166 *
167 * We wrap the 64bit signed time value in a struct to prevent misuse.
168 *
169 * The macros below allow basic arithmetic and comparisons to be performed.
170 * @{
171 */
172/* Don't add fr_time_add_time_time, it's almost always a type error */
179
186
187/** Add a time/time delta together
188 *
189 * Types may either be:
190 * - fr_time_add((fr_time_t), (fr_time_delta_t))
191 * - fr_time_add((fr_time_delta_t), (fr_time_delta_t))
192 *
193 * Adding two time values together is most likely an error.
194 * Adding two time_delta values together can be done with #fr_time_delta_add.
195 */
196#define fr_time_add(_a, _b) \
197 _Generic(_a, \
198 fr_time_t : _Generic(_b, \
199 fr_time_delta_t : fr_time_add_time_delta \
200 ), \
201 fr_time_delta_t : _Generic(_b, \
202 fr_time_t : fr_time_add_delta_time, \
203 fr_time_delta_t : fr_time_delta_add \
204 ) \
205 )(_a, _b)
206
219
220/** Subtract one time from another
221 *
222 * Types may either be:
223 * - fr_time_sub((fr_time_t), (fr_time_t)) - Produces a #fr_time_delta_t
224 * - fr_time_sub((fr_time_t), (fr_time_delta_t)) - Produces a #fr_time_t
225 *
226 * Subtracting time from a delta is most likely an error.
227 * Subtracting two time_delta values can be done with #fr_time_delta_sub
228 */
229#define fr_time_sub(_a, _b) \
230 _Generic(_a, \
231 fr_time_t : _Generic(_b, \
232 fr_time_t : fr_time_sub_time_time, \
233 fr_time_delta_t : fr_time_sub_time_delta \
234 ) \
235 )(_a, _b)
236
237#define fr_time_gt(_a, _b) (fr_time_unwrap(_a) > fr_time_unwrap(_b))
238#define fr_time_gteq(_a, _b) (fr_time_unwrap(_a) >= fr_time_unwrap(_b))
239#define fr_time_lt(_a, _b) (fr_time_unwrap(_a) < fr_time_unwrap(_b))
240#define fr_time_lteq(_a, _b) (fr_time_unwrap(_a) <= fr_time_unwrap(_b))
241#define fr_time_eq(_a, _b) (fr_time_unwrap(_a) == fr_time_unwrap(_b))
242#define fr_time_neq(_a, _b) (fr_time_unwrap(_a) != fr_time_unwrap(_b))
243
244#define fr_time_ispos(_a) (fr_time_unwrap(_a) > 0)
245#define fr_time_isneg(_a) (fr_time_unwrap(_a) < 0)
246/** @} */
247
248/** @name fr_time_delta_t arithmetic and comparison macros
249 *
250 * We wrap the 64bit signed time delta value in a struct to prevent misuse.
251 *
252 * The macros below allow basic arithmetic and comparisons to be performed.
253 * @{
254 */
274{
276 if (!fr_multiply(&out, fr_time_delta_unwrap(a), b)) {
277 return a;
278 }
279 return fr_time_delta_wrap(out);
280}
281
282#define fr_time_delta_cond(_a, _op, _b) (fr_time_delta_unwrap(_a) _op fr_time_delta_unwrap(_b))
283#define fr_time_delta_gt(_a, _b) (fr_time_delta_unwrap(_a) > fr_time_delta_unwrap(_b))
284#define fr_time_delta_gteq(_a, _b) (fr_time_delta_unwrap(_a) >= fr_time_delta_unwrap(_b))
285#define fr_time_delta_lt(_a, _b) (fr_time_delta_unwrap(_a) < fr_time_delta_unwrap(_b))
286#define fr_time_delta_lteq(_a, _b) (fr_time_delta_unwrap(_a) <= fr_time_delta_unwrap(_b))
287#define fr_time_delta_eq(_a, _b) (fr_time_delta_unwrap(_a) == fr_time_delta_unwrap(_b))
288#define fr_time_delta_neq(_a, _b) (fr_time_delta_unwrap(_a) != fr_time_delta_unwrap(_b))
289
290#define fr_time_delta_ispos(_a) (fr_time_delta_unwrap(_a) > 0)
291#define fr_time_delta_isneg(_a) (fr_time_delta_unwrap(_a) < 0)
292/** @} */
293
294/** @name fr_unix_time_t arithmetic and comparison macros
295 *
296 * We wrap the 64bit signed time value in a struct to prevent misuse.
297 *
298 * The macros below allow basic arithmetic and comparisons to be performed.
299 * @{
300 */
301/* Don't add fr_unix_time_add_time_time, it's almost always a type error */
314
315/** Add a time/time delta together
316 *
317 * Types may either be:
318 * - fr_unix_time_add((fr_unix_time_t), (fr_time_delta_t))
319 * - fr_unix_time_add((fr_time_delta_t), (fr_time_delta_t))
320 *
321 * Adding two time values together is most likely an error.
322 * Adding two time_delta values together can be done with #fr_time_delta_add.
323 */
324#define fr_unix_time_add(_a, _b) \
325 _Generic(_a, \
326 fr_unix_time_t : _Generic(_b, \
327 fr_time_delta_t : fr_unix_time_add_time_delta \
328 ), \
329 fr_time_delta_t : _Generic(_b, \
330 fr_unix_time_t : fr_unix_time_add_delta_time, \
331 fr_time_delta_t : fr_time_delta_add \
332 ) \
333 )(_a, _b)
334
347
348/** Subtract one time from another
349 *
350 * Types may either be:
351 * - fr_unix_time_sub((fr_unix_time_t), (fr_unix_time_t)) - Produces a #fr_time_delta_t
352 * - fr_unix_time_sub((fr_unix_time_t), (fr_time_delta_t)) - Produces a #fr_unix_time_t
353 *
354 * Subtracting time from a delta is most likely an error.
355 * Subtracting two time_delta values can be done with #fr_time_delta_sub
356 */
357#define fr_unix_time_sub(_a, _b) \
358 _Generic(_a, \
359 fr_unix_time_t : _Generic(_b, \
360 fr_unix_time_t : fr_unix_time_sub_time_time, \
361 fr_time_delta_t : fr_unix_time_sub_time_delta \
362 ) \
363 )(_a, _b)
364
365#define fr_unix_time_gt(_a, _b) (fr_unix_time_unwrap(_a) > fr_unix_time_unwrap(_b))
366#define fr_unix_time_gteq(_a, _b) (fr_unix_time_unwrap(_a) >= fr_unix_time_unwrap(_b))
367#define fr_unix_time_lt(_a, _b) (fr_unix_time_unwrap(_a) < fr_unix_time_unwrap(_b))
368#define fr_unix_time_lteq(_a, _b) (fr_unix_time_unwrap(_a) <= fr_unix_time_unwrap(_b))
369#define fr_unix_time_eq(_a, _b) (fr_unix_time_unwrap(_a) == fr_unix_time_unwrap(_b))
370#define fr_unix_time_neq(_a, _b) (fr_unix_time_unwrap(_a) != fr_unix_time_unwrap(_b))
371
372#define fr_unix_time_ispos(_a) (fr_unix_time_unwrap(_a) > 0)
373/** @} */
374
375typedef struct {
376 uint64_t array[8]; //!< 100ns to 100s
378
379#define NSEC (1000000000)
380#define USEC (1000000)
381#define MSEC (1000)
382#define CSEC (100)
383
384/*
385 * Pre-defined "magic" values for time in a month and year. The number of seconds in a year is:
386 *
387 * 1 year is 365.2425 days. times 86400 seconds in a day.
388 *
389 * The average month is simply one twelfth of that. Note that the exact value for both year and month
390 * duration are really magic values, which people will never stumble upon themselves. As such, they can
391 * be used (somewhat, in some cases) as magic tokens meaning "year" or "month".
392 */
393#define FR_TIME_DUR_YEAR ((int64_t)NSEC * 31556952)
394#define FR_TIME_DUR_MONTH (FR_TIME_DUR_YEAR/12)
395
396
397/*
398 * The value of clock_gettime(CLOCK_MONOTONIC_RAW) when we started. i.e. our epoch.
399 */
400extern int64_t fr_time_epoch;
401
402/*
403 * The offset from CLOCK_MONOTONIC_RAW to CLOCK_REALTIME.
404 */
406
407/** @name fr_unix_time_t scale conversion macros/functions
408 *
409 * @{
410 */
411static inline fr_unix_time_t fr_unix_time_from_integer(bool *overflow, int64_t integer, fr_time_res_t res)
412{
413 int64_t out;
414 if (res == FR_TIME_RES_INVALID) return fr_unix_time_max();
415 if (!fr_multiply(&out, integer, fr_time_multiplier_by_res[res])) {
416 if (overflow) *overflow = true;
417 return fr_unix_time_max();
418 }
419 if (overflow) *overflow = false;
420 return fr_unix_time_wrap(out);
421}
422
423static inline fr_unix_time_t fr_unix_time_from_nsec(int64_t nsec)
424{
425 return fr_unix_time_wrap(nsec);
426}
427
428static inline fr_unix_time_t fr_unix_time_from_usec(int64_t usec)
429{
430 uint64_t out;
431 if (!fr_multiply(&out, usec, (NSEC / USEC))) return (usec > 0) ? fr_unix_time_max() : fr_unix_time_min();
432 return fr_unix_time_wrap(out);
433}
434
435static inline fr_unix_time_t fr_unix_time_from_msec(int64_t msec)
436{
437 uint64_t out;
438 if (!fr_multiply(&out, msec, (NSEC / MSEC))) return (msec > 0) ? fr_unix_time_max() : fr_unix_time_min();
439 return fr_unix_time_wrap(out);
440}
441
442static inline fr_unix_time_t fr_unix_time_from_csec(int64_t csec)
443{
444 uint64_t out;
445 if (!fr_multiply(&out, csec, (NSEC / CSEC))) return (csec > 0) ? fr_unix_time_max() : fr_unix_time_min();
446 return fr_unix_time_wrap(out);
447}
448
449static inline fr_unix_time_t fr_unix_time_from_sec(int64_t sec)
450{
451 uint64_t out;
452 if (!fr_multiply(&out, sec, NSEC)) return (sec > 0) ? fr_unix_time_max() : fr_unix_time_min();
453 return fr_unix_time_wrap(out);
454}
455
456static inline CC_HINT(nonnull) fr_unix_time_t fr_unix_time_from_timeval(struct timeval const *tv)
457{
458 typeof_field(fr_unix_time_t, value) integer, fraction, out;
459
460 if (!fr_multiply(&integer, (typeof_field(fr_unix_time_t, value)) tv->tv_sec, NSEC)) {
461 overflow:
462 return fr_unix_time_max();
463 }
464
465 if (!fr_multiply(&fraction,
466 (typeof_field(fr_unix_time_t, value)) tv->tv_usec, (NSEC / USEC))) goto overflow;
467
468 if (!fr_add(&out, integer, fraction)) goto overflow;
469
470 return fr_unix_time_wrap(out);
471}
472
473static inline CC_HINT(nonnull) fr_unix_time_t fr_unix_time_from_timespec(struct timespec const *ts)
474{
476
477 if (!fr_multiply(&integer, (typeof_field(fr_unix_time_t, value)) ts->tv_sec, NSEC)) {
478 overflow:
479 return fr_unix_time_max();
480 }
481 if (!fr_add(&out, integer, ts->tv_nsec)) goto overflow;
482
483 return fr_unix_time_wrap(out);
484}
485
486static inline int64_t fr_unix_time_to_integer(fr_unix_time_t delta, fr_time_res_t res)
487{
489}
490
491static inline int64_t fr_unix_time_to_usec(fr_unix_time_t delta)
492{
493 return fr_unix_time_unwrap(delta) / (NSEC / USEC);
494}
495
496static inline int64_t fr_unix_time_to_msec(fr_unix_time_t delta)
497{
498 return fr_unix_time_unwrap(delta) / (NSEC / MSEC);
499}
500
501static inline int64_t fr_unix_time_to_csec(fr_unix_time_t delta)
502{
503 return fr_unix_time_unwrap(delta) / (NSEC / CSEC);
504}
505
506static inline int64_t fr_unix_time_to_sec(fr_unix_time_t delta)
507{
508 return (fr_unix_time_unwrap(delta) / NSEC);
509}
510
511static inline int64_t fr_unix_time_to_min(fr_unix_time_t delta)
512{
513 return (fr_unix_time_unwrap(delta) / NSEC) / 60;
514}
515
516static inline int64_t fr_unix_time_to_hour(fr_unix_time_t delta)
517{
518 return (fr_unix_time_unwrap(delta) / NSEC) / 3600;
519}
520
521static inline int64_t fr_unix_time_to_day(fr_unix_time_t delta)
522{
523 return (fr_unix_time_unwrap(delta) / NSEC) / 386400;
524}
525
526/** Convert a time_t into out internal fr_unix_time_t
527 *
528 * Our internal unix time representation is unsigned and in nanoseconds which
529 * is different from time_t which is signed and has seconds resolution.
530 *
531 * If time is negative we return 0.
532 *
533 * @param[in] time to convert.
534 * @return Unix time in seconds.
535 */
536static inline CC_HINT(nonnull) fr_unix_time_t fr_unix_time_from_time(time_t time)
537{
538 if (time < 0) return fr_unix_time_min();
539
540 return fr_unix_time_wrap(time * NSEC);
541}
542/** @} */
543
544/** @name fr_time_delta_t scale conversion macros/functions
545 *
546 * @{
547 */
548static inline fr_time_delta_t fr_time_delta_from_integer(bool *overflow, int64_t integer, fr_time_res_t res)
549{
550 int64_t out;
551 if (res == FR_TIME_RES_INVALID) {
552 if (overflow) *overflow = true;
553 return fr_time_delta_max();
554 }
555 if (!fr_multiply(&out, integer, fr_time_multiplier_by_res[res])) {
556 if (overflow) *overflow = true;
557 return fr_time_delta_wrap(integer > 0 ? INT64_MAX: INT64_MIN);
558 }
559 if (overflow) *overflow = false;
560 return fr_time_delta_wrap(out);
561}
562
563static inline fr_time_delta_t fr_time_delta_from_nsec(int64_t nsec)
564{
565 return fr_time_delta_wrap(nsec);
566}
567
568static inline fr_time_delta_t fr_time_delta_from_usec(int64_t usec)
569{
570 int64_t out;
571 if (!fr_multiply(&out, usec, (NSEC / USEC))) return (usec > 0) ? fr_time_delta_max() : fr_time_delta_min();
572 return fr_time_delta_wrap(out);
573}
574
575static inline fr_time_delta_t fr_time_delta_from_msec(int64_t msec)
576{
577 int64_t out;
578 if (!fr_multiply(&out, msec, (NSEC / MSEC))) return (msec > 0) ? fr_time_delta_max() : fr_time_delta_min();
579 return fr_time_delta_wrap(out);
580}
581
582static inline fr_time_delta_t fr_time_delta_from_csec(int64_t csec)
583{
584 int64_t out;
585 if (!fr_multiply(&out, csec, (NSEC / CSEC))) return (csec > 0) ? fr_time_delta_max() : fr_time_delta_min();
586 return fr_time_delta_wrap(out);
587}
588
589/** @hidecallergraph */
590static inline fr_time_delta_t fr_time_delta_from_sec(int64_t sec)
591{
592 int64_t out;
593 if (!fr_multiply(&out, sec, NSEC)) return (sec > 0) ? fr_time_delta_max() : fr_time_delta_min();
594 return fr_time_delta_wrap(out);
595}
596
597static inline CC_HINT(nonnull) fr_time_delta_t fr_time_delta_from_timeval(struct timeval const *tv)
598{
599 typeof_field(fr_time_delta_t, value) integer, fraction, out;
600
601 if (!fr_multiply(&integer, (typeof_field(fr_time_delta_t, value)) tv->tv_sec, NSEC)) {
602 overflow:
603 return fr_time_delta_max();
604 }
605
606 if (!fr_multiply(&fraction,
607 (typeof_field(fr_time_delta_t, value)) tv->tv_usec, (NSEC / USEC))) goto overflow;
608
609 if (!fr_add(&out, integer, fraction)) goto overflow;
610
611 return fr_time_delta_wrap(out);
612}
613
614static inline CC_HINT(nonnull) fr_time_delta_t fr_time_delta_from_timespec(struct timespec const *ts)
615{
617
618 if (!fr_multiply(&integer, (typeof_field(fr_time_delta_t, value)) ts->tv_sec, NSEC)) {
619 overflow:
620 return fr_time_delta_max();
621 }
622 if (!fr_add(&out, integer, ts->tv_nsec)) goto overflow;
623
624 return fr_time_delta_wrap(out);
625}
626
628{
630}
631
632static inline int64_t fr_time_delta_to_usec(fr_time_delta_t delta)
633{
634 return fr_time_delta_unwrap(delta) / (NSEC / USEC);
635}
636
637static inline int64_t fr_time_delta_to_msec(fr_time_delta_t delta)
638{
639 return fr_time_delta_unwrap(delta) / (NSEC / MSEC);
640}
641
642static inline int64_t fr_time_delta_to_csec(fr_time_delta_t delta)
643{
644 return fr_time_delta_unwrap(delta) / (NSEC / CSEC);
645}
646
647static inline int64_t fr_time_delta_to_sec(fr_time_delta_t delta)
648{
649 return (fr_time_delta_unwrap(delta) / NSEC);
650}
651
652/** Convert a delta to a timeval
653 *
654 * @param[in] _delta in nanoseconds.
655 */
656#define fr_time_delta_to_timeval(_delta) \
657(struct timeval){ \
658 .tv_sec = fr_time_delta_unwrap(_delta) / NSEC, \
659 .tv_usec = (fr_time_delta_unwrap(_delta) % NSEC) / (NSEC / USEC) \
660}
661
662/** Convert a delta to a timespec
663 *
664 * @param[in] _delta in nanoseconds.
665 */
666#define fr_time_delta_to_timespec(_delta)\
667(struct timespec){ \
668 .tv_sec = fr_time_delta_unwrap(_delta) / NSEC, \
669 .tv_nsec = (fr_time_delta_unwrap(_delta) % NSEC) \
670}
671/** @} */
672
673/** @name fr_time_delta_t scale conversion macros/functions
674 *
675 * @{
676 */
677/** Return the current value of fr_time_monotonic_to_realtime.
678 *
679 */
684
685/** Convert an fr_time_t (internal time) to our version of unix time (wallclock time)
686 *
687 */
689{
690 int64_t out;
691
694 }
695 return fr_unix_time_wrap(out);
696}
697
698/** Convert an fr_time_t (internal time) to number of usec since the unix epoch (wallclock time)
699 *
700 */
701static inline int64_t fr_time_to_usec(fr_time_t when)
702{
703 /* Divide each operand separately to avoid overflow on addition */
704 return (((fr_time_unwrap(when) / (NSEC / USEC)) +
706}
707
708/** Convert an fr_time_t (internal time) to number of msec since the unix epoch (wallclock time)
709 *
710 */
711static inline int64_t fr_time_to_msec(fr_time_t when)
712{
713 /* Divide each operand separately to avoid overflow on addition */
714 return (((fr_time_unwrap(when) / (NSEC / MSEC)) +
716}
717
718/** Convert an fr_time_t (internal time) to number of csec since the unix epoch (wallclock time)
719 *
720 */
721static inline int64_t fr_time_to_csec(fr_time_t when)
722{
723 /* Divide each operand separately to avoid overflow on addition */
724 return (((fr_time_unwrap(when) / (NSEC / CSEC)) +
726}
727
728/** Convert an fr_time_t (internal time) to number of sec since the unix epoch (wallclock time)
729 *
730 */
731static inline int64_t fr_time_to_sec(fr_time_t when)
732{
733 /* Divide each operand separately to avoid overflow on addition */
734 return (((fr_time_unwrap(when) / NSEC) +
736}
737
738/** Convert server epoch time to unix epoch time
739 *
740 * @param[in] _when The server epoch time to convert.
741 */
742#define fr_time_to_timeval(_when) fr_time_delta_to_timeval(fr_time_delta_wrap(fr_time_offset_to_realtime() + fr_time_unwrap(_when)))
743
744/** Convert server epoch time to unix epoch time
745 *
746 * @param[in] _when The server epoch time to convert.
747 */
748#define fr_time_to_timespec(_when) fr_time_delta_to_timespec(fr_time_delta_wrap(fr_time_offset_to_realtime() + fr_time_unwrap(_when)))
749
750/** Convert wallclock time to a fr_time_t (internal time)
751 *
752 * @param[out] overflow Whether the conversion overflowed.
753 * @param[in] when The timestamp to convert.
754 * @param[in] res The scale the integer value is in.
755 * @return
756 * - >0 number of nanoseconds since the server started.
757 * - 0 when the server started.
758 * - <0 number of nanoseconds before the server started.
759 */
760static inline fr_time_t fr_time_from_integer(bool *overflow, int64_t when, fr_time_res_t res)
761{
763
764 if (!fr_multiply(&out, when, fr_time_multiplier_by_res[res])) {
765 if (overflow) *overflow = true;
766 return when > 0 ? fr_time_max() : fr_time_min();
767 }
768
770 if (overflow) *overflow = true;
771 return when < 0 ? fr_time_max() : fr_time_min();
772 }
773
774 if (overflow) *overflow = false;
775 return fr_time_wrap(out);
776}
777
778/** Convert a nsec (wallclock time) to a fr_time_t (internal time)
779 *
780 * @param[in] when The timestamp to convert.
781 * @return
782 * - >0 number of nanoseconds since the server started.
783 * - 0 when the server started.
784 * - <0 number of nanoseconds before the server started.
785 */
786static inline fr_time_t fr_time_from_nsec(int64_t when)
787{
789
791 return when > 0 ? fr_time_min() : fr_time_max();
792 }
793 return fr_time_wrap(out);
794}
795
796/** Convert usec (wallclock time) to a fr_time_t (internal time)
797 *
798 * @param[in] when The timestamp to convert.
799 * @return
800 * - >0 number of nanoseconds since the server started.
801 * - 0 when the server started.
802 * - <0 number of nanoseconds before the server started.
803 */
804static inline fr_time_t fr_time_from_usec(int64_t when)
805{
807
809 return when > 0 ? fr_time_min() : fr_time_max();
810 }
811 return fr_time_wrap(out);
812}
813
814/** Convert msec (wallclock time) to a fr_time_t (internal time)
815 *
816 * @param[in] when The timestamp to convert.
817 * @return
818 * - >0 number of nanoseconds since the server started.
819 * - 0 when the server started.
820 * - <0 number of nanoseconds before the server started.
821 */
822static inline fr_time_t fr_time_from_msec(int64_t when)
823{
825
827 return when > 0 ? fr_time_min() : fr_time_max();
828 }
829 return fr_time_wrap(out);
830}
831
832/** Convert csec (wallclock time) to a fr_time_t (internal time)
833 *
834 * @param[in] when The timestamp to convert.
835 * @return
836 * - >0 number of nanoseconds since the server started.
837 * - 0 when the server started.
838 * - <0 number of nanoseconds before the server started.
839 */
840static inline fr_time_t fr_time_from_csec(int64_t when)
841{
843
845 return when > 0 ? fr_time_min() : fr_time_max();
846 }
847 return fr_time_wrap(out);
848}
849
850/** Convert a time_t (wallclock time) to a fr_time_t (internal time)
851 *
852 * @param[in] when The timestamp to convert.
853 * @return
854 * - >0 number of nanoseconds since the server started.
855 * - 0 when the server started.
856 * - <0 number of nanoseconds before the server started.
857 */
858static inline fr_time_t fr_time_from_sec(time_t when)
859{
861
863 return when > 0 ? fr_time_min() : fr_time_max();
864 }
865 return fr_time_wrap(out);
866}
867
868
869
870/** Convert a timespec (wallclock time) to a fr_time_t (internal time)
871 *
872 * @param[in] when_ts The timestamp to convert.
873 * @return
874 * - >0 number of nanoseconds since the server started.
875 * - 0 when the server started.
876 * - 0 if when_tv occurred before the server started.
877 */
878static inline CC_HINT(nonnull) fr_time_t fr_time_from_timespec(struct timespec const *when_ts)
879{
881
882 if (!fr_sub(&out, tmp, fr_time_offset_to_realtime())) {
883 return tmp > 0 ? fr_time_min() : fr_time_max();
884 }
885 return fr_time_wrap(out);
886}
887
888/** Convert a timeval (wallclock time) to a fr_time_t (internal time)
889 *
890 * @param[in] when_tv The timestamp to convert.
891 * @return
892 * - >0 number of nanoseconds since the server started.
893 * - 0 when the server started.
894 * - <0 number of nanoseconds before the server started.
895 */
896static inline CC_HINT(nonnull) fr_time_t fr_time_from_timeval(struct timeval const *when_tv)
897{
899
900 if (!fr_sub(&out, tmp, fr_time_offset_to_realtime())) {
901 return tmp > 0 ? fr_time_min() : fr_time_max();
902 }
903 return fr_time_wrap(out);
904}
905/** @} */
906
907/** Compare two fr_time_t values
908 *
909 * @param[in] a The first value to compare.
910 * @param[in] b The second value to compare.
911 * @return
912 * - +1 if a > b
913 * - 0 if a == b
914 * - -1 if a < b
915 */
916static inline int8_t fr_time_cmp(fr_time_t a, fr_time_t b)
917{
918 return CMP(fr_time_unwrap(a), fr_time_unwrap(b));
919}
920
921/** Compare two fr_time_delta_t values
922 *
923 * @param[in] a The first value to compare.
924 * @param[in] b The second value to compare.
925 * @return
926 * - +1 if a > b
927 * - 0 if a == b
928 * - -1 if a < b
929 */
931{
933}
934
935/** Compare two fr_unix_time_t values
936 *
937 * @param[in] a The first value to compare.
938 * @param[in] b The second value to compare.
939 * @return
940 * - +1 if a > b
941 * - 0 if a == b
942 * - -1 if a < b
943 */
945{
947}
948
949#ifndef CLOCK_MONOTONIC_RAW
950#define CLOCK_MONOTONIC_RAW CLOCK_MONOTONIC
951#endif
952
953/** Return a relative time since the server fr_time_epoch
954 *
955 * This time is useful for doing time comparisons, deltas, etc.
956 * Human (i.e. printable) time is something else.
957 *
958 * @returns fr_time_t time in nanoseconds since the server fr_time_epoch.
959 *
960 * @hidecallergraph
961 */
962static inline fr_time_t fr_time(void)
963{
964 struct timespec ts;
965 (void) clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
967}
968
969int fr_time_start(void);
970int fr_time_sync(void);
971
972int64_t fr_time_scale(int64_t t, fr_time_res_t hint);
973
974int fr_time_delta_from_time_zone(char const *tz, fr_time_delta_t *delta)
975 CC_HINT(nonnull);
976
978 bool no_trailing, fr_sbuff_term_t const *tt)
979 CC_HINT(nonnull(1,2));
980
982 CC_HINT(nonnull);
983
985 CC_HINT(nonnull);
986
987size_t fr_time_strftime_local(fr_sbuff_t *out, fr_time_t time, char const *fmt)
988 CC_HINT(format(strftime, 3, 0));
989
990size_t fr_time_strftime_utc(fr_sbuff_t *out, fr_time_t time, char const *fmt)
991 CC_HINT(format(strftime, 3, 0));
992
994 CC_HINT(nonnull);
995
996void fr_time_elapsed_fprint(FILE *fp, fr_time_elapsed_t const *elapsed, char const *prefix, int tabs)
997 CC_HINT(nonnull(1,2));
998
1000 CC_HINT(nonnull);
1001
1002int fr_unix_time_from_str(fr_unix_time_t *date, char const *date_str, fr_time_res_t hint)
1003 CC_HINT(nonnull);
1004
1006 CC_HINT(nonnull);
1007
1009
1010bool fr_time_is_dst(void);
1011
1012#ifdef __cplusplus
1013}
1014#endif
static int const char * fmt
Definition acutest.h:573
#define typeof_field(_type, _field)
Typeof field.
Definition build.h:174
#define RCSIDH(h, id)
Definition build.h:484
#define CMP(_a, _b)
Same as CMP_PREFER_SMALLER use when you don't really care about ordering, you just want an ordering.
Definition build.h:112
static const char * tabs
Definition command.c:1581
static fr_slen_t in
Definition dict.h:824
Test enumeration values.
Definition dict_test.h:92
#define fr_sub(_out, _a, _b)
Subtracts two integers.
Definition math.h:140
#define fr_add(_out, _a, _b)
Adds two integers.
Definition math.h:129
#define fr_multiply(_out, _a, _b)
Multiplies two integers together.
Definition math.h:118
ssize_t fr_slen_t
Set of terminal elements.
@ memory_order_consume
Definition stdatomic.h:128
#define _Atomic(T)
Definition stdatomic.h:77
#define atomic_load_explicit(object, order)
Definition stdatomic.h:312
An element in an arbitrarily ordered array of name to num mappings.
Definition table.h:57
static fr_time_t fr_time_from_csec(int64_t when)
Convert csec (wallclock time) to a fr_time_t (internal time)
Definition time.h:840
fr_slen_t fr_time_delta_from_substr(fr_time_delta_t *out, fr_sbuff_t *in, fr_time_res_t hint, bool no_trailing, fr_sbuff_term_t const *tt))
Create fr_time_delta_t from a string.
Definition time.c:214
static fr_unix_time_t fr_unix_time_sub_time_delta(fr_unix_time_t a, fr_time_delta_t b)
Definition time.h:341
static fr_unix_time_t fr_unix_time_from_msec(int64_t msec)
Definition time.h:435
static fr_time_t fr_time_from_timeval(struct timeval const *when_tv)
Convert a timeval (wallclock time) to a fr_time_t (internal time)
Definition time.h:896
void fr_time_elapsed_update(fr_time_elapsed_t *elapsed, fr_time_t start, fr_time_t end)
Definition time.c:584
static fr_time_delta_t fr_time_delta_from_integer(bool *overflow, int64_t integer, fr_time_res_t res)
Definition time.h:548
fr_unix_time_t fr_unix_time_from_tm(struct tm *tm)
Definition time.c:665
#define MSEC
Definition time.h:381
static fr_time_t fr_time_from_nsec(int64_t when)
Convert a nsec (wallclock time) to a fr_time_t (internal time)
Definition time.h:786
#define fr_time_delta_min()
Definition time.h:151
static fr_time_delta_t fr_time_delta_from_msec(int64_t msec)
Definition time.h:575
static int64_t fr_time_delta_to_integer(fr_time_delta_t delta, fr_time_res_t res)
Definition time.h:627
static fr_time_t fr_time_from_msec(int64_t when)
Convert msec (wallclock time) to a fr_time_t (internal time)
Definition time.h:822
static int64_t fr_time_to_sec(fr_time_t when)
Convert an fr_time_t (internal time) to number of sec since the unix epoch (wallclock time)
Definition time.h:731
static fr_time_delta_t fr_time_delta_add(fr_time_delta_t a, fr_time_delta_t b)
Definition time.h:255
static fr_unix_time_t fr_unix_time_add_delta_time(fr_time_delta_t a, fr_unix_time_t b)
Definition time.h:308
static fr_unix_time_t fr_unix_time_from_nsec(int64_t nsec)
Definition time.h:423
static fr_time_t fr_time_add_time_delta(fr_time_t a, fr_time_delta_t b)
Definition time.h:173
int fr_time_sync(void)
Get a new fr_time_monotonic_to_realtime value.
Definition time.c:102
static int64_t fr_time_delta_unwrap(fr_time_delta_t time)
Definition time.h:154
static int64_t fr_time_to_msec(fr_time_t when)
Convert an fr_time_t (internal time) to number of msec since the unix epoch (wallclock time)
Definition time.h:711
static int8_t fr_time_delta_cmp(fr_time_delta_t a, fr_time_delta_t b)
Compare two fr_time_delta_t values.
Definition time.h:930
fr_table_num_ordered_t const fr_time_precision_table[]
Definition time.c:46
static int64_t fr_unix_time_to_min(fr_unix_time_t delta)
Definition time.h:511
static fr_time_t fr_time_from_integer(bool *overflow, int64_t when, fr_time_res_t res)
Convert wallclock time to a fr_time_t (internal time)
Definition time.h:760
#define fr_time_delta_overflow_add(_a, _b)
Definition time.h:155
static int64_t fr_time_unwrap(fr_time_t time)
Definition time.h:146
int64_t value
Definition time.h:81
static fr_time_delta_t fr_time_delta_from_sec(int64_t sec)
Definition time.h:590
static int64_t fr_unix_time_to_csec(fr_unix_time_t delta)
Definition time.h:501
#define fr_unix_time_overflow_sub(_a, _b)
Definition time.h:163
static int64_t fr_unix_time_to_sec(fr_unix_time_t delta)
Definition time.h:506
#define fr_time_delta_wrap(_time)
Definition time.h:152
int fr_time_delta_from_time_zone(char const *tz, fr_time_delta_t *delta)
Return time delta from the time zone.
Definition time.c:176
#define fr_time_min()
Definition time.h:144
#define fr_time_wrap(_time)
Definition time.h:145
fr_slen_t fr_time_delta_from_str(fr_time_delta_t *out, char const *in, size_t inlen, fr_time_res_t hint)
Create fr_time_delta_t from a string.
Definition time.c:449
static fr_time_t fr_time_add_delta_time(fr_time_delta_t a, fr_time_t b)
Definition time.h:180
bool fr_time_is_dst(void)
Whether or not we're daylight savings.
Definition time.c:1243
static fr_time_delta_t fr_time_delta_mul(fr_time_delta_t a, int64_t b)
Definition time.h:273
#define fr_unix_time_min()
Definition time.h:159
static fr_unix_time_t fr_unix_time_from_timeval(struct timeval const *tv)
Definition time.h:456
static int64_t fr_time_delta_to_csec(fr_time_delta_t delta)
Definition time.h:642
#define fr_time_overflow_add(_a, _b)
Definition time.h:147
static fr_unix_time_t fr_unix_time_from_timespec(struct timespec const *ts)
Definition time.h:473
#define fr_unix_time_wrap(_time)
Definition time.h:160
static int64_t fr_time_to_usec(fr_time_t when)
Convert an fr_time_t (internal time) to number of usec since the unix epoch (wallclock time)
Definition time.h:701
static int64_t fr_time_delta_to_sec(fr_time_delta_t delta)
Definition time.h:647
_Atomic int64_t fr_time_monotonic_to_realtime
difference between the two clocks
Definition time.c:87
int fr_unix_time_from_str(fr_unix_time_t *date, char const *date_str, fr_time_res_t hint)
Convert string in various formats to a fr_unix_time_t.
Definition time.c:831
static fr_time_t fr_time_from_usec(int64_t when)
Convert usec (wallclock time) to a fr_time_t (internal time)
Definition time.h:804
#define fr_time_delta_overflow_sub(_a, _b)
Definition time.h:156
int64_t fr_time_scale(int64_t t, fr_time_res_t hint)
Scale an input time to NSEC, clamping it at max / min.
Definition time.c:720
int64_t value
Signed because we need times before the server started for things like certificate validity checks an...
Definition time.h:70
static fr_time_delta_t fr_time_sub_time_time(fr_time_t a, fr_time_t b)
Definition time.h:207
fr_time_res_t
The base resolution for print parse operations.
Definition time.h:48
@ FR_TIME_RES_MONTH
Definition time.h:55
@ FR_TIME_RES_MSEC
Definition time.h:58
@ FR_TIME_RES_WEEK
Definition time.h:54
@ FR_TIME_RES_MIN
Definition time.h:51
@ FR_TIME_RES_CSEC
Definition time.h:57
@ FR_TIME_RES_HOUR
Definition time.h:52
@ FR_TIME_RES_YEAR
Definition time.h:56
@ FR_TIME_RES_DAY
Definition time.h:53
@ FR_TIME_RES_NSEC
Definition time.h:60
@ FR_TIME_RES_USEC
Definition time.h:59
@ FR_TIME_RES_SEC
Definition time.h:50
@ FR_TIME_RES_INVALID
Definition time.h:49
static int64_t fr_time_delta_to_usec(fr_time_delta_t delta)
Definition time.h:632
static fr_time_t fr_time_from_timespec(struct timespec const *when_ts)
Convert a timespec (wallclock time) to a fr_time_t (internal time)
Definition time.h:878
static fr_unix_time_t fr_unix_time_from_csec(int64_t csec)
Definition time.h:442
static fr_unix_time_t fr_unix_time_from_sec(int64_t sec)
Definition time.h:449
size_t fr_time_strftime_utc(fr_sbuff_t *out, fr_time_t time, char const *fmt))
Copy a time string (UTC) to an sbuff.
Definition time.c:569
#define fr_unix_time_overflow_add(_a, _b)
Definition time.h:162
static int64_t fr_unix_time_to_day(fr_unix_time_t delta)
Definition time.h:521
static fr_unix_time_t fr_unix_time_from_integer(bool *overflow, int64_t integer, fr_time_res_t res)
Definition time.h:411
fr_time_delta_t fr_time_gmtoff(void)
Get the offset to gmt.
Definition time.c:1235
#define NSEC
Definition time.h:379
static int64_t fr_unix_time_to_usec(fr_unix_time_t delta)
Definition time.h:491
#define fr_time_overflow_sub(_a, _b)
Definition time.h:148
static int8_t fr_unix_time_cmp(fr_unix_time_t a, fr_unix_time_t b)
Compare two fr_unix_time_t values.
Definition time.h:944
void fr_time_elapsed_fprint(FILE *fp, fr_time_elapsed_t const *elapsed, char const *prefix, int tabs))
Definition time.c:629
struct fr_time_s fr_time_t
"server local" time.
static fr_time_t fr_time_from_sec(time_t when)
Convert a time_t (wallclock time) to a fr_time_t (internal time)
Definition time.h:858
static uint64_t fr_unix_time_unwrap(fr_unix_time_t time)
Definition time.h:161
static fr_unix_time_t fr_unix_time_add_time_delta(fr_unix_time_t a, fr_time_delta_t b)
Definition time.h:302
#define CLOCK_MONOTONIC_RAW
Definition time.h:950
#define fr_unix_time_max()
Definition time.h:158
static fr_time_delta_t fr_time_delta_from_nsec(int64_t nsec)
Definition time.h:563
fr_slen_t fr_time_delta_to_str(fr_sbuff_t *out, fr_time_delta_t delta, fr_time_res_t res, bool is_unsigned)
Print fr_time_delta_t to a string with an appropriate suffix.
Definition time.c:472
static int64_t fr_unix_time_to_integer(fr_unix_time_t delta, fr_time_res_t res)
Definition time.h:486
static fr_time_delta_t fr_time_delta_sub(fr_time_delta_t a, fr_time_delta_t b)
Definition time.h:261
static fr_time_delta_t fr_time_delta_from_timeval(struct timeval const *tv)
Definition time.h:597
uint64_t value
Definition time.h:96
size_t fr_time_strftime_local(fr_sbuff_t *out, fr_time_t time, char const *fmt))
Copy a time string (local timezone) to an sbuff.
Definition time.c:540
static fr_time_delta_t fr_time_delta_from_csec(int64_t csec)
Definition time.h:582
static int64_t fr_unix_time_to_msec(fr_unix_time_t delta)
Definition time.h:496
size_t fr_time_precision_table_len
Definition time.c:84
static fr_time_t fr_time(void)
Return a relative time since the server fr_time_epoch.
Definition time.h:962
static fr_time_t fr_time_sub_time_delta(fr_time_t a, fr_time_delta_t b)
Definition time.h:213
static fr_unix_time_t fr_unix_time_from_time(time_t time)
Convert a time_t into out internal fr_unix_time_t.
Definition time.h:536
static bool fr_time_op_ispos(bool a, bool op, bool b)
Definition time.h:119
#define USEC
Definition time.h:380
static int64_t fr_time_offset_to_realtime(void)
Return the current value of fr_time_monotonic_to_realtime.
Definition time.h:680
static int64_t fr_time_to_csec(fr_time_t when)
Convert an fr_time_t (internal time) to number of csec since the unix epoch (wallclock time)
Definition time.h:721
static fr_time_delta_t fr_time_delta_div(fr_time_delta_t a, fr_time_delta_t b)
Definition time.h:267
static fr_unix_time_t fr_time_to_unix_time(fr_time_t when)
Convert an fr_time_t (internal time) to our version of unix time (wallclock time)
Definition time.h:688
static fr_time_delta_t fr_time_delta_from_usec(int64_t usec)
Definition time.h:568
struct fr_time_delta_s fr_time_delta_t
A time delta, a difference in time measured in nanoseconds.
#define CSEC
Definition time.h:382
int fr_time_start(void)
Initialize the local time.
Definition time.c:150
static fr_time_delta_t fr_time_delta_from_timespec(struct timespec const *ts)
Definition time.h:614
static fr_time_delta_t fr_unix_time_sub_time_time(fr_unix_time_t a, fr_unix_time_t b)
Definition time.h:335
#define fr_time_max()
Definition time.h:143
#define fr_time_delta_max()
Definition time.h:150
static int64_t fr_unix_time_to_hour(fr_unix_time_t delta)
Definition time.h:516
static int64_t fr_time_delta_to_msec(fr_time_delta_t delta)
Definition time.h:637
fr_slen_t fr_unix_time_to_str(fr_sbuff_t *out, fr_unix_time_t time, fr_time_res_t res, bool utc)
Convert unix time to string.
Definition time.c:1158
static int8_t fr_time_cmp(fr_time_t a, fr_time_t b)
Compare two fr_time_t values.
Definition time.h:916
static fr_unix_time_t fr_unix_time_from_usec(int64_t usec)
Definition time.h:428
int64_t fr_time_epoch
monotonic clock at boot, i.e. our epoch
Definition time.c:86
struct fr_unix_time_s fr_unix_time_t
"Unix" time.
int64_t const fr_time_multiplier_by_res[]
Definition time.c:32
A time delta, a difference in time measured in nanoseconds.
Definition time.h:80
"server local" time.
Definition time.h:69
"Unix" time.
Definition time.h:95
static size_t char fr_sbuff_t size_t inlen
Definition value.h:997
int nonnull(2, 5))
int format(printf, 5, 0))
static size_t char ** out
Definition value.h:997