1.. BSD LICENSE 2 Copyright(c) 2010-2014 Intel Corporation. All rights reserved. 3 All rights reserved. 4 5 Redistribution and use in source and binary forms, with or without 6 modification, are permitted provided that the following conditions 7 are met: 8 9 * Redistributions of source code must retain the above copyright 10 notice, this list of conditions and the following disclaimer. 11 * Redistributions in binary form must reproduce the above copyright 12 notice, this list of conditions and the following disclaimer in 13 the documentation and/or other materials provided with the 14 distribution. 15 * Neither the name of Intel Corporation nor the names of its 16 contributors may be used to endorse or promote products derived 17 from this software without specific prior written permission. 18 19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 31Timer Sample Application 32======================== 33 34The Timer sample application is a simple application that demonstrates the use of a timer in a DPDK application. 35This application prints some messages from different lcores regularly, demonstrating the use of timers. 36 37Compiling the Application 38------------------------- 39 40To compile the sample application see :doc:`compiling`. 41 42The application is located in the ``timer`` sub-directory. 43 44Running the Application 45----------------------- 46 47To run the example in linuxapp environment: 48 49.. code-block:: console 50 51 $ ./build/timer -l 0-3 -n 4 52 53Refer to the *DPDK Getting Started Guide* for general information on running applications and 54the Environment Abstraction Layer (EAL) options. 55 56Explanation 57----------- 58 59The following sections provide some explanation of the code. 60 61Initialization and Main Loop 62~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 63 64In addition to EAL initialization, the timer subsystem must be initialized, by calling the rte_timer_subsystem_init() function. 65 66.. code-block:: c 67 68 /* init EAL */ 69 70 ret = rte_eal_init(argc, argv); 71 if (ret < 0) 72 rte_panic("Cannot init EAL\n"); 73 74 /* init RTE timer library */ 75 76 rte_timer_subsystem_init(); 77 78After timer creation (see the next paragraph), 79the main loop is executed on each slave lcore using the well-known rte_eal_remote_launch() and also on the master. 80 81.. code-block:: c 82 83 /* call lcore_mainloop() on every slave lcore */ 84 85 RTE_LCORE_FOREACH_SLAVE(lcore_id) { 86 rte_eal_remote_launch(lcore_mainloop, NULL, lcore_id); 87 } 88 89 /* call it on master lcore too */ 90 91 (void) lcore_mainloop(NULL); 92 93The main loop is very simple in this example: 94 95.. code-block:: c 96 97 while (1) { 98 /* 99 * Call the timer handler on each core: as we don't 100 * need a very precise timer, so only call 101 * rte_timer_manage() every ~10ms (at 2 GHz). In a real 102 * application, this will enhance performances as 103 * reading the HPET timer is not efficient. 104 */ 105 106 cur_tsc = rte_rdtsc(); 107 108 diff_tsc = cur_tsc - prev_tsc; 109 110 if (diff_tsc > TIMER_RESOLUTION_CYCLES) { 111 rte_timer_manage(); 112 prev_tsc = cur_tsc; 113 } 114 } 115 116As explained in the comment, it is better to use the TSC register (as it is a per-lcore register) to check if the 117rte_timer_manage() function must be called or not. 118In this example, the resolution of the timer is 10 milliseconds. 119 120Managing Timers 121~~~~~~~~~~~~~~~ 122 123In the main() function, the two timers are initialized. 124This call to rte_timer_init() is necessary before doing any other operation on the timer structure. 125 126.. code-block:: c 127 128 /* init timer structures */ 129 130 rte_timer_init(&timer0); 131 rte_timer_init(&timer1); 132 133Then, the two timers are configured: 134 135* The first timer (timer0) is loaded on the master lcore and expires every second. 136 Since the PERIODICAL flag is provided, the timer is reloaded automatically by the timer subsystem. 137 The callback function is timer0_cb(). 138 139* The second timer (timer1) is loaded on the next available lcore every 333 ms. 140 The SINGLE flag means that the timer expires only once and must be reloaded manually if required. 141 The callback function is timer1_cb(). 142 143.. code-block:: c 144 145 /* load timer0, every second, on master lcore, reloaded automatically */ 146 147 hz = rte_get_hpet_hz(); 148 149 lcore_id = rte_lcore_id(); 150 151 rte_timer_reset(&timer0, hz, PERIODICAL, lcore_id, timer0_cb, NULL); 152 153 /* load timer1, every second/3, on next lcore, reloaded manually */ 154 155 lcore_id = rte_get_next_lcore(lcore_id, 0, 1); 156 157 rte_timer_reset(&timer1, hz/3, SINGLE, lcore_id, timer1_cb, NULL); 158 159The callback for the first timer (timer0) only displays a message until a global counter reaches 20 (after 20 seconds). 160In this case, the timer is stopped using the rte_timer_stop() function. 161 162.. code-block:: c 163 164 /* timer0 callback */ 165 166 static void 167 timer0_cb( attribute ((unused)) struct rte_timer *tim, __attribute ((unused)) void *arg) 168 { 169 static unsigned counter = 0; 170 171 unsigned lcore_id = rte_lcore_id(); 172 173 printf("%s() on lcore %u\n", FUNCTION , lcore_id); 174 175 /* this timer is automatically reloaded until we decide to stop it, when counter reaches 20. */ 176 177 if ((counter ++) == 20) 178 rte_timer_stop(tim); 179 } 180 181The callback for the second timer (timer1) displays a message and reloads the timer on the next lcore, using the 182rte_timer_reset() function: 183 184.. code-block:: c 185 186 /* timer1 callback */ 187 188 static void 189 timer1_cb( attribute ((unused)) struct rte_timer *tim, _attribute ((unused)) void *arg) 190 { 191 unsigned lcore_id = rte_lcore_id(); 192 uint64_t hz; 193 194 printf("%s() on lcore %u\\n", FUNCTION , lcore_id); 195 196 /* reload it on another lcore */ 197 198 hz = rte_get_hpet_hz(); 199 200 lcore_id = rte_get_next_lcore(lcore_id, 0, 1); 201 202 rte_timer_reset(&timer1, hz/3, SINGLE, lcore_id, timer1_cb, NULL); 203 } 204