199a2dd95SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause 299a2dd95SBruce Richardson * Copyright(c) 2015 Intel Corporation 399a2dd95SBruce Richardson */ 499a2dd95SBruce Richardson 599a2dd95SBruce Richardson #ifndef _RTE_TIME_H_ 699a2dd95SBruce Richardson #define _RTE_TIME_H_ 799a2dd95SBruce Richardson 8*719834a6SMattias Rönnblom #include <stdint.h> 9*719834a6SMattias Rönnblom #include <time.h> 10*719834a6SMattias Rönnblom 11d7e9c02cSBrian Dooley #ifdef __cplusplus 12d7e9c02cSBrian Dooley extern "C" { 13d7e9c02cSBrian Dooley #endif 14d7e9c02cSBrian Dooley 1599a2dd95SBruce Richardson #define NSEC_PER_SEC 1000000000L 1699a2dd95SBruce Richardson 1799a2dd95SBruce Richardson /** 1899a2dd95SBruce Richardson * Structure to hold the parameters of a running cycle counter to assist 1999a2dd95SBruce Richardson * in converting cycles to nanoseconds. 2099a2dd95SBruce Richardson */ 2199a2dd95SBruce Richardson struct rte_timecounter { 2299a2dd95SBruce Richardson /** Last cycle counter value read. */ 2399a2dd95SBruce Richardson uint64_t cycle_last; 2499a2dd95SBruce Richardson /** Nanoseconds count. */ 2599a2dd95SBruce Richardson uint64_t nsec; 2699a2dd95SBruce Richardson /** Bitmask separating nanosecond and sub-nanoseconds. */ 2799a2dd95SBruce Richardson uint64_t nsec_mask; 2899a2dd95SBruce Richardson /** Sub-nanoseconds count. */ 2999a2dd95SBruce Richardson uint64_t nsec_frac; 3099a2dd95SBruce Richardson /** Bitmask for two's complement subtraction of non-64 bit counters. */ 3199a2dd95SBruce Richardson uint64_t cc_mask; 3299a2dd95SBruce Richardson /** Cycle to nanosecond divisor (power of two). */ 3399a2dd95SBruce Richardson uint32_t cc_shift; 3499a2dd95SBruce Richardson }; 3599a2dd95SBruce Richardson 3699a2dd95SBruce Richardson /** 3799a2dd95SBruce Richardson * Converts cyclecounter cycles to nanoseconds. 3899a2dd95SBruce Richardson */ 3999a2dd95SBruce Richardson static inline uint64_t 4099a2dd95SBruce Richardson rte_cyclecounter_cycles_to_ns(struct rte_timecounter *tc, uint64_t cycles) 4199a2dd95SBruce Richardson { 4299a2dd95SBruce Richardson uint64_t ns; 4399a2dd95SBruce Richardson 4499a2dd95SBruce Richardson /* Add fractional nanoseconds. */ 4599a2dd95SBruce Richardson ns = cycles + tc->nsec_frac; 4699a2dd95SBruce Richardson tc->nsec_frac = ns & tc->nsec_mask; 4799a2dd95SBruce Richardson 4899a2dd95SBruce Richardson /* Shift to get only nanoseconds. */ 4999a2dd95SBruce Richardson return ns >> tc->cc_shift; 5099a2dd95SBruce Richardson } 5199a2dd95SBruce Richardson 5299a2dd95SBruce Richardson /** 5399a2dd95SBruce Richardson * Update the internal nanosecond count in the structure. 5499a2dd95SBruce Richardson */ 5599a2dd95SBruce Richardson static inline uint64_t 5699a2dd95SBruce Richardson rte_timecounter_update(struct rte_timecounter *tc, uint64_t cycle_now) 5799a2dd95SBruce Richardson { 5899a2dd95SBruce Richardson uint64_t cycle_delta, ns_offset; 5999a2dd95SBruce Richardson 6099a2dd95SBruce Richardson /* Calculate the delta since the last call. */ 6199a2dd95SBruce Richardson if (tc->cycle_last <= cycle_now) 6299a2dd95SBruce Richardson cycle_delta = (cycle_now - tc->cycle_last) & tc->cc_mask; 6399a2dd95SBruce Richardson else 6499a2dd95SBruce Richardson /* Handle cycle counts that have wrapped around . */ 6599a2dd95SBruce Richardson cycle_delta = (~(tc->cycle_last - cycle_now) & tc->cc_mask) + 1; 6699a2dd95SBruce Richardson 6799a2dd95SBruce Richardson /* Convert to nanoseconds. */ 6899a2dd95SBruce Richardson ns_offset = rte_cyclecounter_cycles_to_ns(tc, cycle_delta); 6999a2dd95SBruce Richardson 7099a2dd95SBruce Richardson /* Store current cycle counter for next call. */ 7199a2dd95SBruce Richardson tc->cycle_last = cycle_now; 7299a2dd95SBruce Richardson 7399a2dd95SBruce Richardson /* Update the nanosecond count. */ 7499a2dd95SBruce Richardson tc->nsec += ns_offset; 7599a2dd95SBruce Richardson 7699a2dd95SBruce Richardson return tc->nsec; 7799a2dd95SBruce Richardson } 7899a2dd95SBruce Richardson 7999a2dd95SBruce Richardson /** 8099a2dd95SBruce Richardson * Convert from timespec structure into nanosecond units. 8199a2dd95SBruce Richardson */ 8299a2dd95SBruce Richardson static inline uint64_t 8399a2dd95SBruce Richardson rte_timespec_to_ns(const struct timespec *ts) 8499a2dd95SBruce Richardson { 8599a2dd95SBruce Richardson return ((uint64_t) ts->tv_sec * NSEC_PER_SEC) + ts->tv_nsec; 8699a2dd95SBruce Richardson } 8799a2dd95SBruce Richardson 8899a2dd95SBruce Richardson /** 8999a2dd95SBruce Richardson * Convert from nanosecond units into timespec structure. 9099a2dd95SBruce Richardson */ 9199a2dd95SBruce Richardson static inline struct timespec 9299a2dd95SBruce Richardson rte_ns_to_timespec(uint64_t nsec) 9399a2dd95SBruce Richardson { 9499a2dd95SBruce Richardson struct timespec ts = {0, 0}; 9599a2dd95SBruce Richardson 9699a2dd95SBruce Richardson if (nsec == 0) 9799a2dd95SBruce Richardson return ts; 9899a2dd95SBruce Richardson 9999a2dd95SBruce Richardson ts.tv_sec = nsec / NSEC_PER_SEC; 10099a2dd95SBruce Richardson ts.tv_nsec = nsec % NSEC_PER_SEC; 10199a2dd95SBruce Richardson 10299a2dd95SBruce Richardson return ts; 10399a2dd95SBruce Richardson } 10499a2dd95SBruce Richardson 105d7e9c02cSBrian Dooley #ifdef __cplusplus 106d7e9c02cSBrian Dooley } 107d7e9c02cSBrian Dooley #endif 108d7e9c02cSBrian Dooley 10999a2dd95SBruce Richardson #endif /* _RTE_TIME_H_ */ 110