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