ktime.h revision 277396
1258579Sneel/*-
2258579Sneel * Copyright (c) 2014 Mellanox Technologies, Ltd.
3258579Sneel * All rights reserved.
4258579Sneel *
5258579Sneel * Redistribution and use in source and binary forms, with or without
6258579Sneel * modification, are permitted provided that the following conditions
7258579Sneel * are met:
8258579Sneel * 1. Redistributions of source code must retain the above copyright
9258579Sneel *    notice unmodified, this list of conditions, and the following
10258579Sneel *    disclaimer.
11258579Sneel * 2. Redistributions in binary form must reproduce the above copyright
12258579Sneel *    notice, this list of conditions and the following disclaimer in the
13258579Sneel *    documentation and/or other materials provided with the distribution.
14258579Sneel *
15258579Sneel * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16258579Sneel * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17258579Sneel * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18258579Sneel * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19258579Sneel * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20258579Sneel * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21258579Sneel * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22258579Sneel * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23258579Sneel * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24258579Sneel * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25258579Sneel */
26258579Sneel
27258579Sneel#ifndef _LINUX_KTIME_H
28258579Sneel#define _LINUX_KTIME_H
29258579Sneel
30258579Sneel#include <sys/time.h>
31258579Sneel#include <linux/types.h>
32258579Sneel#include <linux/jiffies.h>
33258579Sneel
34258579Sneel
35258579Sneel/* Get the monotonic time in timespec format: */
36258579Sneel#define ktime_get_ts getnanouptime
37258579Sneel
38258579Sneel#define NSEC_PER_USEC   1000L
39258579Sneel#define NSEC_PER_SEC    1000000000L
40258579Sneel
41258579Sneel/*
42258579Sneel * ktime_t:
43258579Sneel *
44258579Sneel * On 64-bit CPUs a single 64-bit variable is used to store the hrtimers
45258579Sneel * internal representation of time values in scalar nanoseconds. The
46258579Sneel * design plays out best on 64-bit CPUs, where most conversions are
47258579Sneel * NOPs and most arithmetic ktime_t operations are plain arithmetic
48258579Sneel * operations.
49258579Sneel *
50258579Sneel * On 32-bit CPUs an optimized representation of the timespec structure
51258579Sneel * is used to avoid expensive conversions from and to timespecs. The
52258579Sneel * endian-aware order of the tv struct members is chosen to allow
53258579Sneel * mathematical operations on the tv64 member of the union too, which
54258579Sneel * for certain operations produces better code.
55258579Sneel *
56258579Sneel * For architectures with efficient support for 64/32-bit conversions the
57258579Sneel * plain scalar nanosecond based representation can be selected by the
58258579Sneel * config switch CONFIG_KTIME_SCALAR.
59258579Sneel */
60258579Sneelunion ktime {
61258579Sneel	s64	tv64;
62258579Sneel#if BITS_PER_LONG != 64 && !defined(CONFIG_KTIME_SCALAR)
63258579Sneel	struct {
64258579Sneel# ifdef __BIG_ENDIAN
65258579Sneel	s32	sec, nsec;
66258579Sneel# else
67258579Sneel	s32	nsec, sec;
68258579Sneel# endif
69258579Sneel	} tv;
70258579Sneel#endif
71258579Sneel};
72258579Sneel
73258579Sneeltypedef union ktime ktime_t;		/* Kill this */
74258579Sneel
75258579Sneel#define KTIME_MAX                       ((s64)~((u64)1 << 63))
76258579Sneel#define KTIME_SEC_MAX                   (KTIME_MAX / NSEC_PER_SEC)
77258579Sneel
78258579Sneel/*
79258579Sneel * ktime_t definitions when using the 64-bit scalar representation:
80258579Sneel */
81258579Sneel
82258579Sneel#if (BITS_PER_LONG == 64) || defined(CONFIG_KTIME_SCALAR)
83258579Sneel
84258579Sneel/**
85258579Sneel * ktime_set - Set a ktime_t variable from a seconds/nanoseconds value
86258579Sneel * @secs:	seconds to set
87258579Sneel * @nsecs:	nanoseconds to set
88258579Sneel *
89258579Sneel * Return the ktime_t representation of the value
90258579Sneel */
91258579Sneelstatic inline ktime_t ktime_set(const long secs, const unsigned long nsecs)
92258579Sneel{
93258579Sneel#if (BITS_PER_LONG == 64)
94258579Sneel	if (unlikely(secs >= KTIME_SEC_MAX))
95258579Sneel		return (ktime_t){ .tv64 = KTIME_MAX };
96258579Sneel#endif
97258579Sneel	return (ktime_t) { .tv64 = (s64)secs * NSEC_PER_SEC + (s64)nsecs };
98258579Sneel}
99258579Sneel
100258579Sneel/* Subtract two ktime_t variables. rem = lhs -rhs: */
101258579Sneel#define ktime_sub(lhs, rhs) \
102258579Sneel		({ (ktime_t){ .tv64 = (lhs).tv64 - (rhs).tv64 }; })
103258579Sneel
104258579Sneel/* Add two ktime_t variables. res = lhs + rhs: */
105258579Sneel#define ktime_add(lhs, rhs) \
106258579Sneel		({ (ktime_t){ .tv64 = (lhs).tv64 + (rhs).tv64 }; })
107258579Sneel
108258579Sneel/*
109258579Sneel * Add a ktime_t variable and a scalar nanosecond value.
110258579Sneel * res = kt + nsval:
111258579Sneel */
112258579Sneel#define ktime_add_ns(kt, nsval) \
113258579Sneel		({ (ktime_t){ .tv64 = (kt).tv64 + (nsval) }; })
114258579Sneel
115258579Sneel/*
116258579Sneel * Subtract a scalar nanosecod from a ktime_t variable
117258579Sneel * res = kt - nsval:
118258579Sneel */
119258579Sneel#define ktime_sub_ns(kt, nsval) \
120258579Sneel		({ (ktime_t){ .tv64 = (kt).tv64 - (nsval) }; })
121258579Sneel
122258579Sneel/* convert a timespec to ktime_t format: */
123258579Sneelstatic inline ktime_t timespec_to_ktime(struct timespec ts)
124258579Sneel{
125258579Sneel	return ktime_set(ts.tv_sec, ts.tv_nsec);
126258579Sneel}
127258579Sneel
128258579Sneel/* convert a timeval to ktime_t format: */
129258579Sneelstatic inline ktime_t timeval_to_ktime(struct timeval tv)
130258579Sneel{
131258579Sneel	return ktime_set(tv.tv_sec, tv.tv_usec * NSEC_PER_USEC);
132258579Sneel}
133258579Sneel
134258579Sneel/* Map the ktime_t to timespec conversion to ns_to_timespec function */
135258579Sneel#define ktime_to_timespec(kt)		ns_to_timespec((kt).tv64)
136258579Sneel
137258579Sneel/* Map the ktime_t to timeval conversion to ns_to_timeval function */
138258579Sneel#define ktime_to_timeval(kt)		ns_to_timeval((kt).tv64)
139258579Sneel
140258579Sneel/* Convert ktime_t to nanoseconds - NOP in the scalar storage format: */
141258579Sneel#define ktime_to_ns(kt)			((kt).tv64)
142258579Sneel
143258579Sneel#else	/* !((BITS_PER_LONG == 64) || defined(CONFIG_KTIME_SCALAR)) */
144258579Sneel
145258579Sneel/*
146258579Sneel * Helper macros/inlines to get the ktime_t math right in the timespec
147258579Sneel * representation. The macros are sometimes ugly - their actual use is
148258579Sneel * pretty okay-ish, given the circumstances. We do all this for
149258579Sneel * performance reasons. The pure scalar nsec_t based code was nice and
150258579Sneel * simple, but created too many 64-bit / 32-bit conversions and divisions.
151258579Sneel *
152258579Sneel * Be especially aware that negative values are represented in a way
153258579Sneel * that the tv.sec field is negative and the tv.nsec field is greater
154258579Sneel * or equal to zero but less than nanoseconds per second. This is the
155258579Sneel * same representation which is used by timespecs.
156258579Sneel *
157258579Sneel *   tv.sec < 0 and 0 >= tv.nsec < NSEC_PER_SEC
158258579Sneel */
159258579Sneel
160258579Sneel/* Set a ktime_t variable to a value in sec/nsec representation: */
161258579Sneelstatic inline ktime_t ktime_set(const long secs, const unsigned long nsecs)
162258579Sneel{
163258579Sneel	return (ktime_t) { .tv = { .sec = secs, .nsec = nsecs } };
164258579Sneel}
165258579Sneel
166258579Sneel/**
167258579Sneel * ktime_sub - subtract two ktime_t variables
168258579Sneel * @lhs:	minuend
169258579Sneel * @rhs:	subtrahend
170258579Sneel *
171258579Sneel * Returns the remainder of the subtraction
172258579Sneel */
173258579Sneelstatic inline ktime_t ktime_sub(const ktime_t lhs, const ktime_t rhs)
174258579Sneel{
175258579Sneel	ktime_t res;
176258579Sneel
177258579Sneel	res.tv64 = lhs.tv64 - rhs.tv64;
178258579Sneel	if (res.tv.nsec < 0)
179258579Sneel		res.tv.nsec += NSEC_PER_SEC;
180258579Sneel
181258579Sneel	return res;
182258579Sneel}
183258579Sneel
184258579Sneel/**
185258579Sneel * ktime_add - add two ktime_t variables
186258579Sneel * @add1:	addend1
187258579Sneel * @add2:	addend2
188258579Sneel *
189258579Sneel * Returns the sum of @add1 and @add2.
190258579Sneel */
191258579Sneelstatic inline ktime_t ktime_add(const ktime_t add1, const ktime_t add2)
192258579Sneel{
193258579Sneel	ktime_t res;
194258579Sneel
195258579Sneel	res.tv64 = add1.tv64 + add2.tv64;
196258579Sneel	/*
197258579Sneel	 * performance trick: the (u32) -NSEC gives 0x00000000Fxxxxxxx
198258579Sneel	 * so we subtract NSEC_PER_SEC and add 1 to the upper 32 bit.
199258579Sneel	 *
200258579Sneel	 * it's equivalent to:
201258579Sneel	 *   tv.nsec -= NSEC_PER_SEC
202258579Sneel	 *   tv.sec ++;
203258579Sneel	 */
204258579Sneel	if (res.tv.nsec >= NSEC_PER_SEC)
205258579Sneel		res.tv64 += (u32)-NSEC_PER_SEC;
206258579Sneel
207258579Sneel	return res;
208258579Sneel}
209258579Sneel
210258579Sneel/**
211258579Sneel * ktime_add_ns - Add a scalar nanoseconds value to a ktime_t variable
212258579Sneel * @kt:		addend
213258579Sneel * @nsec:	the scalar nsec value to add
214258579Sneel *
215258579Sneel * Returns the sum of @kt and @nsec in ktime_t format
216258579Sneel */
217258579Sneelextern ktime_t ktime_add_ns(const ktime_t kt, u64 nsec);
218258579Sneel
219258579Sneel/**
220258579Sneel * ktime_sub_ns - Subtract a scalar nanoseconds value from a ktime_t variable
221258579Sneel * @kt:		minuend
222258579Sneel * @nsec:	the scalar nsec value to subtract
223258579Sneel *
224258579Sneel * Returns the subtraction of @nsec from @kt in ktime_t format
225258579Sneel */
226258579Sneelextern ktime_t ktime_sub_ns(const ktime_t kt, u64 nsec);
227258579Sneel
228258579Sneel/**
229258579Sneel * timespec_to_ktime - convert a timespec to ktime_t format
230258579Sneel * @ts:		the timespec variable to convert
231258579Sneel *
232258579Sneel * Returns a ktime_t variable with the converted timespec value
233258579Sneel */
234258579Sneelstatic inline ktime_t timespec_to_ktime(const struct timespec ts)
235258579Sneel{
236258579Sneel	return (ktime_t) { .tv = { .sec = (s32)ts.tv_sec,
237258579Sneel			   	   .nsec = (s32)ts.tv_nsec } };
238258579Sneel}
239258579Sneel
240258579Sneel/**
241258579Sneel * timeval_to_ktime - convert a timeval to ktime_t format
242258579Sneel * @tv:		the timeval variable to convert
243258579Sneel *
244258579Sneel * Returns a ktime_t variable with the converted timeval value
245258579Sneel */
246258579Sneelstatic inline ktime_t timeval_to_ktime(const struct timeval tv)
247258579Sneel{
248258579Sneel	return (ktime_t) { .tv = { .sec = (s32)tv.tv_sec,
249258579Sneel				   .nsec = (s32)(tv.tv_usec *
250258579Sneel						 NSEC_PER_USEC) } };
251258579Sneel}
252258579Sneel
253258579Sneel/**
254258579Sneel * ktime_to_timespec - convert a ktime_t variable to timespec format
255258579Sneel * @kt:		the ktime_t variable to convert
256258579Sneel *
257258579Sneel * Returns the timespec representation of the ktime value
258258579Sneel */
259258579Sneelstatic inline struct timespec ktime_to_timespec(const ktime_t kt)
260258579Sneel{
261258579Sneel	return (struct timespec) { .tv_sec = (time_t) kt.tv.sec,
262258579Sneel				   .tv_nsec = (long) kt.tv.nsec };
263258579Sneel}
264258579Sneel
265258579Sneel/**
266258579Sneel * ktime_to_timeval - convert a ktime_t variable to timeval format
267258579Sneel * @kt:		the ktime_t variable to convert
268258579Sneel *
269258579Sneel * Returns the timeval representation of the ktime value
270258579Sneel */
271258579Sneelstatic inline struct timeval ktime_to_timeval(const ktime_t kt)
272258579Sneel{
273258579Sneel	return (struct timeval) {
274258579Sneel		.tv_sec = (time_t) kt.tv.sec,
275258579Sneel		.tv_usec = (suseconds_t) (kt.tv.nsec / NSEC_PER_USEC) };
276258579Sneel}
277258579Sneel
278258579Sneel/**
279258579Sneel * ktime_to_ns - convert a ktime_t variable to scalar nanoseconds
280258579Sneel * @kt:		the ktime_t variable to convert
281258579Sneel *
282258579Sneel * Returns the scalar nanoseconds representation of @kt
283258579Sneel */
284258579Sneelstatic inline s64 ktime_to_ns(const ktime_t kt)
285258579Sneel{
286258579Sneel	return (s64) kt.tv.sec * NSEC_PER_SEC + kt.tv.nsec;
287258579Sneel}
288258579Sneel
289258579Sneel#endif	/* !((BITS_PER_LONG == 64) || defined(CONFIG_KTIME_SCALAR)) */
290258579Sneel
291258579Sneelstatic inline s64 ktime_get_ns(void)
292258579Sneel{
293258579Sneel	struct timespec ts;
294258579Sneel	ktime_t kt;
295258579Sneel	ktime_get_ts(&ts);
296258579Sneel	kt = timespec_to_ktime(ts);
297258579Sneel	return (ktime_to_ns(kt));
298258579Sneel}
299258579Sneel
300258579Sneel#endif	/* _LINUX_KTIME_H */
301258579Sneel