back to topotato report
topotato coverage report
Current view: top level - lib - monotime.h (source / functions) Hit Total Coverage
Test: test_pim6_basic.py::PIM6Basic Lines: 25 44 56.8 %
Date: 2023-02-24 18:38:38 Functions: 4 6 66.7 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2017  David Lamparter, for NetDEF, Inc.
       3             :  *
       4             :  * Permission to use, copy, modify, and distribute this software for any
       5             :  * purpose with or without fee is hereby granted, provided that the above
       6             :  * copyright notice and this permission notice appear in all copies.
       7             :  *
       8             :  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
       9             :  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
      10             :  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
      11             :  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
      12             :  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
      13             :  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
      14             :  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
      15             :  */
      16             : 
      17             : #ifndef _FRR_MONOTIME_H
      18             : #define _FRR_MONOTIME_H
      19             : 
      20             : #include <stdint.h>
      21             : #include <time.h>
      22             : #include <sys/time.h>
      23             : 
      24             : #ifdef __cplusplus
      25             : extern "C" {
      26             : #endif
      27             : 
      28             : struct fbuf;
      29             : struct printfrr_eargs;
      30             : 
      31             : #ifndef TIMESPEC_TO_TIMEVAL
      32             : /* should be in sys/time.h on BSD & Linux libcs */
      33             : #define TIMESPEC_TO_TIMEVAL(tv, ts)                                            \
      34             :         do {                                                                   \
      35             :                 (tv)->tv_sec = (ts)->tv_sec;                                   \
      36             :                 (tv)->tv_usec = (ts)->tv_nsec / 1000;                          \
      37             :         } while (0)
      38             : #endif
      39             : #ifndef TIMEVAL_TO_TIMESPEC
      40             : /* should be in sys/time.h on BSD & Linux libcs */
      41             : #define TIMEVAL_TO_TIMESPEC(tv, ts)                                            \
      42             :         do {                                                                   \
      43             :                 (ts)->tv_sec = (tv)->tv_sec;                                   \
      44             :                 (ts)->tv_nsec = (tv)->tv_usec * 1000;                          \
      45             :         } while (0)
      46             : #endif
      47             : 
      48             : /* Linux/glibc is sadly missing these timespec helpers */
      49             : #ifndef timespecadd
      50             : #define timespecadd(tsp, usp, vsp)                                             \
      51             :         do {                                                                   \
      52             :                 (vsp)->tv_sec = (tsp)->tv_sec + (usp)->tv_sec;                 \
      53             :                 (vsp)->tv_nsec = (tsp)->tv_nsec + (usp)->tv_nsec;              \
      54             :                 if ((vsp)->tv_nsec >= 1000000000L) {                           \
      55             :                         (vsp)->tv_sec++;                                       \
      56             :                         (vsp)->tv_nsec -= 1000000000L;                         \
      57             :                 }                                                              \
      58             :         } while (0)
      59             : #endif
      60             : 
      61             : #ifndef timespecsub
      62             : #define timespecsub(tsp, usp, vsp)                                             \
      63             :         do {                                                                   \
      64             :                 (vsp)->tv_sec = (tsp)->tv_sec - (usp)->tv_sec;                 \
      65             :                 (vsp)->tv_nsec = (tsp)->tv_nsec - (usp)->tv_nsec;              \
      66             :                 if ((vsp)->tv_nsec < 0) {                                      \
      67             :                         (vsp)->tv_sec--;                                       \
      68             :                         (vsp)->tv_nsec += 1000000000L;                         \
      69             :                 }                                                              \
      70             :         } while (0)
      71             : #endif
      72             : 
      73       28532 : static inline time_t monotime(struct timeval *tvo)
      74             : {
      75       28532 :         struct timespec ts;
      76             : 
      77       28532 :         clock_gettime(CLOCK_MONOTONIC, &ts);
      78       28524 :         if (tvo) {
      79       28524 :                 TIMESPEC_TO_TIMEVAL(tvo, &ts);
      80             :         }
      81       28534 :         return ts.tv_sec;
      82             : }
      83             : 
      84             : #define ONE_DAY_SECOND (60 * 60 * 24)
      85             : #define ONE_WEEK_SECOND (ONE_DAY_SECOND * 7)
      86             : #define ONE_YEAR_SECOND (ONE_DAY_SECOND * 365)
      87             : 
      88             : /* the following two return microseconds, not time_t!
      89             :  *
      90             :  * also, they're negative forms of each other, but having both makes the
      91             :  * code more readable
      92             :  */
      93          46 : static inline int64_t monotime_since(const struct timeval *ref,
      94             :                                      struct timeval *out)
      95             : {
      96          46 :         struct timeval tv;
      97          46 :         monotime(&tv);
      98          46 :         timersub(&tv, ref, &tv);
      99          46 :         if (out)
     100           0 :                 *out = tv;
     101          46 :         return (int64_t)tv.tv_sec * 1000000LL + tv.tv_usec;
     102             : }
     103             : 
     104       12930 : static inline int64_t monotime_until(const struct timeval *ref,
     105             :                                      struct timeval *out)
     106             : {
     107       12930 :         struct timeval tv;
     108       12930 :         monotime(&tv);
     109       12930 :         timersub(ref, &tv, &tv);
     110       12930 :         if (out)
     111       12928 :                 *out = tv;
     112       12930 :         return (int64_t)tv.tv_sec * 1000000LL + tv.tv_usec;
     113             : }
     114             : 
     115           0 : static inline time_t monotime_to_realtime(const struct timeval *mono,
     116             :                                           struct timeval *realout)
     117             : {
     118           0 :         struct timeval delta, real;
     119             : 
     120           0 :         monotime_since(mono, &delta);
     121           0 :         gettimeofday(&real, NULL);
     122             : 
     123           0 :         timersub(&real, &delta, &real);
     124           0 :         if (realout)
     125           0 :                 *realout = real;
     126           0 :         return real.tv_sec;
     127             : }
     128             : 
     129             : /* Char buffer size for time-to-string api */
     130             : #define MONOTIME_STRLEN 32
     131             : 
     132           0 : static inline char *time_to_string(time_t ts, char *buf)
     133             : {
     134           0 :         struct timeval tv;
     135           0 :         time_t tbuf;
     136             : 
     137           0 :         monotime(&tv);
     138           0 :         tbuf = time(NULL) - (tv.tv_sec - ts);
     139             : 
     140           0 :         return ctime_r(&tbuf, buf);
     141             : }
     142             : 
     143             : /* Convert interval to human-friendly string, used in cli output e.g. */
     144          12 : static inline const char *frrtime_to_interval(time_t t, char *buf,
     145             :                                               size_t buflen)
     146             : {
     147          12 :         struct tm tm;
     148             : 
     149          12 :         gmtime_r(&t, &tm);
     150             : 
     151          12 :         if (t < ONE_DAY_SECOND)
     152          12 :                 snprintf(buf, buflen, "%02d:%02d:%02d", tm.tm_hour, tm.tm_min,
     153             :                          tm.tm_sec);
     154           0 :         else if (t < ONE_WEEK_SECOND)
     155           0 :                 snprintf(buf, buflen, "%dd%02dh%02dm", tm.tm_yday, tm.tm_hour,
     156             :                          tm.tm_min);
     157             :         else
     158           0 :                 snprintf(buf, buflen, "%02dw%dd%02dh", tm.tm_yday / 7,
     159           0 :                          tm.tm_yday - ((tm.tm_yday / 7) * 7), tm.tm_hour);
     160          12 :         return buf;
     161             : }
     162             : 
     163             : enum {
     164             :         /* n/a - input was seconds precision, don't print any fractional */
     165             :         TIMEFMT_SECONDS = (1 << 0),
     166             :         /* caller is directly invoking printfrr_time and has pre-specified
     167             :          * I/Iu/Is/M/Mu/Ms/R/Ru/Rs (for printing timers)
     168             :          */
     169             :         TIMEFMT_PRESELECT = (1 << 1),
     170             :         /* don't print any output - this is needed for invoking printfrr_time
     171             :          * from another printfrr extensions to skip over flag characters
     172             :          */
     173             :         TIMEFMT_SKIP = (1 << 2),
     174             :         /* use spaces in appropriate places */
     175             :         TIMEFMT_SPACE = (1 << 3),
     176             : 
     177             :         /* input interpretations: */
     178             :         TIMEFMT_REALTIME = (1 << 8),
     179             :         TIMEFMT_MONOTONIC = (1 << 9),
     180             :         TIMEFMT_SINCE = (1 << 10),
     181             :         TIMEFMT_UNTIL = (1 << 11),
     182             : 
     183             :         TIMEFMT_ABSOLUTE = TIMEFMT_REALTIME | TIMEFMT_MONOTONIC,
     184             :         TIMEFMT_ANCHORS = TIMEFMT_SINCE | TIMEFMT_UNTIL,
     185             : 
     186             :         /* calendaric formats: */
     187             :         TIMEFMT_ISO8601 = (1 << 16),
     188             : 
     189             :         /* interval formats: */
     190             :         /* 't' - use [t]raditional 3-block format */
     191             :         TIMEFMT_BASIC = (1 << 24),
     192             :         /* 'm' - select mm:ss */
     193             :         TIMEFMT_MMSS = (1 << 25),
     194             :         /* 'h' - select hh:mm:ss */
     195             :         TIMEFMT_HHMMSS = (1 << 26),
     196             :         /* 'd' - print as decimal number of seconds */
     197             :         TIMEFMT_DECIMAL = (1 << 27),
     198             :         /* 'mx'/'hx' - replace zero value with "--:--" or "--:--:--" */
     199             :         TIMEFMT_DASHES = (1 << 31),
     200             : 
     201             :         /* helpers for reference */
     202             :         TIMEFMT_TIMER_DEADLINE =
     203             :                 TIMEFMT_PRESELECT | TIMEFMT_MONOTONIC | TIMEFMT_UNTIL,
     204             :         TIMEFMT_TIMER_INTERVAL = TIMEFMT_PRESELECT,
     205             : };
     206             : 
     207             : extern ssize_t printfrr_time(struct fbuf *buf, struct printfrr_eargs *ea,
     208             :                              const struct timespec *ts, unsigned int flags);
     209             : 
     210             : #ifdef __cplusplus
     211             : }
     212             : #endif
     213             : 
     214             : #endif /* _FRR_MONOTIME_H */

Generated by: LCOV version v1.16-topotato