xref: /dpdk/examples/timer/main.c (revision ddcd7640ca48a13ac211f356495ec894651b87b4)
13998e2a0SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause
23998e2a0SBruce Richardson  * Copyright(c) 2010-2014 Intel Corporation
3af75078fSIntel  */
4af75078fSIntel 
5af75078fSIntel #include <stdio.h>
6af75078fSIntel #include <string.h>
7af75078fSIntel #include <stdint.h>
8af75078fSIntel #include <errno.h>
9af75078fSIntel #include <sys/queue.h>
10af75078fSIntel 
11af75078fSIntel #include <rte_common.h>
12af75078fSIntel #include <rte_memory.h>
13af75078fSIntel #include <rte_launch.h>
14af75078fSIntel #include <rte_eal.h>
15af75078fSIntel #include <rte_per_lcore.h>
16af75078fSIntel #include <rte_lcore.h>
17af75078fSIntel #include <rte_cycles.h>
18af75078fSIntel #include <rte_timer.h>
19af75078fSIntel #include <rte_debug.h>
20af75078fSIntel 
21af75078fSIntel #define TIMER_RESOLUTION_CYCLES 20000000ULL /* around 10ms at 2 Ghz */
22af75078fSIntel 
23af75078fSIntel static struct rte_timer timer0;
24af75078fSIntel static struct rte_timer timer1;
25af75078fSIntel 
26af75078fSIntel /* timer0 callback */
27af75078fSIntel static void
28f2fc83b4SThomas Monjalon timer0_cb(__rte_unused struct rte_timer *tim,
29f2fc83b4SThomas Monjalon 	  __rte_unused void *arg)
30af75078fSIntel {
31af75078fSIntel 	static unsigned counter = 0;
32af75078fSIntel 	unsigned lcore_id = rte_lcore_id();
33af75078fSIntel 
34af75078fSIntel 	printf("%s() on lcore %u\n", __func__, lcore_id);
35af75078fSIntel 
36af75078fSIntel 	/* this timer is automatically reloaded until we decide to
37af75078fSIntel 	 * stop it, when counter reaches 20. */
38af75078fSIntel 	if ((counter ++) == 20)
39af75078fSIntel 		rte_timer_stop(tim);
40af75078fSIntel }
41af75078fSIntel 
42af75078fSIntel /* timer1 callback */
43af75078fSIntel static void
44f2fc83b4SThomas Monjalon timer1_cb(__rte_unused struct rte_timer *tim,
45f2fc83b4SThomas Monjalon 	  __rte_unused void *arg)
46af75078fSIntel {
47af75078fSIntel 	unsigned lcore_id = rte_lcore_id();
48af75078fSIntel 	uint64_t hz;
49af75078fSIntel 
50af75078fSIntel 	printf("%s() on lcore %u\n", __func__, lcore_id);
51af75078fSIntel 
52af75078fSIntel 	/* reload it on another lcore */
53e987449cSIntel 	hz = rte_get_timer_hz();
54af75078fSIntel 	lcore_id = rte_get_next_lcore(lcore_id, 0, 1);
55af75078fSIntel 	rte_timer_reset(tim, hz/3, SINGLE, lcore_id, timer1_cb, NULL);
56af75078fSIntel }
57af75078fSIntel 
58*ddcd7640SThomas Monjalon static __rte_noreturn int
59f2fc83b4SThomas Monjalon lcore_mainloop(__rte_unused void *arg)
60af75078fSIntel {
61af75078fSIntel 	uint64_t prev_tsc = 0, cur_tsc, diff_tsc;
62af75078fSIntel 	unsigned lcore_id;
63af75078fSIntel 
64af75078fSIntel 	lcore_id = rte_lcore_id();
65af75078fSIntel 	printf("Starting mainloop on core %u\n", lcore_id);
66af75078fSIntel 
67af75078fSIntel 	while (1) {
68af75078fSIntel 		/*
69af75078fSIntel 		 * Call the timer handler on each core: as we don't
70af75078fSIntel 		 * need a very precise timer, so only call
71af75078fSIntel 		 * rte_timer_manage() every ~10ms (at 2Ghz). In a real
72af75078fSIntel 		 * application, this will enhance performances as
73af75078fSIntel 		 * reading the HPET timer is not efficient.
74af75078fSIntel 		 */
75af75078fSIntel 		cur_tsc = rte_rdtsc();
76af75078fSIntel 		diff_tsc = cur_tsc - prev_tsc;
77af75078fSIntel 		if (diff_tsc > TIMER_RESOLUTION_CYCLES) {
78af75078fSIntel 			rte_timer_manage();
79af75078fSIntel 			prev_tsc = cur_tsc;
80af75078fSIntel 		}
81af75078fSIntel 	}
82af75078fSIntel }
83af75078fSIntel 
84af75078fSIntel int
8598a16481SDavid Marchand main(int argc, char **argv)
86af75078fSIntel {
87af75078fSIntel 	int ret;
88af75078fSIntel 	uint64_t hz;
89af75078fSIntel 	unsigned lcore_id;
90af75078fSIntel 
91af75078fSIntel 	/* init EAL */
92af75078fSIntel 	ret = rte_eal_init(argc, argv);
93af75078fSIntel 	if (ret < 0)
94af75078fSIntel 		rte_panic("Cannot init EAL\n");
95af75078fSIntel 
96af75078fSIntel 	/* init RTE timer library */
97af75078fSIntel 	rte_timer_subsystem_init();
98af75078fSIntel 
99af75078fSIntel 	/* init timer structures */
100af75078fSIntel 	rte_timer_init(&timer0);
101af75078fSIntel 	rte_timer_init(&timer1);
102af75078fSIntel 
103af75078fSIntel 	/* load timer0, every second, on master lcore, reloaded automatically */
104e987449cSIntel 	hz = rte_get_timer_hz();
105af75078fSIntel 	lcore_id = rte_lcore_id();
106af75078fSIntel 	rte_timer_reset(&timer0, hz, PERIODICAL, lcore_id, timer0_cb, NULL);
107af75078fSIntel 
108af75078fSIntel 	/* load timer1, every second/3, on next lcore, reloaded manually */
109af75078fSIntel 	lcore_id = rte_get_next_lcore(lcore_id, 0, 1);
110af75078fSIntel 	rte_timer_reset(&timer1, hz/3, SINGLE, lcore_id, timer1_cb, NULL);
111af75078fSIntel 
112af75078fSIntel 	/* call lcore_mainloop() on every slave lcore */
113af75078fSIntel 	RTE_LCORE_FOREACH_SLAVE(lcore_id) {
114af75078fSIntel 		rte_eal_remote_launch(lcore_mainloop, NULL, lcore_id);
115af75078fSIntel 	}
116af75078fSIntel 
117af75078fSIntel 	/* call it on master lcore too */
118af75078fSIntel 	(void) lcore_mainloop(NULL);
119af75078fSIntel 
120af75078fSIntel 	return 0;
121af75078fSIntel }
122