xref: /dpdk/lib/eal/include/rte_time.h (revision 719834a6849e1daf4a70ff7742bbcc3ae7e25607)
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