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