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