1*d30ea906Sjfb8856606 /* SPDX-License-Identifier: BSD-3-Clause
2*d30ea906Sjfb8856606  * Copyright(c) 2015 Intel Corporation
3a9643ea8Slogwang  */
4a9643ea8Slogwang 
5a9643ea8Slogwang 
6a9643ea8Slogwang #ifndef LTHREAD_TIMER_H_
7a9643ea8Slogwang #define LTHREAD_TIMER_H_
8a9643ea8Slogwang 
92bfe3f2eSlogwang #ifdef __cplusplus
102bfe3f2eSlogwang extern "C" {
112bfe3f2eSlogwang #endif
122bfe3f2eSlogwang 
13a9643ea8Slogwang #include "lthread_int.h"
14a9643ea8Slogwang #include "lthread_sched.h"
15a9643ea8Slogwang 
16a9643ea8Slogwang 
17a9643ea8Slogwang static inline uint64_t
_ns_to_clks(uint64_t ns)18a9643ea8Slogwang _ns_to_clks(uint64_t ns)
19a9643ea8Slogwang {
202bfe3f2eSlogwang 	/*
212bfe3f2eSlogwang 	 * clkns needs to be divided by 1E9 to get ns clocks. However,
222bfe3f2eSlogwang 	 * dividing by this first would lose a lot of accuracy.
232bfe3f2eSlogwang 	 * Dividing after a multiply by ns, could cause overflow of
242bfe3f2eSlogwang 	 * uint64_t if ns is about 5 seconds [if we assume a max tsc
252bfe3f2eSlogwang 	 * rate of 4GHz]. Therefore we first divide by 1E4, then
262bfe3f2eSlogwang 	 * multiply and finally divide by 1E5. This allows ns to be
272bfe3f2eSlogwang 	 * values many hours long, without overflow, while still keeping
282bfe3f2eSlogwang 	 * reasonable accuracy.
292bfe3f2eSlogwang 	 */
302bfe3f2eSlogwang 	uint64_t clkns = rte_get_tsc_hz() / 1e4;
31a9643ea8Slogwang 
32a9643ea8Slogwang 	clkns *= ns;
332bfe3f2eSlogwang 	clkns /= 1e5;
342bfe3f2eSlogwang 
352bfe3f2eSlogwang 	return clkns;
36a9643ea8Slogwang }
37a9643ea8Slogwang 
38a9643ea8Slogwang 
39a9643ea8Slogwang static inline void
_timer_start(struct lthread * lt,uint64_t clks)40a9643ea8Slogwang _timer_start(struct lthread *lt, uint64_t clks)
41a9643ea8Slogwang {
42a9643ea8Slogwang 	if (clks > 0) {
43a9643ea8Slogwang 		DIAG_EVENT(lt, LT_DIAG_LTHREAD_TMR_START, &lt->tim, clks);
44a9643ea8Slogwang 		rte_timer_init(&lt->tim);
45a9643ea8Slogwang 		rte_timer_reset(&lt->tim,
46a9643ea8Slogwang 				clks,
47a9643ea8Slogwang 				SINGLE,
48a9643ea8Slogwang 				rte_lcore_id(),
49a9643ea8Slogwang 				_sched_timer_cb,
50a9643ea8Slogwang 				(void *)lt);
51a9643ea8Slogwang 	}
52a9643ea8Slogwang }
53a9643ea8Slogwang 
54a9643ea8Slogwang 
55a9643ea8Slogwang static inline void
_timer_stop(struct lthread * lt)56a9643ea8Slogwang _timer_stop(struct lthread *lt)
57a9643ea8Slogwang {
58a9643ea8Slogwang 	if (lt != NULL) {
59a9643ea8Slogwang 		DIAG_EVENT(lt, LT_DIAG_LTHREAD_TMR_DELETE, &lt->tim, 0);
60a9643ea8Slogwang 		rte_timer_stop(&lt->tim);
61a9643ea8Slogwang 	}
62a9643ea8Slogwang }
63a9643ea8Slogwang 
642bfe3f2eSlogwang #ifdef __cplusplus
652bfe3f2eSlogwang }
662bfe3f2eSlogwang #endif
67a9643ea8Slogwang 
68a9643ea8Slogwang #endif /* LTHREAD_TIMER_H_ */
69