ktime.h revision 282513
1/*- 2 * Copyright (c) 2014 Mellanox Technologies, Ltd. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice unmodified, this list of conditions, and the following 10 * disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27#ifndef _LINUX_KTIME_H 28#define _LINUX_KTIME_H 29 30#include <sys/time.h> 31#include <linux/types.h> 32#include <linux/jiffies.h> 33 34 35/* Get the monotonic time in timespec format: */ 36#define ktime_get_ts getnanouptime 37 38#define NSEC_PER_USEC 1000L 39#define NSEC_PER_SEC 1000000000L 40 41/* 42 * ktime_t: 43 * 44 * On 64-bit CPUs a single 64-bit variable is used to store the hrtimers 45 * internal representation of time values in scalar nanoseconds. The 46 * design plays out best on 64-bit CPUs, where most conversions are 47 * NOPs and most arithmetic ktime_t operations are plain arithmetic 48 * operations. 49 * 50 * On 32-bit CPUs an optimized representation of the timespec structure 51 * is used to avoid expensive conversions from and to timespecs. The 52 * endian-aware order of the tv struct members is chosen to allow 53 * mathematical operations on the tv64 member of the union too, which 54 * for certain operations produces better code. 55 * 56 * For architectures with efficient support for 64/32-bit conversions the 57 * plain scalar nanosecond based representation can be selected by the 58 * config switch CONFIG_KTIME_SCALAR. 59 */ 60union ktime { 61 s64 tv64; 62#if BITS_PER_LONG != 64 && !defined(CONFIG_KTIME_SCALAR) 63 struct { 64# ifdef __BIG_ENDIAN 65 s32 sec, nsec; 66# else 67 s32 nsec, sec; 68# endif 69 } tv; 70#endif 71}; 72 73typedef union ktime ktime_t; /* Kill this */ 74 75#define KTIME_MAX ((s64)~((u64)1 << 63)) 76#define KTIME_SEC_MAX (KTIME_MAX / NSEC_PER_SEC) 77 78/* 79 * ktime_t definitions when using the 64-bit scalar representation: 80 */ 81 82#if (BITS_PER_LONG == 64) || defined(CONFIG_KTIME_SCALAR) 83 84/** 85 * ktime_set - Set a ktime_t variable from a seconds/nanoseconds value 86 * @secs: seconds to set 87 * @nsecs: nanoseconds to set 88 * 89 * Return the ktime_t representation of the value 90 */ 91static inline ktime_t ktime_set(const long secs, const unsigned long nsecs) 92{ 93#if (BITS_PER_LONG == 64) 94 if (unlikely(secs >= KTIME_SEC_MAX)) 95 return (ktime_t){ .tv64 = KTIME_MAX }; 96#endif 97 return (ktime_t) { .tv64 = (s64)secs * NSEC_PER_SEC + (s64)nsecs }; 98} 99 100/* Subtract two ktime_t variables. rem = lhs -rhs: */ 101#define ktime_sub(lhs, rhs) \ 102 ({ (ktime_t){ .tv64 = (lhs).tv64 - (rhs).tv64 }; }) 103 104/* Add two ktime_t variables. res = lhs + rhs: */ 105#define ktime_add(lhs, rhs) \ 106 ({ (ktime_t){ .tv64 = (lhs).tv64 + (rhs).tv64 }; }) 107 108/* 109 * Add a ktime_t variable and a scalar nanosecond value. 110 * res = kt + nsval: 111 */ 112#define ktime_add_ns(kt, nsval) \ 113 ({ (ktime_t){ .tv64 = (kt).tv64 + (nsval) }; }) 114 115/* 116 * Subtract a scalar nanosecod from a ktime_t variable 117 * res = kt - nsval: 118 */ 119#define ktime_sub_ns(kt, nsval) \ 120 ({ (ktime_t){ .tv64 = (kt).tv64 - (nsval) }; }) 121 122/* convert a timespec to ktime_t format: */ 123static inline ktime_t timespec_to_ktime(struct timespec ts) 124{ 125 return ktime_set(ts.tv_sec, ts.tv_nsec); 126} 127 128/* convert a timeval to ktime_t format: */ 129static inline ktime_t timeval_to_ktime(struct timeval tv) 130{ 131 return ktime_set(tv.tv_sec, tv.tv_usec * NSEC_PER_USEC); 132} 133 134/* Map the ktime_t to timespec conversion to ns_to_timespec function */ 135#define ktime_to_timespec(kt) ns_to_timespec((kt).tv64) 136 137/* Map the ktime_t to timeval conversion to ns_to_timeval function */ 138#define ktime_to_timeval(kt) ns_to_timeval((kt).tv64) 139 140/* Convert ktime_t to nanoseconds - NOP in the scalar storage format: */ 141#define ktime_to_ns(kt) ((kt).tv64) 142 143#else /* !((BITS_PER_LONG == 64) || defined(CONFIG_KTIME_SCALAR)) */ 144 145/* 146 * Helper macros/inlines to get the ktime_t math right in the timespec 147 * representation. The macros are sometimes ugly - their actual use is 148 * pretty okay-ish, given the circumstances. We do all this for 149 * performance reasons. The pure scalar nsec_t based code was nice and 150 * simple, but created too many 64-bit / 32-bit conversions and divisions. 151 * 152 * Be especially aware that negative values are represented in a way 153 * that the tv.sec field is negative and the tv.nsec field is greater 154 * or equal to zero but less than nanoseconds per second. This is the 155 * same representation which is used by timespecs. 156 * 157 * tv.sec < 0 and 0 >= tv.nsec < NSEC_PER_SEC 158 */ 159 160/* Set a ktime_t variable to a value in sec/nsec representation: */ 161static inline ktime_t ktime_set(const long secs, const unsigned long nsecs) 162{ 163 return (ktime_t) { .tv = { .sec = secs, .nsec = nsecs } }; 164} 165 166/** 167 * ktime_sub - subtract two ktime_t variables 168 * @lhs: minuend 169 * @rhs: subtrahend 170 * 171 * Returns the remainder of the subtraction 172 */ 173static inline ktime_t ktime_sub(const ktime_t lhs, const ktime_t rhs) 174{ 175 ktime_t res; 176 177 res.tv64 = lhs.tv64 - rhs.tv64; 178 if (res.tv.nsec < 0) 179 res.tv.nsec += NSEC_PER_SEC; 180 181 return res; 182} 183 184/** 185 * ktime_add - add two ktime_t variables 186 * @add1: addend1 187 * @add2: addend2 188 * 189 * Returns the sum of @add1 and @add2. 190 */ 191static inline ktime_t ktime_add(const ktime_t add1, const ktime_t add2) 192{ 193 ktime_t res; 194 195 res.tv64 = add1.tv64 + add2.tv64; 196 /* 197 * performance trick: the (u32) -NSEC gives 0x00000000Fxxxxxxx 198 * so we subtract NSEC_PER_SEC and add 1 to the upper 32 bit. 199 * 200 * it's equivalent to: 201 * tv.nsec -= NSEC_PER_SEC 202 * tv.sec ++; 203 */ 204 if (res.tv.nsec >= NSEC_PER_SEC) 205 res.tv64 += (u32)-NSEC_PER_SEC; 206 207 return res; 208} 209 210/** 211 * ktime_add_ns - Add a scalar nanoseconds value to a ktime_t variable 212 * @kt: addend 213 * @nsec: the scalar nsec value to add 214 * 215 * Returns the sum of @kt and @nsec in ktime_t format 216 */ 217extern ktime_t ktime_add_ns(const ktime_t kt, u64 nsec); 218 219/** 220 * ktime_sub_ns - Subtract a scalar nanoseconds value from a ktime_t variable 221 * @kt: minuend 222 * @nsec: the scalar nsec value to subtract 223 * 224 * Returns the subtraction of @nsec from @kt in ktime_t format 225 */ 226extern ktime_t ktime_sub_ns(const ktime_t kt, u64 nsec); 227 228/** 229 * timespec_to_ktime - convert a timespec to ktime_t format 230 * @ts: the timespec variable to convert 231 * 232 * Returns a ktime_t variable with the converted timespec value 233 */ 234static inline ktime_t timespec_to_ktime(const struct timespec ts) 235{ 236 return (ktime_t) { .tv = { .sec = (s32)ts.tv_sec, 237 .nsec = (s32)ts.tv_nsec } }; 238} 239 240/** 241 * timeval_to_ktime - convert a timeval to ktime_t format 242 * @tv: the timeval variable to convert 243 * 244 * Returns a ktime_t variable with the converted timeval value 245 */ 246static inline ktime_t timeval_to_ktime(const struct timeval tv) 247{ 248 return (ktime_t) { .tv = { .sec = (s32)tv.tv_sec, 249 .nsec = (s32)(tv.tv_usec * 250 NSEC_PER_USEC) } }; 251} 252 253/** 254 * ktime_to_timespec - convert a ktime_t variable to timespec format 255 * @kt: the ktime_t variable to convert 256 * 257 * Returns the timespec representation of the ktime value 258 */ 259static inline struct timespec ktime_to_timespec(const ktime_t kt) 260{ 261 return (struct timespec) { .tv_sec = (time_t) kt.tv.sec, 262 .tv_nsec = (long) kt.tv.nsec }; 263} 264 265/** 266 * ktime_to_timeval - convert a ktime_t variable to timeval format 267 * @kt: the ktime_t variable to convert 268 * 269 * Returns the timeval representation of the ktime value 270 */ 271static inline struct timeval ktime_to_timeval(const ktime_t kt) 272{ 273 return (struct timeval) { 274 .tv_sec = (time_t) kt.tv.sec, 275 .tv_usec = (suseconds_t) (kt.tv.nsec / NSEC_PER_USEC) }; 276} 277 278/** 279 * ktime_to_ns - convert a ktime_t variable to scalar nanoseconds 280 * @kt: the ktime_t variable to convert 281 * 282 * Returns the scalar nanoseconds representation of @kt 283 */ 284static inline s64 ktime_to_ns(const ktime_t kt) 285{ 286 return (s64) kt.tv.sec * NSEC_PER_SEC + kt.tv.nsec; 287} 288 289#endif /* !((BITS_PER_LONG == 64) || defined(CONFIG_KTIME_SCALAR)) */ 290 291static inline s64 ktime_get_ns(void) 292{ 293 struct timespec ts; 294 ktime_t kt; 295 ktime_get_ts(&ts); 296 kt = timespec_to_ktime(ts); 297 return (ktime_to_ns(kt)); 298} 299 300#endif /* _LINUX_KTIME_H */ 301