xref: /dpdk/examples/timer/main.c (revision 9a212dc06c7aaf09b146d9c3dcfd584d741634c1)
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 
2180aa15c4SChengchang Tang static uint64_t timer_resolution_cycles;
22af75078fSIntel static struct rte_timer timer0;
23af75078fSIntel static struct rte_timer timer1;
24af75078fSIntel 
25*9a212dc0SConor Fogarty /* timer0 callback. 8< */
26af75078fSIntel static void
timer0_cb(__rte_unused struct rte_timer * tim,__rte_unused void * arg)27f2fc83b4SThomas Monjalon timer0_cb(__rte_unused struct rte_timer *tim,
28f2fc83b4SThomas Monjalon 	  __rte_unused void *arg)
29af75078fSIntel {
30af75078fSIntel 	static unsigned counter = 0;
31af75078fSIntel 	unsigned lcore_id = rte_lcore_id();
32af75078fSIntel 
33af75078fSIntel 	printf("%s() on lcore %u\n", __func__, lcore_id);
34af75078fSIntel 
35af75078fSIntel 	/* this timer is automatically reloaded until we decide to
36af75078fSIntel 	 * stop it, when counter reaches 20. */
37af75078fSIntel 	if ((counter ++) == 20)
38af75078fSIntel 		rte_timer_stop(tim);
39af75078fSIntel }
40*9a212dc0SConor Fogarty /* >8 End of timer0 callback. */
41af75078fSIntel 
42*9a212dc0SConor Fogarty /* timer1 callback. 8< */
43af75078fSIntel static void
timer1_cb(__rte_unused struct rte_timer * tim,__rte_unused void * arg)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 }
57*9a212dc0SConor Fogarty /* >8 End of timer1 callback. */
58af75078fSIntel 
59ddcd7640SThomas Monjalon static __rte_noreturn int
lcore_mainloop(__rte_unused void * arg)60f2fc83b4SThomas Monjalon lcore_mainloop(__rte_unused void *arg)
61af75078fSIntel {
62af75078fSIntel 	uint64_t prev_tsc = 0, cur_tsc, diff_tsc;
63af75078fSIntel 	unsigned lcore_id;
64af75078fSIntel 
65af75078fSIntel 	lcore_id = rte_lcore_id();
66af75078fSIntel 	printf("Starting mainloop on core %u\n", lcore_id);
67af75078fSIntel 
68*9a212dc0SConor Fogarty 	/* Main loop. 8< */
69af75078fSIntel 	while (1) {
70af75078fSIntel 		/*
7180aa15c4SChengchang Tang 		 * Call the timer handler on each core: as we don't need a
7280aa15c4SChengchang Tang 		 * very precise timer, so only call rte_timer_manage()
7380aa15c4SChengchang Tang 		 * every ~10ms. In a real application, this will enhance
7480aa15c4SChengchang Tang 		 * performances as reading the HPET timer is not efficient.
75af75078fSIntel 		 */
7680aa15c4SChengchang Tang 		cur_tsc = rte_get_timer_cycles();
77af75078fSIntel 		diff_tsc = cur_tsc - prev_tsc;
7880aa15c4SChengchang Tang 		if (diff_tsc > timer_resolution_cycles) {
79af75078fSIntel 			rte_timer_manage();
80af75078fSIntel 			prev_tsc = cur_tsc;
81af75078fSIntel 		}
82af75078fSIntel 	}
83*9a212dc0SConor Fogarty 	/* >8 End of main loop. */
84af75078fSIntel }
85af75078fSIntel 
86af75078fSIntel int
main(int argc,char ** argv)8798a16481SDavid Marchand main(int argc, char **argv)
88af75078fSIntel {
89af75078fSIntel 	int ret;
90af75078fSIntel 	uint64_t hz;
91af75078fSIntel 	unsigned lcore_id;
92af75078fSIntel 
93*9a212dc0SConor Fogarty 	/* Init EAL. 8< */
94af75078fSIntel 	ret = rte_eal_init(argc, argv);
95af75078fSIntel 	if (ret < 0)
96af75078fSIntel 		rte_panic("Cannot init EAL\n");
97af75078fSIntel 
98af75078fSIntel 	/* init RTE timer library */
99af75078fSIntel 	rte_timer_subsystem_init();
100*9a212dc0SConor Fogarty 	/* >8 End of init EAL. */
101af75078fSIntel 
102*9a212dc0SConor Fogarty 	/* Init timer structures. 8< */
103af75078fSIntel 	rte_timer_init(&timer0);
104af75078fSIntel 	rte_timer_init(&timer1);
105*9a212dc0SConor Fogarty 	/* >8 End of init timer structures. */
106af75078fSIntel 
107*9a212dc0SConor Fogarty 	/* Load timer0, every second, on main lcore, reloaded automatically. 8< */
108e987449cSIntel 	hz = rte_get_timer_hz();
10980aa15c4SChengchang Tang 	timer_resolution_cycles = hz * 10 / 1000; /* around 10ms */
11080aa15c4SChengchang Tang 
111af75078fSIntel 	lcore_id = rte_lcore_id();
112af75078fSIntel 	rte_timer_reset(&timer0, hz, PERIODICAL, lcore_id, timer0_cb, NULL);
113af75078fSIntel 
114af75078fSIntel 	/* load timer1, every second/3, on next lcore, reloaded manually */
115af75078fSIntel 	lcore_id = rte_get_next_lcore(lcore_id, 0, 1);
116af75078fSIntel 	rte_timer_reset(&timer1, hz/3, SINGLE, lcore_id, timer1_cb, NULL);
117af75078fSIntel 
118*9a212dc0SConor Fogarty 	/* >8 End of two timers configured. */
119*9a212dc0SConor Fogarty 
120*9a212dc0SConor Fogarty 	/* Call lcore_mainloop() on every worker lcore. 8< */
121cb056611SStephen Hemminger 	RTE_LCORE_FOREACH_WORKER(lcore_id) {
122af75078fSIntel 		rte_eal_remote_launch(lcore_mainloop, NULL, lcore_id);
123af75078fSIntel 	}
124af75078fSIntel 
125cb056611SStephen Hemminger 	/* call it on main lcore too */
126af75078fSIntel 	(void) lcore_mainloop(NULL);
127*9a212dc0SConor Fogarty 	/* >8 End of call lcore_mainloop() on every worker lcore. */
128af75078fSIntel 
12910aa3757SChengchang Tang 	/* clean up the EAL */
13010aa3757SChengchang Tang 	rte_eal_cleanup();
13110aa3757SChengchang Tang 
132af75078fSIntel 	return 0;
133af75078fSIntel }
134