1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2015 Intel Corporation 3 */ 4 5 #ifndef _RTE_TIME_H_ 6 #define _RTE_TIME_H_ 7 8 #include <stdint.h> 9 #include <time.h> 10 11 #define NSEC_PER_SEC 1000000000L 12 13 /** 14 * Structure to hold the parameters of a running cycle counter to assist 15 * in converting cycles to nanoseconds. 16 */ 17 struct rte_timecounter { 18 /** Last cycle counter value read. */ 19 uint64_t cycle_last; 20 /** Nanoseconds count. */ 21 uint64_t nsec; 22 /** Bitmask separating nanosecond and sub-nanoseconds. */ 23 uint64_t nsec_mask; 24 /** Sub-nanoseconds count. */ 25 uint64_t nsec_frac; 26 /** Bitmask for two's complement subtraction of non-64 bit counters. */ 27 uint64_t cc_mask; 28 /** Cycle to nanosecond divisor (power of two). */ 29 uint32_t cc_shift; 30 }; 31 32 /** 33 * Converts cyclecounter cycles to nanoseconds. 34 */ 35 static inline uint64_t rte_cyclecounter_cycles_to_ns(struct rte_timecounter * tc,uint64_t cycles)36rte_cyclecounter_cycles_to_ns(struct rte_timecounter *tc, uint64_t cycles) 37 { 38 uint64_t ns; 39 40 /* Add fractional nanoseconds. */ 41 ns = cycles + tc->nsec_frac; 42 tc->nsec_frac = ns & tc->nsec_mask; 43 44 /* Shift to get only nanoseconds. */ 45 return ns >> tc->cc_shift; 46 } 47 48 /** 49 * Update the internal nanosecond count in the structure. 50 */ 51 static inline uint64_t rte_timecounter_update(struct rte_timecounter * tc,uint64_t cycle_now)52rte_timecounter_update(struct rte_timecounter *tc, uint64_t cycle_now) 53 { 54 uint64_t cycle_delta, ns_offset; 55 56 /* Calculate the delta since the last call. */ 57 if (tc->cycle_last <= cycle_now) 58 cycle_delta = (cycle_now - tc->cycle_last) & tc->cc_mask; 59 else 60 /* Handle cycle counts that have wrapped around . */ 61 cycle_delta = (~(tc->cycle_last - cycle_now) & tc->cc_mask) + 1; 62 63 /* Convert to nanoseconds. */ 64 ns_offset = rte_cyclecounter_cycles_to_ns(tc, cycle_delta); 65 66 /* Store current cycle counter for next call. */ 67 tc->cycle_last = cycle_now; 68 69 /* Update the nanosecond count. */ 70 tc->nsec += ns_offset; 71 72 return tc->nsec; 73 } 74 75 /** 76 * Convert from timespec structure into nanosecond units. 77 */ 78 static inline uint64_t rte_timespec_to_ns(const struct timespec * ts)79rte_timespec_to_ns(const struct timespec *ts) 80 { 81 return ((uint64_t) ts->tv_sec * NSEC_PER_SEC) + ts->tv_nsec; 82 } 83 84 /** 85 * Convert from nanosecond units into timespec structure. 86 */ 87 static inline struct timespec rte_ns_to_timespec(uint64_t nsec)88rte_ns_to_timespec(uint64_t nsec) 89 { 90 struct timespec ts = {0, 0}; 91 92 if (nsec == 0) 93 return ts; 94 95 ts.tv_sec = nsec / NSEC_PER_SEC; 96 ts.tv_nsec = nsec % NSEC_PER_SEC; 97 98 return ts; 99 } 100 101 #endif /* _RTE_TIME_H_ */ 102