1 /*-
2  * Copyright (c) 2018 Limelight Networks, Inc.
3  * Copyright (c) 2014-2018 Mellanox Technologies, Ltd.
4  * Copyright (c) 2015 François Tigeot
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice unmodified, this list of conditions, and the following
12  *    disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #ifndef _LINUXKPI_LINUX_KTIME_H
30 #define	_LINUXKPI_LINUX_KTIME_H
31 
32 #include <linux/types.h>
33 #include <linux/time.h>
34 #include <linux/jiffies.h>
35 
36 /* time values in nanoseconds */
37 typedef s64 ktime_t;
38 
39 #define	KTIME_MAX			((s64)~((u64)1 << 63))
40 #define	KTIME_SEC_MAX			(KTIME_MAX / NSEC_PER_SEC)
41 
42 static inline int64_t
43 ktime_to_ns(ktime_t kt)
44 {
45 	return (kt);
46 }
47 
48 static inline ktime_t
49 ns_to_ktime(uint64_t nsec)
50 {
51 	return (nsec);
52 }
53 
54 static inline int64_t
55 ktime_divns(const ktime_t kt, int64_t div)
56 {
57 	return (kt / div);
58 }
59 
60 static inline int64_t
61 ktime_to_us(ktime_t kt)
62 {
63 	return (ktime_divns(kt, NSEC_PER_USEC));
64 }
65 
66 static inline int64_t
67 ktime_to_ms(ktime_t kt)
68 {
69 	return (ktime_divns(kt, NSEC_PER_MSEC));
70 }
71 
72 static inline struct timeval
73 ktime_to_timeval(ktime_t kt)
74 {
75 	return (ns_to_timeval(kt));
76 }
77 
78 static inline ktime_t
79 ktime_add_ns(ktime_t kt, int64_t ns)
80 {
81 	return (kt + ns);
82 }
83 
84 static inline ktime_t
85 ktime_add_ms(ktime_t kt, int64_t ms)
86 {
87 
88 	return (ktime_add_ns(kt, ms * NSEC_PER_MSEC));
89 }
90 
91 static inline ktime_t
92 ktime_add_us(ktime_t kt, int64_t us)
93 {
94 
95 	return (ktime_add_ns(kt, us * NSEC_PER_USEC));
96 }
97 
98 static inline ktime_t
99 ktime_sub_ns(ktime_t kt, int64_t ns)
100 {
101 	return (kt - ns);
102 }
103 
104 static inline ktime_t
105 ktime_set(const long secs, const unsigned long nsecs)
106 {
107 	ktime_t retval = {(s64) secs * NSEC_PER_SEC + (s64) nsecs};
108 
109 	return (retval);
110 }
111 
112 static inline ktime_t
113 ktime_sub(ktime_t lhs, ktime_t rhs)
114 {
115 	return (lhs - rhs);
116 }
117 
118 static inline int64_t
119 ktime_us_delta(ktime_t later, ktime_t earlier)
120 {
121 	ktime_t diff = ktime_sub(later, earlier);
122 
123 	return (ktime_to_us(diff));
124 }
125 
126 static inline int64_t
127 ktime_ms_delta(ktime_t later, ktime_t earlier)
128 {
129 	ktime_t diff = ktime_sub(later, earlier);
130 
131 	return (ktime_to_ms(diff));
132 }
133 
134 static inline ktime_t
135 ktime_add(ktime_t lhs, ktime_t rhs)
136 {
137 	return (lhs + rhs);
138 }
139 
140 static inline int
141 ktime_compare(const ktime_t cmp1, const ktime_t cmp2)
142 {
143 
144 	if (cmp1 > cmp2)
145 		return (1);
146 	else if (cmp1 < cmp2)
147 		return (-1);
148 	else
149 		return (0);
150 }
151 
152 static inline bool
153 ktime_after(const ktime_t cmp1, const ktime_t cmp2)
154 {
155 
156 	return (ktime_compare(cmp1, cmp2) > 0);
157 }
158 
159 static inline bool
160 ktime_before(const ktime_t cmp1, const ktime_t cmp2)
161 {
162 
163 	return (ktime_compare(cmp1, cmp2) < 0);
164 }
165 
166 static inline ktime_t
167 timespec_to_ktime(struct timespec ts)
168 {
169 	return (ktime_set(ts.tv_sec, ts.tv_nsec));
170 }
171 
172 static inline ktime_t
173 timeval_to_ktime(struct timeval tv)
174 {
175 	return (ktime_set(tv.tv_sec, tv.tv_usec * NSEC_PER_USEC));
176 }
177 
178 static inline int64_t
179 timespec64_to_ns(struct timespec64 *ts)
180 {
181 	return (timespec_to_ns(ts));
182 }
183 
184 #define	ktime_to_timespec(kt)		ns_to_timespec(kt)
185 #define	ktime_to_timespec64(kt)		ns_to_timespec(kt)
186 #define	ktime_to_timeval(kt)		ns_to_timeval(kt)
187 #define	ktime_to_ns(kt)			(kt)
188 #define	ktime_get_ts(ts)		getnanouptime(ts)
189 #define	ktime_get_ts64(ts)		getnanouptime(ts)
190 #define	ktime_get_raw_ts64(ts)		getnanouptime(ts)
191 #define	ktime_get_real_ts64(ts)		getnanotime(ts)
192 #define	getrawmonotonic64(ts)		getnanouptime(ts)
193 
194 static inline int64_t
195 ktime_get_ns(void)
196 {
197 	struct timespec ts;
198 
199 	ktime_get_ts(&ts);
200 
201 	return (ktime_to_ns(timespec_to_ktime(ts)));
202 }
203 
204 static inline ktime_t
205 ktime_get(void)
206 {
207 	struct timespec ts;
208 
209 	ktime_get_ts(&ts);
210 	return (timespec_to_ktime(ts));
211 }
212 
213 static inline ktime_t
214 ktime_get_boottime(void)
215 {
216 	struct timespec ts;
217 
218 	nanouptime(&ts);
219 	return (timespec_to_ktime(ts));
220 }
221 
222 static inline uint64_t
223 ktime_get_boottime_ns(void)
224 {
225 
226 	return (ktime_to_ns(ktime_get_boottime()));
227 }
228 
229 static inline ktime_t
230 ktime_get_real(void)
231 {
232 	struct timespec ts;
233 
234 	nanotime(&ts);
235 	return (timespec_to_ktime(ts));
236 }
237 
238 static inline ktime_t
239 ktime_get_real_seconds(void)
240 {
241 	struct timespec ts;
242 
243 	nanotime(&ts);
244 	return (ts.tv_sec);
245 }
246 
247 static inline ktime_t
248 ktime_get_raw(void)
249 {
250 	struct timespec ts;
251 
252 	nanouptime(&ts);
253 	return (timespec_to_ktime(ts));
254 }
255 
256 static inline u64
257 ktime_get_raw_ns(void)
258 {
259 	struct timespec ts;
260 
261 	nanouptime(&ts);
262 	return (ktime_to_ns(timespec_to_ktime(ts)));
263 }
264 
265 #endif /* _LINUXKPI_LINUX_KTIME_H */
266