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 */ 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 41 /* timer1 callback */ 42 static void 43 timer1_cb(__rte_unused struct rte_timer *tim, 44 __rte_unused void *arg) 45 { 46 unsigned lcore_id = rte_lcore_id(); 47 uint64_t hz; 48 49 printf("%s() on lcore %u\n", __func__, lcore_id); 50 51 /* reload it on another lcore */ 52 hz = rte_get_timer_hz(); 53 lcore_id = rte_get_next_lcore(lcore_id, 0, 1); 54 rte_timer_reset(tim, hz/3, SINGLE, lcore_id, timer1_cb, NULL); 55 } 56 57 static __rte_noreturn int 58 lcore_mainloop(__rte_unused void *arg) 59 { 60 uint64_t prev_tsc = 0, cur_tsc, diff_tsc; 61 unsigned lcore_id; 62 63 lcore_id = rte_lcore_id(); 64 printf("Starting mainloop on core %u\n", lcore_id); 65 66 while (1) { 67 /* 68 * Call the timer handler on each core: as we don't need a 69 * very precise timer, so only call rte_timer_manage() 70 * every ~10ms. In a real application, this will enhance 71 * performances as reading the HPET timer is not efficient. 72 */ 73 cur_tsc = rte_get_timer_cycles(); 74 diff_tsc = cur_tsc - prev_tsc; 75 if (diff_tsc > timer_resolution_cycles) { 76 rte_timer_manage(); 77 prev_tsc = cur_tsc; 78 } 79 } 80 } 81 82 int 83 main(int argc, char **argv) 84 { 85 int ret; 86 uint64_t hz; 87 unsigned lcore_id; 88 89 /* init EAL */ 90 ret = rte_eal_init(argc, argv); 91 if (ret < 0) 92 rte_panic("Cannot init EAL\n"); 93 94 /* init RTE timer library */ 95 rte_timer_subsystem_init(); 96 97 /* init timer structures */ 98 rte_timer_init(&timer0); 99 rte_timer_init(&timer1); 100 101 hz = rte_get_timer_hz(); 102 timer_resolution_cycles = hz * 10 / 1000; /* around 10ms */ 103 104 /* load timer0, every second, on main lcore, reloaded automatically */ 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 worker lcore */ 113 RTE_LCORE_FOREACH_WORKER(lcore_id) { 114 rte_eal_remote_launch(lcore_mainloop, NULL, lcore_id); 115 } 116 117 /* call it on main lcore too */ 118 (void) lcore_mainloop(NULL); 119 120 /* clean up the EAL */ 121 rte_eal_cleanup(); 122 123 return 0; 124 } 125