xref: /freebsd/crypto/openssl/include/internal/time.h (revision e7be843b4a162e68651d3911f0357ed464915629)
1*e7be843bSPierre Pronchery /*
2*e7be843bSPierre Pronchery  * Copyright 2022-2023 The OpenSSL Project Authors. All Rights Reserved.
3*e7be843bSPierre Pronchery  *
4*e7be843bSPierre Pronchery  * Licensed under the Apache License 2.0 (the "License").  You may not use
5*e7be843bSPierre Pronchery  * this file except in compliance with the License.  You can obtain a copy
6*e7be843bSPierre Pronchery  * in the file LICENSE in the source distribution or at
7*e7be843bSPierre Pronchery  * https://www.openssl.org/source/license.html
8*e7be843bSPierre Pronchery  */
9*e7be843bSPierre Pronchery 
10*e7be843bSPierre Pronchery #ifndef OSSL_INTERNAL_TIME_H
11*e7be843bSPierre Pronchery # define OSSL_INTERNAL_TIME_H
12*e7be843bSPierre Pronchery # pragma once
13*e7be843bSPierre Pronchery 
14*e7be843bSPierre Pronchery # include <openssl/e_os2.h>     /* uint64_t */
15*e7be843bSPierre Pronchery # include "internal/e_os.h"
16*e7be843bSPierre Pronchery # include "internal/e_winsock.h" /* for struct timeval */
17*e7be843bSPierre Pronchery # include "internal/safe_math.h"
18*e7be843bSPierre Pronchery 
19*e7be843bSPierre Pronchery /*
20*e7be843bSPierre Pronchery  * Internal type defining a time.
21*e7be843bSPierre Pronchery  * This should be treated as an opaque structure.
22*e7be843bSPierre Pronchery  *
23*e7be843bSPierre Pronchery  * The time datum is Unix's 1970 and at nanosecond precision, this gives
24*e7be843bSPierre Pronchery  * a range of 584 years roughly.
25*e7be843bSPierre Pronchery  */
26*e7be843bSPierre Pronchery typedef struct {
27*e7be843bSPierre Pronchery     uint64_t t;     /* Ticks since the epoch */
28*e7be843bSPierre Pronchery } OSSL_TIME;
29*e7be843bSPierre Pronchery 
30*e7be843bSPierre Pronchery /* The precision of times allows this many values per second */
31*e7be843bSPierre Pronchery # define OSSL_TIME_SECOND ((uint64_t)1000000000)
32*e7be843bSPierre Pronchery 
33*e7be843bSPierre Pronchery /* One millisecond. */
34*e7be843bSPierre Pronchery # define OSSL_TIME_MS     (OSSL_TIME_SECOND / 1000)
35*e7be843bSPierre Pronchery 
36*e7be843bSPierre Pronchery /* One microsecond. */
37*e7be843bSPierre Pronchery # define OSSL_TIME_US     (OSSL_TIME_MS     / 1000)
38*e7be843bSPierre Pronchery 
39*e7be843bSPierre Pronchery /* One nanosecond. */
40*e7be843bSPierre Pronchery # define OSSL_TIME_NS     (OSSL_TIME_US     / 1000)
41*e7be843bSPierre Pronchery 
42*e7be843bSPierre Pronchery #define ossl_seconds2time(s) ossl_ticks2time((s) * OSSL_TIME_SECOND)
43*e7be843bSPierre Pronchery #define ossl_time2seconds(t) (ossl_time2ticks(t) / OSSL_TIME_SECOND)
44*e7be843bSPierre Pronchery #define ossl_ms2time(ms) ossl_ticks2time((ms) * OSSL_TIME_MS)
45*e7be843bSPierre Pronchery #define ossl_time2ms(t) (ossl_time2ticks(t) / OSSL_TIME_MS)
46*e7be843bSPierre Pronchery #define ossl_us2time(us) ossl_ticks2time((us) * OSSL_TIME_US)
47*e7be843bSPierre Pronchery #define ossl_time2us(t) (ossl_time2ticks(t) / OSSL_TIME_US)
48*e7be843bSPierre Pronchery 
49*e7be843bSPierre Pronchery /*
50*e7be843bSPierre Pronchery  * Arithmetic operations on times.
51*e7be843bSPierre Pronchery  * These operations are saturating, in that an overflow or underflow returns
52*e7be843bSPierre Pronchery  * the largest or smallest value respectively.
53*e7be843bSPierre Pronchery  */
OSSL_SAFE_MATH_UNSIGNED(time,uint64_t)54*e7be843bSPierre Pronchery OSSL_SAFE_MATH_UNSIGNED(time, uint64_t)
55*e7be843bSPierre Pronchery 
56*e7be843bSPierre Pronchery /* Convert a tick count into a time */
57*e7be843bSPierre Pronchery static ossl_unused ossl_inline
58*e7be843bSPierre Pronchery OSSL_TIME ossl_ticks2time(uint64_t ticks)
59*e7be843bSPierre Pronchery {
60*e7be843bSPierre Pronchery     OSSL_TIME r;
61*e7be843bSPierre Pronchery 
62*e7be843bSPierre Pronchery     r.t = ticks;
63*e7be843bSPierre Pronchery     return r;
64*e7be843bSPierre Pronchery }
65*e7be843bSPierre Pronchery 
66*e7be843bSPierre Pronchery /* Convert a time to a tick count */
67*e7be843bSPierre Pronchery static ossl_unused ossl_inline
ossl_time2ticks(OSSL_TIME t)68*e7be843bSPierre Pronchery uint64_t ossl_time2ticks(OSSL_TIME t)
69*e7be843bSPierre Pronchery {
70*e7be843bSPierre Pronchery     return t.t;
71*e7be843bSPierre Pronchery }
72*e7be843bSPierre Pronchery 
73*e7be843bSPierre Pronchery /* Get current time */
74*e7be843bSPierre Pronchery OSSL_TIME ossl_time_now(void);
75*e7be843bSPierre Pronchery 
76*e7be843bSPierre Pronchery /* The beginning and end of the time range */
77*e7be843bSPierre Pronchery static ossl_unused ossl_inline
ossl_time_zero(void)78*e7be843bSPierre Pronchery OSSL_TIME ossl_time_zero(void)
79*e7be843bSPierre Pronchery {
80*e7be843bSPierre Pronchery     return ossl_ticks2time(0);
81*e7be843bSPierre Pronchery }
82*e7be843bSPierre Pronchery 
83*e7be843bSPierre Pronchery static ossl_unused ossl_inline
ossl_time_infinite(void)84*e7be843bSPierre Pronchery OSSL_TIME ossl_time_infinite(void)
85*e7be843bSPierre Pronchery {
86*e7be843bSPierre Pronchery     return ossl_ticks2time(~(uint64_t)0);
87*e7be843bSPierre Pronchery }
88*e7be843bSPierre Pronchery 
89*e7be843bSPierre Pronchery 
90*e7be843bSPierre Pronchery /* Convert time to timeval */
91*e7be843bSPierre Pronchery static ossl_unused ossl_inline
ossl_time_to_timeval(OSSL_TIME t)92*e7be843bSPierre Pronchery struct timeval ossl_time_to_timeval(OSSL_TIME t)
93*e7be843bSPierre Pronchery {
94*e7be843bSPierre Pronchery     struct timeval tv;
95*e7be843bSPierre Pronchery     int err = 0;
96*e7be843bSPierre Pronchery 
97*e7be843bSPierre Pronchery     /*
98*e7be843bSPierre Pronchery      * Round up any nano secs which struct timeval doesn't support. Ensures that
99*e7be843bSPierre Pronchery      * we never return a zero time if the input time is non zero
100*e7be843bSPierre Pronchery      */
101*e7be843bSPierre Pronchery     t.t = safe_add_time(t.t, OSSL_TIME_US - 1, &err);
102*e7be843bSPierre Pronchery     if (err)
103*e7be843bSPierre Pronchery         t = ossl_time_infinite();
104*e7be843bSPierre Pronchery 
105*e7be843bSPierre Pronchery #ifdef _WIN32
106*e7be843bSPierre Pronchery     tv.tv_sec = (long int)(t.t / OSSL_TIME_SECOND);
107*e7be843bSPierre Pronchery #else
108*e7be843bSPierre Pronchery     tv.tv_sec = (time_t)(t.t / OSSL_TIME_SECOND);
109*e7be843bSPierre Pronchery #endif
110*e7be843bSPierre Pronchery     tv.tv_usec = (t.t % OSSL_TIME_SECOND) / OSSL_TIME_US;
111*e7be843bSPierre Pronchery     return tv;
112*e7be843bSPierre Pronchery }
113*e7be843bSPierre Pronchery 
114*e7be843bSPierre Pronchery /* Convert timeval to time */
115*e7be843bSPierre Pronchery static ossl_unused ossl_inline
ossl_time_from_timeval(struct timeval tv)116*e7be843bSPierre Pronchery OSSL_TIME ossl_time_from_timeval(struct timeval tv)
117*e7be843bSPierre Pronchery {
118*e7be843bSPierre Pronchery     OSSL_TIME t;
119*e7be843bSPierre Pronchery 
120*e7be843bSPierre Pronchery #ifndef __DJGPP__ /* tv_sec is unsigned on djgpp. */
121*e7be843bSPierre Pronchery     if (tv.tv_sec < 0)
122*e7be843bSPierre Pronchery         return ossl_time_zero();
123*e7be843bSPierre Pronchery #endif
124*e7be843bSPierre Pronchery     t.t = tv.tv_sec * OSSL_TIME_SECOND + tv.tv_usec * OSSL_TIME_US;
125*e7be843bSPierre Pronchery     return t;
126*e7be843bSPierre Pronchery }
127*e7be843bSPierre Pronchery 
128*e7be843bSPierre Pronchery /* Convert OSSL_TIME to time_t */
129*e7be843bSPierre Pronchery static ossl_unused ossl_inline
ossl_time_to_time_t(OSSL_TIME t)130*e7be843bSPierre Pronchery time_t ossl_time_to_time_t(OSSL_TIME t)
131*e7be843bSPierre Pronchery {
132*e7be843bSPierre Pronchery     return (time_t)(t.t / OSSL_TIME_SECOND);
133*e7be843bSPierre Pronchery }
134*e7be843bSPierre Pronchery 
135*e7be843bSPierre Pronchery /* Convert time_t to OSSL_TIME */
136*e7be843bSPierre Pronchery static ossl_unused ossl_inline
ossl_time_from_time_t(time_t t)137*e7be843bSPierre Pronchery OSSL_TIME ossl_time_from_time_t(time_t t)
138*e7be843bSPierre Pronchery {
139*e7be843bSPierre Pronchery     OSSL_TIME ot;
140*e7be843bSPierre Pronchery 
141*e7be843bSPierre Pronchery     ot.t = t;
142*e7be843bSPierre Pronchery     ot.t *= OSSL_TIME_SECOND;
143*e7be843bSPierre Pronchery     return ot;
144*e7be843bSPierre Pronchery }
145*e7be843bSPierre Pronchery 
146*e7be843bSPierre Pronchery /* Compare two time values, return -1 if less, 1 if greater and 0 if equal */
147*e7be843bSPierre Pronchery static ossl_unused ossl_inline
ossl_time_compare(OSSL_TIME a,OSSL_TIME b)148*e7be843bSPierre Pronchery int ossl_time_compare(OSSL_TIME a, OSSL_TIME b)
149*e7be843bSPierre Pronchery {
150*e7be843bSPierre Pronchery     if (a.t > b.t)
151*e7be843bSPierre Pronchery         return 1;
152*e7be843bSPierre Pronchery     if (a.t < b.t)
153*e7be843bSPierre Pronchery         return -1;
154*e7be843bSPierre Pronchery     return 0;
155*e7be843bSPierre Pronchery }
156*e7be843bSPierre Pronchery 
157*e7be843bSPierre Pronchery /* Returns true if an OSSL_TIME is ossl_time_zero(). */
158*e7be843bSPierre Pronchery static ossl_unused ossl_inline
ossl_time_is_zero(OSSL_TIME t)159*e7be843bSPierre Pronchery int ossl_time_is_zero(OSSL_TIME t)
160*e7be843bSPierre Pronchery {
161*e7be843bSPierre Pronchery     return ossl_time_compare(t, ossl_time_zero()) == 0;
162*e7be843bSPierre Pronchery }
163*e7be843bSPierre Pronchery 
164*e7be843bSPierre Pronchery /* Returns true if an OSSL_TIME is ossl_time_infinite(). */
165*e7be843bSPierre Pronchery static ossl_unused ossl_inline
ossl_time_is_infinite(OSSL_TIME t)166*e7be843bSPierre Pronchery int ossl_time_is_infinite(OSSL_TIME t)
167*e7be843bSPierre Pronchery {
168*e7be843bSPierre Pronchery     return ossl_time_compare(t, ossl_time_infinite()) == 0;
169*e7be843bSPierre Pronchery }
170*e7be843bSPierre Pronchery 
171*e7be843bSPierre Pronchery static ossl_unused ossl_inline
ossl_time_add(OSSL_TIME a,OSSL_TIME b)172*e7be843bSPierre Pronchery OSSL_TIME ossl_time_add(OSSL_TIME a, OSSL_TIME b)
173*e7be843bSPierre Pronchery {
174*e7be843bSPierre Pronchery     OSSL_TIME r;
175*e7be843bSPierre Pronchery     int err = 0;
176*e7be843bSPierre Pronchery 
177*e7be843bSPierre Pronchery     r.t = safe_add_time(a.t, b.t, &err);
178*e7be843bSPierre Pronchery     return err ? ossl_time_infinite() : r;
179*e7be843bSPierre Pronchery }
180*e7be843bSPierre Pronchery 
181*e7be843bSPierre Pronchery static ossl_unused ossl_inline
ossl_time_subtract(OSSL_TIME a,OSSL_TIME b)182*e7be843bSPierre Pronchery OSSL_TIME ossl_time_subtract(OSSL_TIME a, OSSL_TIME b)
183*e7be843bSPierre Pronchery {
184*e7be843bSPierre Pronchery     OSSL_TIME r;
185*e7be843bSPierre Pronchery     int err = 0;
186*e7be843bSPierre Pronchery 
187*e7be843bSPierre Pronchery     r.t = safe_sub_time(a.t, b.t, &err);
188*e7be843bSPierre Pronchery     return err ? ossl_time_zero() : r;
189*e7be843bSPierre Pronchery }
190*e7be843bSPierre Pronchery 
191*e7be843bSPierre Pronchery /* Returns |a - b|. */
192*e7be843bSPierre Pronchery static ossl_unused ossl_inline
ossl_time_abs_difference(OSSL_TIME a,OSSL_TIME b)193*e7be843bSPierre Pronchery OSSL_TIME ossl_time_abs_difference(OSSL_TIME a, OSSL_TIME b)
194*e7be843bSPierre Pronchery {
195*e7be843bSPierre Pronchery     return a.t > b.t ? ossl_time_subtract(a, b)
196*e7be843bSPierre Pronchery                      : ossl_time_subtract(b, a);
197*e7be843bSPierre Pronchery }
198*e7be843bSPierre Pronchery 
199*e7be843bSPierre Pronchery static ossl_unused ossl_inline
ossl_time_multiply(OSSL_TIME a,uint64_t b)200*e7be843bSPierre Pronchery OSSL_TIME ossl_time_multiply(OSSL_TIME a, uint64_t b)
201*e7be843bSPierre Pronchery {
202*e7be843bSPierre Pronchery     OSSL_TIME r;
203*e7be843bSPierre Pronchery     int err = 0;
204*e7be843bSPierre Pronchery 
205*e7be843bSPierre Pronchery     r.t = safe_mul_time(a.t, b, &err);
206*e7be843bSPierre Pronchery     return err ? ossl_time_infinite() : r;
207*e7be843bSPierre Pronchery }
208*e7be843bSPierre Pronchery 
209*e7be843bSPierre Pronchery static ossl_unused ossl_inline
ossl_time_divide(OSSL_TIME a,uint64_t b)210*e7be843bSPierre Pronchery OSSL_TIME ossl_time_divide(OSSL_TIME a, uint64_t b)
211*e7be843bSPierre Pronchery {
212*e7be843bSPierre Pronchery     OSSL_TIME r;
213*e7be843bSPierre Pronchery     int err = 0;
214*e7be843bSPierre Pronchery 
215*e7be843bSPierre Pronchery     r.t = safe_div_time(a.t, b, &err);
216*e7be843bSPierre Pronchery     return err ? ossl_time_zero() : r;
217*e7be843bSPierre Pronchery }
218*e7be843bSPierre Pronchery 
219*e7be843bSPierre Pronchery static ossl_unused ossl_inline
ossl_time_muldiv(OSSL_TIME a,uint64_t b,uint64_t c)220*e7be843bSPierre Pronchery OSSL_TIME ossl_time_muldiv(OSSL_TIME a, uint64_t b, uint64_t c)
221*e7be843bSPierre Pronchery {
222*e7be843bSPierre Pronchery     OSSL_TIME r;
223*e7be843bSPierre Pronchery     int err = 0;
224*e7be843bSPierre Pronchery 
225*e7be843bSPierre Pronchery     r.t = safe_muldiv_time(a.t, b, c, &err);
226*e7be843bSPierre Pronchery     return err ? ossl_time_zero() : r;
227*e7be843bSPierre Pronchery }
228*e7be843bSPierre Pronchery 
229*e7be843bSPierre Pronchery /* Return higher of the two given time values. */
230*e7be843bSPierre Pronchery static ossl_unused ossl_inline
ossl_time_max(OSSL_TIME a,OSSL_TIME b)231*e7be843bSPierre Pronchery OSSL_TIME ossl_time_max(OSSL_TIME a, OSSL_TIME b)
232*e7be843bSPierre Pronchery {
233*e7be843bSPierre Pronchery     return a.t > b.t ? a : b;
234*e7be843bSPierre Pronchery }
235*e7be843bSPierre Pronchery 
236*e7be843bSPierre Pronchery /* Return the lower of the two given time values. */
237*e7be843bSPierre Pronchery static ossl_unused ossl_inline
ossl_time_min(OSSL_TIME a,OSSL_TIME b)238*e7be843bSPierre Pronchery OSSL_TIME ossl_time_min(OSSL_TIME a, OSSL_TIME b)
239*e7be843bSPierre Pronchery {
240*e7be843bSPierre Pronchery     return a.t < b.t ? a : b;
241*e7be843bSPierre Pronchery }
242*e7be843bSPierre Pronchery 
243*e7be843bSPierre Pronchery #endif
244