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