xref: /dpdk/examples/timer/main.c (revision e987449c9fce2ec6210be3d8bad680d08d68c9dc)
1af75078fSIntel /*-
2af75078fSIntel  *   BSD LICENSE
3af75078fSIntel  *
4b6df9fc8SIntel  *   Copyright(c) 2010-2013 Intel Corporation. All rights reserved.
5af75078fSIntel  *   All rights reserved.
6af75078fSIntel  *
7af75078fSIntel  *   Redistribution and use in source and binary forms, with or without
8af75078fSIntel  *   modification, are permitted provided that the following conditions
9af75078fSIntel  *   are met:
10af75078fSIntel  *
11af75078fSIntel  *     * Redistributions of source code must retain the above copyright
12af75078fSIntel  *       notice, this list of conditions and the following disclaimer.
13af75078fSIntel  *     * Redistributions in binary form must reproduce the above copyright
14af75078fSIntel  *       notice, this list of conditions and the following disclaimer in
15af75078fSIntel  *       the documentation and/or other materials provided with the
16af75078fSIntel  *       distribution.
17af75078fSIntel  *     * Neither the name of Intel Corporation nor the names of its
18af75078fSIntel  *       contributors may be used to endorse or promote products derived
19af75078fSIntel  *       from this software without specific prior written permission.
20af75078fSIntel  *
21af75078fSIntel  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22af75078fSIntel  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23af75078fSIntel  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24af75078fSIntel  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25af75078fSIntel  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26af75078fSIntel  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27af75078fSIntel  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28af75078fSIntel  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29af75078fSIntel  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30af75078fSIntel  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31af75078fSIntel  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32af75078fSIntel  *
33af75078fSIntel  */
34af75078fSIntel 
35af75078fSIntel #include <stdio.h>
36af75078fSIntel #include <string.h>
37af75078fSIntel #include <stdint.h>
38af75078fSIntel #include <errno.h>
39af75078fSIntel #include <sys/queue.h>
40af75078fSIntel 
41af75078fSIntel #include <rte_common.h>
42af75078fSIntel #include <rte_memory.h>
43af75078fSIntel #include <rte_memzone.h>
44af75078fSIntel #include <rte_launch.h>
45af75078fSIntel #include <rte_tailq.h>
46af75078fSIntel #include <rte_eal.h>
47af75078fSIntel #include <rte_per_lcore.h>
48af75078fSIntel #include <rte_lcore.h>
49af75078fSIntel #include <rte_cycles.h>
50af75078fSIntel #include <rte_timer.h>
51af75078fSIntel #include <rte_debug.h>
52af75078fSIntel 
53af75078fSIntel #include "main.h"
54af75078fSIntel 
55af75078fSIntel #define TIMER_RESOLUTION_CYCLES 20000000ULL /* around 10ms at 2 Ghz */
56af75078fSIntel 
57af75078fSIntel static struct rte_timer timer0;
58af75078fSIntel static struct rte_timer timer1;
59af75078fSIntel 
60af75078fSIntel /* timer0 callback */
61af75078fSIntel static void
62af75078fSIntel timer0_cb(__attribute__((unused)) struct rte_timer *tim,
63af75078fSIntel 	  __attribute__((unused)) void *arg)
64af75078fSIntel {
65af75078fSIntel 	static unsigned counter = 0;
66af75078fSIntel 	unsigned lcore_id = rte_lcore_id();
67af75078fSIntel 
68af75078fSIntel 	printf("%s() on lcore %u\n", __func__, lcore_id);
69af75078fSIntel 
70af75078fSIntel 	/* this timer is automatically reloaded until we decide to
71af75078fSIntel 	 * stop it, when counter reaches 20. */
72af75078fSIntel 	if ((counter ++) == 20)
73af75078fSIntel 		rte_timer_stop(tim);
74af75078fSIntel }
75af75078fSIntel 
76af75078fSIntel /* timer1 callback */
77af75078fSIntel static void
78af75078fSIntel timer1_cb(__attribute__((unused)) struct rte_timer *tim,
79af75078fSIntel 	  __attribute__((unused)) void *arg)
80af75078fSIntel {
81af75078fSIntel 	unsigned lcore_id = rte_lcore_id();
82af75078fSIntel 	uint64_t hz;
83af75078fSIntel 
84af75078fSIntel 	printf("%s() on lcore %u\n", __func__, lcore_id);
85af75078fSIntel 
86af75078fSIntel 	/* reload it on another lcore */
87*e987449cSIntel 	hz = rte_get_timer_hz();
88af75078fSIntel 	lcore_id = rte_get_next_lcore(lcore_id, 0, 1);
89af75078fSIntel 	rte_timer_reset(tim, hz/3, SINGLE, lcore_id, timer1_cb, NULL);
90af75078fSIntel }
91af75078fSIntel 
92af75078fSIntel static __attribute__((noreturn)) int
93af75078fSIntel lcore_mainloop(__attribute__((unused)) void *arg)
94af75078fSIntel {
95af75078fSIntel 	uint64_t prev_tsc = 0, cur_tsc, diff_tsc;
96af75078fSIntel 	unsigned lcore_id;
97af75078fSIntel 
98af75078fSIntel 	lcore_id = rte_lcore_id();
99af75078fSIntel 	printf("Starting mainloop on core %u\n", lcore_id);
100af75078fSIntel 
101af75078fSIntel 	while (1) {
102af75078fSIntel 		/*
103af75078fSIntel 		 * Call the timer handler on each core: as we don't
104af75078fSIntel 		 * need a very precise timer, so only call
105af75078fSIntel 		 * rte_timer_manage() every ~10ms (at 2Ghz). In a real
106af75078fSIntel 		 * application, this will enhance performances as
107af75078fSIntel 		 * reading the HPET timer is not efficient.
108af75078fSIntel 		 */
109af75078fSIntel 		cur_tsc = rte_rdtsc();
110af75078fSIntel 		diff_tsc = cur_tsc - prev_tsc;
111af75078fSIntel 		if (diff_tsc > TIMER_RESOLUTION_CYCLES) {
112af75078fSIntel 			rte_timer_manage();
113af75078fSIntel 			prev_tsc = cur_tsc;
114af75078fSIntel 		}
115af75078fSIntel 	}
116af75078fSIntel }
117af75078fSIntel 
118af75078fSIntel int
119af75078fSIntel MAIN(int argc, char **argv)
120af75078fSIntel {
121af75078fSIntel 	int ret;
122af75078fSIntel 	uint64_t hz;
123af75078fSIntel 	unsigned lcore_id;
124af75078fSIntel 
125af75078fSIntel 	/* init EAL */
126af75078fSIntel 	ret = rte_eal_init(argc, argv);
127af75078fSIntel 	if (ret < 0)
128af75078fSIntel 		rte_panic("Cannot init EAL\n");
129af75078fSIntel 
130af75078fSIntel 	/* init RTE timer library */
131af75078fSIntel 	rte_timer_subsystem_init();
132af75078fSIntel 
133af75078fSIntel 	/* init timer structures */
134af75078fSIntel 	rte_timer_init(&timer0);
135af75078fSIntel 	rte_timer_init(&timer1);
136af75078fSIntel 
137af75078fSIntel 	/* load timer0, every second, on master lcore, reloaded automatically */
138*e987449cSIntel 	hz = rte_get_timer_hz();
139af75078fSIntel 	lcore_id = rte_lcore_id();
140af75078fSIntel 	rte_timer_reset(&timer0, hz, PERIODICAL, lcore_id, timer0_cb, NULL);
141af75078fSIntel 
142af75078fSIntel 	/* load timer1, every second/3, on next lcore, reloaded manually */
143af75078fSIntel 	lcore_id = rte_get_next_lcore(lcore_id, 0, 1);
144af75078fSIntel 	rte_timer_reset(&timer1, hz/3, SINGLE, lcore_id, timer1_cb, NULL);
145af75078fSIntel 
146af75078fSIntel 	/* call lcore_mainloop() on every slave lcore */
147af75078fSIntel 	RTE_LCORE_FOREACH_SLAVE(lcore_id) {
148af75078fSIntel 		rte_eal_remote_launch(lcore_mainloop, NULL, lcore_id);
149af75078fSIntel 	}
150af75078fSIntel 
151af75078fSIntel 	/* call it on master lcore too */
152af75078fSIntel 	(void) lcore_mainloop(NULL);
153af75078fSIntel 
154af75078fSIntel 	return 0;
155af75078fSIntel }
156