xref: /openssl/include/internal/time.h (revision 4d32f533)
1 /*
2  * Copyright 2022 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the Apache License 2.0 (the "License").  You may not use
5  * this file except in compliance with the License.  You can obtain a copy
6  * in the file LICENSE in the source distribution or at
7  * https://www.openssl.org/source/license.html
8  */
9 
10 #ifndef OSSL_INTERNAL_TIME_H
11 # define OSSL_INTERNAL_TIME_H
12 # pragma once
13 
14 # include <openssl/e_os2.h>     /* uint64_t */
15 # include "internal/e_os.h"     /* for struct timeval */
16 # include "internal/safe_math.h"
17 
18 /*
19  * Internal type defining a time.
20  * This should be treated as an opaque structure.
21  *
22  * The time datum is Unix's 1970 and at nanosecond precision, this gives
23  * a range of 584 years roughly.
24  */
25 typedef struct {
26     uint64_t t;     /* Ticks since the epoch */
27 } OSSL_TIME;
28 
29 /* The precision of times allows this many values per second */
30 # define OSSL_TIME_SECOND ((uint64_t)1000000000)
31 
32 /* One millisecond. */
33 # define OSSL_TIME_MS     (OSSL_TIME_SECOND / 1000)
34 
35 /* One microsecond. */
36 # define OSSL_TIME_US     (OSSL_TIME_MS     / 1000)
37 
38 /* Convert a tick count into a time */
ossl_ticks2time(uint64_t ticks)39 static ossl_unused ossl_inline OSSL_TIME ossl_ticks2time(uint64_t ticks)
40 {
41     OSSL_TIME r;
42 
43     r.t = ticks;
44     return r;
45 }
46 
47 /* Convert a time to a tick count */
ossl_time2ticks(OSSL_TIME t)48 static ossl_unused ossl_inline uint64_t ossl_time2ticks(OSSL_TIME t)
49 {
50     return t.t;
51 }
52 
53 /* Get current time */
54 OSSL_TIME ossl_time_now(void);
55 
56 /* The beginning and end of the time range */
ossl_time_zero(void)57 static ossl_unused ossl_inline OSSL_TIME ossl_time_zero(void)
58 {
59     return ossl_ticks2time(0);
60 }
61 
ossl_time_infinite(void)62 static ossl_unused ossl_inline OSSL_TIME ossl_time_infinite(void)
63 {
64     return ossl_ticks2time(~(uint64_t)0);
65 }
66 
67 
68 /* Convert time to timeval */
69 static ossl_unused ossl_inline
ossl_time_time_to_timeval(OSSL_TIME t,struct timeval * out)70 void ossl_time_time_to_timeval(OSSL_TIME t, struct timeval *out)
71 {
72 #ifdef _WIN32
73     out->tv_sec = (long int)(t.t / OSSL_TIME_SECOND);
74 #else
75     out->tv_sec = (time_t)(t.t / OSSL_TIME_SECOND);
76 #endif
77     out->tv_usec = (t.t % OSSL_TIME_SECOND) / (OSSL_TIME_SECOND / 1000000);
78 }
79 
80 /* Convert time_t to OSSL_TIME */
ossl_time_from_time_t(time_t t)81 static ossl_inline OSSL_TIME ossl_time_from_time_t(time_t t)
82 {
83     OSSL_TIME ot;
84 
85     ot.t = t;
86     ot.t *= OSSL_TIME_SECOND;
87     return ot;
88 }
89 
90 /* Compare two time values, return -1 if less, 1 if greater and 0 if equal */
91 static ossl_unused ossl_inline
ossl_time_compare(OSSL_TIME a,OSSL_TIME b)92 int ossl_time_compare(OSSL_TIME a, OSSL_TIME b)
93 {
94     if (a.t > b.t)
95         return 1;
96     if (a.t < b.t)
97         return -1;
98     return 0;
99 }
100 
101 /* Returns true if an OSSL_TIME is ossl_time_zero(). */
102 static ossl_unused ossl_inline
ossl_time_is_zero(OSSL_TIME t)103 int ossl_time_is_zero(OSSL_TIME t)
104 {
105     return ossl_time_compare(t, ossl_time_zero()) == 0;
106 }
107 
108 /* Returns true if an OSSL_TIME is ossl_time_infinite(). */
109 static ossl_unused ossl_inline
ossl_time_is_infinite(OSSL_TIME t)110 int ossl_time_is_infinite(OSSL_TIME t)
111 {
112     return ossl_time_compare(t, ossl_time_infinite()) == 0;
113 }
114 
115 /*
116  * Arithmetic operations on times.
117  * These operations are saturating, in that an overflow or underflow returns
118  * the largest or smallest value respectively.
119  */
OSSL_SAFE_MATH_UNSIGNED(time,uint64_t)120 OSSL_SAFE_MATH_UNSIGNED(time, uint64_t)
121 
122 static ossl_unused ossl_inline
123 OSSL_TIME ossl_time_add(OSSL_TIME a, OSSL_TIME b)
124 {
125     OSSL_TIME r;
126     int err = 0;
127 
128     r.t = safe_add_time(a.t, b.t, &err);
129     return err ? ossl_time_infinite() : r;
130 }
131 
132 static ossl_unused ossl_inline
ossl_time_subtract(OSSL_TIME a,OSSL_TIME b)133 OSSL_TIME ossl_time_subtract(OSSL_TIME a, OSSL_TIME b)
134 {
135     OSSL_TIME r;
136     int err = 0;
137 
138     r.t = safe_sub_time(a.t, b.t, &err);
139     return err ? ossl_time_zero() : r;
140 }
141 
142 /* Returns |a - b|. */
143 static ossl_unused ossl_inline
ossl_time_abs_difference(OSSL_TIME a,OSSL_TIME b)144 OSSL_TIME ossl_time_abs_difference(OSSL_TIME a, OSSL_TIME b)
145 {
146     return a.t > b.t ? ossl_time_subtract(a, b)
147                      : ossl_time_subtract(b, a);
148 }
149 
150 static ossl_unused ossl_inline
ossl_time_multiply(OSSL_TIME a,uint64_t b)151 OSSL_TIME ossl_time_multiply(OSSL_TIME a, uint64_t b)
152 {
153     OSSL_TIME r;
154     int err = 0;
155 
156     r.t = safe_mul_time(a.t, b, &err);
157     return err ? ossl_time_infinite() : r;
158 }
159 
160 static ossl_unused ossl_inline
ossl_time_divide(OSSL_TIME a,uint64_t b)161 OSSL_TIME ossl_time_divide(OSSL_TIME a, uint64_t b)
162 {
163     OSSL_TIME r;
164     int err = 0;
165 
166     r.t = safe_div_time(a.t, b, &err);
167     return err ? ossl_time_zero() : r;
168 }
169 
170 /* Return higher of the two given time values. */
171 static ossl_unused ossl_inline
ossl_time_max(OSSL_TIME a,OSSL_TIME b)172 OSSL_TIME ossl_time_max(OSSL_TIME a, OSSL_TIME b)
173 {
174     return a.t > b.t ? a : b;
175 }
176 
177 /* Return the lower of the two given time values. */
178 static ossl_unused ossl_inline
ossl_time_min(OSSL_TIME a,OSSL_TIME b)179 OSSL_TIME ossl_time_min(OSSL_TIME a, OSSL_TIME b)
180 {
181     return a.t < b.t ? a : b;
182 }
183 
184 #endif
185