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