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