1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2015 Intel Corporation
3  */
4 
5 
6 #ifndef LTHREAD_TIMER_H_
7 #define LTHREAD_TIMER_H_
8 
9 #ifdef __cplusplus
10 extern "C" {
11 #endif
12 
13 #include "lthread_int.h"
14 #include "lthread_sched.h"
15 
16 
17 static inline uint64_t
_ns_to_clks(uint64_t ns)18 _ns_to_clks(uint64_t ns)
19 {
20 	/*
21 	 * clkns needs to be divided by 1E9 to get ns clocks. However,
22 	 * dividing by this first would lose a lot of accuracy.
23 	 * Dividing after a multiply by ns, could cause overflow of
24 	 * uint64_t if ns is about 5 seconds [if we assume a max tsc
25 	 * rate of 4GHz]. Therefore we first divide by 1E4, then
26 	 * multiply and finally divide by 1E5. This allows ns to be
27 	 * values many hours long, without overflow, while still keeping
28 	 * reasonable accuracy.
29 	 */
30 	uint64_t clkns = rte_get_tsc_hz() / 1e4;
31 
32 	clkns *= ns;
33 	clkns /= 1e5;
34 
35 	return clkns;
36 }
37 
38 
39 static inline void
_timer_start(struct lthread * lt,uint64_t clks)40 _timer_start(struct lthread *lt, uint64_t clks)
41 {
42 	if (clks > 0) {
43 		DIAG_EVENT(lt, LT_DIAG_LTHREAD_TMR_START, &lt->tim, clks);
44 		rte_timer_init(&lt->tim);
45 		rte_timer_reset(&lt->tim,
46 				clks,
47 				SINGLE,
48 				rte_lcore_id(),
49 				_sched_timer_cb,
50 				(void *)lt);
51 	}
52 }
53 
54 
55 static inline void
_timer_stop(struct lthread * lt)56 _timer_stop(struct lthread *lt)
57 {
58 	if (lt != NULL) {
59 		DIAG_EVENT(lt, LT_DIAG_LTHREAD_TMR_DELETE, &lt->tim, 0);
60 		rte_timer_stop(&lt->tim);
61 	}
62 }
63 
64 #ifdef __cplusplus
65 }
66 #endif
67 
68 #endif /* LTHREAD_TIMER_H_ */
69