Coverage Report

Created: 2025-07-11 06:47

/src/gpsd/gpsd-3.26.2~dev/include/timespec.h
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * This file is Copyright by the GPSD project
3
 * SPDX-License-Identifier: BSD-2-clause
4
 */
5
6
#ifndef GPSD_TIMESPEC_H
7
#define GPSD_TIMESPEC_H
8
9
#include <math.h>          // for modf()
10
#include <stdbool.h>       // for bool
11
12
0
#define NS_IN_SEC       1000000000LL     // nanoseconds in a second
13
0
#define NS_IN_MS        1000000LL        // nanoseconds in a millisecond
14
#define US_IN_SEC       1000000LL        // microseconds in a second
15
0
#define MS_IN_SEC       1000LL           // milliseconds in a second
16
17
// convert a timespec_t to an int64_t of milliseconds
18
0
#define TSTOMS(ts) ((int64_t)((ts)->tv_sec) * MS_IN_SEC + \
19
0
                    (int64_t)((ts)->tv_nsec / NS_IN_MS))
20
21
/* normalize a timespec
22
 *
23
 * three cases to note
24
 * if tv_sec is positive, then tv_nsec must be positive
25
 * if tv_sec is negative, then tv_nsec must be negative
26
 * if tv_sec is zero, then tv_nsec may be positive or negative.
27
 *
28
 * this only handles the case where two normalized timespecs
29
 * are added or subtracted.  (e.g. only a one needs to be borrowed/carried
30
 *
31
 * NOTE: this normalization is not the same as ntpd uses
32
 */
33
34
/* return the difference between timespecs in nanoseconds
35
 * int may be too small, 32 bit long is too small, floats are too imprecise,
36
 * doubles are not quite precise enough
37
 * MUST be at least int64_t to maintain precision on 32 bit code */
38
#define timespec_diff_ns(x, y) \
39
0
    (int64_t)((((x).tv_sec-(y).tv_sec)*NS_IN_SEC)+(x).tv_nsec-(y).tv_nsec)
40
41
static inline void TS_NORM( struct timespec *ts)
42
0
{
43
0
    if ((1 <= ts->tv_sec) ||
44
0
        ((0 == ts->tv_sec) &&
45
0
         (0 <= ts->tv_nsec))) {
46
        // result is positive
47
0
        if (NS_IN_SEC <= ts->tv_nsec) {
48
            // borrow from tv_sec
49
0
            ts->tv_nsec -= NS_IN_SEC;
50
0
            ts->tv_sec++;
51
0
        } else if (0 > (ts)->tv_nsec) {
52
            // carry to tv_sec
53
0
            ts->tv_nsec += NS_IN_SEC;
54
0
            ts->tv_sec--;
55
0
        }
56
0
    }  else {
57
        // result is negative
58
0
        if (-NS_IN_SEC >= ts->tv_nsec) {
59
            // carry to tv_sec
60
0
            ts->tv_nsec += NS_IN_SEC;
61
0
            ts->tv_sec--;
62
0
        } else if (0 < ts->tv_nsec) {
63
            // borrow from tv_sec
64
0
            ts->tv_nsec -= NS_IN_SEC;
65
0
            ts->tv_sec++;
66
0
        }
67
0
    }
68
0
}
Unexecuted instantiation: FuzzJson.c:TS_NORM
Unexecuted instantiation: libgps_json.c:TS_NORM
Unexecuted instantiation: rtcm2_json.c:TS_NORM
Unexecuted instantiation: rtcm3_json.c:TS_NORM
Unexecuted instantiation: shared_json.c:TS_NORM
Unexecuted instantiation: hex.c:TS_NORM
Unexecuted instantiation: json.c:TS_NORM
Unexecuted instantiation: gpsutils.c:TS_NORM
Unexecuted instantiation: FuzzPacket.c:TS_NORM
Unexecuted instantiation: packet.c:TS_NORM
Unexecuted instantiation: driver_rtcm2.c:TS_NORM
Unexecuted instantiation: isgps.c:TS_NORM
Unexecuted instantiation: libgpsd_core.c:TS_NORM
Unexecuted instantiation: net_gnss_dispatch.c:TS_NORM
Unexecuted instantiation: net_ntrip.c:TS_NORM
Unexecuted instantiation: ppsthread.c:TS_NORM
Unexecuted instantiation: pseudonmea.c:TS_NORM
Unexecuted instantiation: serial.c:TS_NORM
Unexecuted instantiation: timebase.c:TS_NORM
Unexecuted instantiation: bsd_base64.c:TS_NORM
Unexecuted instantiation: driver_nmea0183.c:TS_NORM
Unexecuted instantiation: driver_nmea2000.c:TS_NORM
Unexecuted instantiation: drivers.c:TS_NORM
Unexecuted instantiation: driver_sirf.c:TS_NORM
Unexecuted instantiation: driver_skytraq.c:TS_NORM
Unexecuted instantiation: driver_superstar2.c:TS_NORM
Unexecuted instantiation: driver_tsip.c:TS_NORM
Unexecuted instantiation: driver_ubx.c:TS_NORM
Unexecuted instantiation: driver_zodiac.c:TS_NORM
Unexecuted instantiation: geoid.c:TS_NORM
Unexecuted instantiation: net_dgpsip.c:TS_NORM
Unexecuted instantiation: pseudoais.c:TS_NORM
Unexecuted instantiation: subframe.c:TS_NORM
Unexecuted instantiation: driver_ais.c:TS_NORM
Unexecuted instantiation: driver_allystar.c:TS_NORM
Unexecuted instantiation: driver_casic.c:TS_NORM
Unexecuted instantiation: driver_evermore.c:TS_NORM
Unexecuted instantiation: driver_garmin.c:TS_NORM
Unexecuted instantiation: driver_garmin_txt.c:TS_NORM
Unexecuted instantiation: driver_geostar.c:TS_NORM
Unexecuted instantiation: driver_greis.c:TS_NORM
Unexecuted instantiation: driver_italk.c:TS_NORM
Unexecuted instantiation: driver_navcom.c:TS_NORM
Unexecuted instantiation: driver_oncore.c:TS_NORM
Unexecuted instantiation: driver_rtcm3.c:TS_NORM
Unexecuted instantiation: gps_maskdump.c:TS_NORM
Unexecuted instantiation: libgps_core.c:TS_NORM
Unexecuted instantiation: libgps_shm.c:TS_NORM
Unexecuted instantiation: libgps_sock.c:TS_NORM
Unexecuted instantiation: netlib.c:TS_NORM
Unexecuted instantiation: timespec_str.c:TS_NORM
69
70
// normalize a timeval
71
#define TV_NORM(tv)  \
72
    do { \
73
        if (US_IN_SEC <= (tv)->tv_usec) { \
74
            (tv)->tv_usec -= US_IN_SEC; \
75
            (tv)->tv_sec++; \
76
        } else if (0 > (tv)->tv_usec) { \
77
            (tv)->tv_usec += US_IN_SEC; \
78
            (tv)->tv_sec--; \
79
        } \
80
    } while (0)
81
82
// convert timespec to timeval, with rounding
83
#define TSTOTV(tv, ts) \
84
    do { \
85
        (tv)->tv_sec = (ts)->tv_sec; \
86
        (tv)->tv_usec = ((ts)->tv_nsec + 500)/1000; \
87
        TV_NORM(tv); \
88
    } while (0)
89
90
// convert timeval to timespec
91
#define TVTOTS(ts, tv) \
92
    do { \
93
        (ts)->tv_sec = (tv)->tv_sec; \
94
        (ts)->tv_nsec = (tv)->tv_usec*1000; \
95
        TS_NORM(ts); \
96
    } while (0)
97
98
// subtract two timespec
99
#define TS_SUB(r, ts1, ts2) \
100
0
    do { \
101
0
        (r)->tv_sec = (ts1)->tv_sec - (ts2)->tv_sec; \
102
0
        (r)->tv_nsec = (ts1)->tv_nsec - (ts2)->tv_nsec; \
103
0
        TS_NORM(r); \
104
0
    } while (0)
105
106
// subtract two timespec, return a double
107
#define TS_SUB_D(ts1, ts2) \
108
0
    ((double)((ts1)->tv_sec - (ts2)->tv_sec) + \
109
0
      ((double)((ts1)->tv_nsec - (ts2)->tv_nsec) * 1e-9))
110
111
// true if normalized timespec is non zero
112
#define TS_NZ(ts) (0 != (ts)->tv_sec || 0 != (ts)->tv_nsec)
113
114
// true if normalized timespec equal or greater than zero
115
0
#define TS_GEZ(ts) (0 <= (ts)->tv_sec && 0 <= (ts)->tv_nsec)
116
117
// true if normalized timespec greater than zero
118
#define TS_GZ(ts) (0 < (ts)->tv_sec || 0 < (ts)->tv_nsec)
119
120
// true if normalized timespec1 greater than timespec2
121
0
#define TS_GT(ts1, ts2) ((ts1)->tv_sec > (ts2)->tv_sec || \
122
0
                         ((ts1)->tv_sec == (ts2)->tv_sec && \
123
0
                          (ts1)->tv_nsec > (ts2)->tv_nsec))
124
125
// true if normalized timespec1 greater or equal to timespec2
126
#define TS_GE(ts1, ts2) ((ts1)->tv_sec > (ts2)->tv_sec || \
127
                         ((ts1)->tv_sec == (ts2)->tv_sec && \
128
                          (ts1)->tv_nsec >= (ts2)->tv_nsec))
129
130
// true if normalized timespec1 equal to timespec2
131
0
#define TS_EQ(ts1, ts2) ((ts1)->tv_sec == (ts2)->tv_sec && \
132
0
                         (ts1)->tv_nsec == (ts2)->tv_nsec)
133
134
/* convert a timespec to a double.
135
 * if tv_sec > 2, then inevitable loss of precision in tv_nsec
136
 * so best to NEVER use TSTONS()
137
 * WARNING replacing 1e9 with NS_IN_SEC causes loss of precision */
138
0
#define TSTONS(ts) ((double)((ts)->tv_sec + ((ts)->tv_nsec / 1e9)))
139
140
/* convert a double to a timespec_t
141
 * if D > 2, then inevitable loss of precision in nanoseconds
142
 */
143
#define DTOTS(ts, d) \
144
198
    do { \
145
198
        double int_part; \
146
198
        (ts)->tv_nsec = (long)(modf(d, &int_part) * 1e9); \
147
198
        (ts)->tv_sec = (time_t)int_part; \
148
198
    } while (0)
149
150
// convert integer (64 bit for full range) ms to a timespec_t
151
#define MSTOTS(ts, ms) \
152
0
    do { \
153
0
        (ts)->tv_sec = (time_t)(ms / 1000); \
154
0
        (ts)->tv_nsec = (long)((ms % 1000) * 1000000L); \
155
0
    } while (0)
156
157
// convert integer (64 bit for full range) us to a timespec_t
158
#define USTOTS(ts, ms) \
159
0
    do { \
160
0
        (ts)->tv_sec = (time_t)(ms / 1000000); \
161
0
        (ts)->tv_nsec = (long)((ms % 1000000) * 1000L); \
162
0
    } while (0)
163
164
#define TIMESPEC_LEN    42      // required length of a timespec buffer
165
166
extern const char *timespec_str(const struct timespec *, char *, size_t);
167
168
bool nanowait(int, struct timespec *);
169
170
#endif  // GPSD_TIMESPEC_H
171
172
// vim: set expandtab shiftwidth=4