1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2010-2014 Intel Corporation 3 */ 4 5 #ifndef _RTE_TIMER_H_ 6 #define _RTE_TIMER_H_ 7 8 /** 9 * @file 10 RTE Timer 11 * 12 * This library provides a timer service to RTE Data Plane execution 13 * units that allows the execution of callback functions asynchronously. 14 * 15 * - Timers can be periodic or single (one-shot). 16 * - The timers can be loaded from one core and executed on another. This has 17 * to be specified in the call to rte_timer_reset(). 18 * - High precision is possible. NOTE: this depends on the call frequency to 19 * rte_timer_manage() that check the timer expiration for the local core. 20 * - If not used in an application, for improved performance, it can be 21 * disabled at compilation time by not calling the rte_timer_manage() 22 * to improve performance. 23 * 24 * The timer library uses the rte_get_hpet_cycles() function that 25 * uses the HPET, when available, to provide a reliable time reference. [HPET 26 * routines are provided by EAL, which falls back to using the chip TSC (time- 27 * stamp counter) as fallback when HPET is not available] 28 * 29 * This library provides an interface to add, delete and restart a 30 * timer. The API is based on the BSD callout(9) API with a few 31 * differences. 32 * 33 * See the RTE architecture documentation for more information about the 34 * design of this library. 35 */ 36 37 #include <stdio.h> 38 #include <stdint.h> 39 #include <stddef.h> 40 #include <rte_common.h> 41 #include <rte_config.h> 42 #include <rte_spinlock.h> 43 44 #ifdef __cplusplus 45 extern "C" { 46 #endif 47 48 #define RTE_TIMER_STOP 0 /**< State: timer is stopped. */ 49 #define RTE_TIMER_PENDING 1 /**< State: timer is scheduled. */ 50 #define RTE_TIMER_RUNNING 2 /**< State: timer function is running. */ 51 #define RTE_TIMER_CONFIG 3 /**< State: timer is being configured. */ 52 53 #define RTE_TIMER_NO_OWNER -2 /**< Timer has no owner. */ 54 55 /** 56 * Timer type: Periodic or single (one-shot). 57 */ 58 enum rte_timer_type { 59 SINGLE, 60 PERIODICAL 61 }; 62 63 /** 64 * Timer status: A union of the state (stopped, pending, running, 65 * config) and an owner (the id of the lcore that owns the timer). 66 */ 67 union rte_timer_status { 68 RTE_STD_C11 69 struct { 70 uint16_t state; /**< Stop, pending, running, config. */ 71 int16_t owner; /**< The lcore that owns the timer. */ 72 }; 73 uint32_t u32; /**< To atomic-set status + owner. */ 74 }; 75 76 #ifdef RTE_LIBRTE_TIMER_DEBUG 77 /** 78 * A structure that stores the timer statistics (per-lcore). 79 */ 80 struct rte_timer_debug_stats { 81 uint64_t reset; /**< Number of success calls to rte_timer_reset(). */ 82 uint64_t stop; /**< Number of success calls to rte_timer_stop(). */ 83 uint64_t manage; /**< Number of calls to rte_timer_manage(). */ 84 uint64_t pending; /**< Number of pending/running timers. */ 85 }; 86 #endif 87 88 struct rte_timer; 89 90 /** 91 * Callback function type for timer expiry. 92 */ 93 typedef void (*rte_timer_cb_t)(struct rte_timer *, void *); 94 95 #define MAX_SKIPLIST_DEPTH 10 96 97 /** 98 * A structure describing a timer in RTE. 99 */ 100 struct rte_timer 101 { 102 uint64_t expire; /**< Time when timer expire. */ 103 struct rte_timer *sl_next[MAX_SKIPLIST_DEPTH]; 104 volatile union rte_timer_status status; /**< Status of timer. */ 105 uint64_t period; /**< Period of timer (0 if not periodic). */ 106 rte_timer_cb_t f; /**< Callback function. */ 107 void *arg; /**< Argument to callback function. */ 108 }; 109 110 111 #ifdef __cplusplus 112 /** 113 * A C++ static initializer for a timer structure. 114 */ 115 #define RTE_TIMER_INITIALIZER { \ 116 0, \ 117 {NULL}, \ 118 {{RTE_TIMER_STOP, RTE_TIMER_NO_OWNER}}, \ 119 0, \ 120 NULL, \ 121 NULL, \ 122 } 123 #else 124 /** 125 * A static initializer for a timer structure. 126 */ 127 #define RTE_TIMER_INITIALIZER { \ 128 .status = {{ \ 129 .state = RTE_TIMER_STOP, \ 130 .owner = RTE_TIMER_NO_OWNER, \ 131 }}, \ 132 } 133 #endif 134 135 /** 136 * @warning 137 * @b EXPERIMENTAL: this API may change without prior notice 138 * 139 * Allocate a timer data instance in shared memory to track a set of pending 140 * timer lists. 141 * 142 * @param id_ptr 143 * Pointer to variable into which to write the identifier of the allocated 144 * timer data instance. 145 * 146 * @return 147 * - 0: Success 148 * - -ENOSPC: maximum number of timer data instances already allocated 149 */ 150 __rte_experimental 151 int rte_timer_data_alloc(uint32_t *id_ptr); 152 153 /** 154 * @warning 155 * @b EXPERIMENTAL: this API may change without prior notice 156 * 157 * Deallocate a timer data instance. 158 * 159 * @param id 160 * Identifier of the timer data instance to deallocate. 161 * 162 * @return 163 * - 0: Success 164 * - -EINVAL: invalid timer data instance identifier 165 */ 166 __rte_experimental 167 int rte_timer_data_dealloc(uint32_t id); 168 169 /** 170 * Initialize the timer library. 171 * 172 * Initializes internal variables (list, locks and so on) for the RTE 173 * timer library. 174 * 175 * @note 176 * This function must be called in every process before using the library. 177 * 178 * @return 179 * - 0: Success 180 * - -ENOMEM: Unable to allocate memory needed to initialize timer 181 * subsystem 182 */ 183 int rte_timer_subsystem_init(void); 184 185 /** 186 * @warning 187 * @b EXPERIMENTAL: this API may change without prior notice 188 * 189 * Free timer subsystem resources. 190 */ 191 __rte_experimental 192 void rte_timer_subsystem_finalize(void); 193 194 /** 195 * Initialize a timer handle. 196 * 197 * The rte_timer_init() function initializes the timer handle *tim* 198 * for use. No operations can be performed on a timer before it is 199 * initialized. 200 * 201 * @param tim 202 * The timer to initialize. 203 */ 204 void rte_timer_init(struct rte_timer *tim); 205 206 /** 207 * Reset and start the timer associated with the timer handle. 208 * 209 * The rte_timer_reset() function resets and starts the timer 210 * associated with the timer handle *tim*. When the timer expires after 211 * *ticks* HPET cycles, the function specified by *fct* will be called 212 * with the argument *arg* on core *tim_lcore*. 213 * 214 * If the timer associated with the timer handle is already running 215 * (in the RUNNING state), the function will fail. The user has to check 216 * the return value of the function to see if there is a chance that the 217 * timer is in the RUNNING state. 218 * 219 * If the timer is being configured on another core (the CONFIG state), 220 * it will also fail. 221 * 222 * If the timer is pending or stopped, it will be rescheduled with the 223 * new parameters. 224 * 225 * @param tim 226 * The timer handle. 227 * @param ticks 228 * The number of cycles (see rte_get_hpet_hz()) before the callback 229 * function is called. 230 * @param type 231 * The type can be either: 232 * - PERIODICAL: The timer is automatically reloaded after execution 233 * (returns to the PENDING state) 234 * - SINGLE: The timer is one-shot, that is, the timer goes to a 235 * STOPPED state after execution. 236 * @param tim_lcore 237 * The ID of the lcore where the timer callback function has to be 238 * executed. If tim_lcore is LCORE_ID_ANY, the timer library will 239 * launch it on a different core for each call (round-robin). 240 * @param fct 241 * The callback function of the timer. 242 * @param arg 243 * The user argument of the callback function. 244 * @return 245 * - 0: Success; the timer is scheduled. 246 * - (-1): Timer is in the RUNNING or CONFIG state. 247 */ 248 int rte_timer_reset(struct rte_timer *tim, uint64_t ticks, 249 enum rte_timer_type type, unsigned tim_lcore, 250 rte_timer_cb_t fct, void *arg); 251 252 /** 253 * Loop until rte_timer_reset() succeeds. 254 * 255 * Reset and start the timer associated with the timer handle. Always 256 * succeed. See rte_timer_reset() for details. 257 * 258 * @param tim 259 * The timer handle. 260 * @param ticks 261 * The number of cycles (see rte_get_hpet_hz()) before the callback 262 * function is called. 263 * @param type 264 * The type can be either: 265 * - PERIODICAL: The timer is automatically reloaded after execution 266 * (returns to the PENDING state) 267 * - SINGLE: The timer is one-shot, that is, the timer goes to a 268 * STOPPED state after execution. 269 * @param tim_lcore 270 * The ID of the lcore where the timer callback function has to be 271 * executed. If tim_lcore is LCORE_ID_ANY, the timer library will 272 * launch it on a different core for each call (round-robin). 273 * @param fct 274 * The callback function of the timer. 275 * @param arg 276 * The user argument of the callback function. 277 * 278 * @note 279 * This API should not be called inside a timer's callback function to 280 * reset another timer; doing so could hang in certain scenarios. Instead, 281 * the rte_timer_reset() API can be called directly and its return code 282 * can be checked for success or failure. 283 */ 284 void 285 rte_timer_reset_sync(struct rte_timer *tim, uint64_t ticks, 286 enum rte_timer_type type, unsigned tim_lcore, 287 rte_timer_cb_t fct, void *arg); 288 289 /** 290 * Stop a timer. 291 * 292 * The rte_timer_stop() function stops the timer associated with the 293 * timer handle *tim*. It may fail if the timer is currently running or 294 * being configured. 295 * 296 * If the timer is pending or stopped (for instance, already expired), 297 * the function will succeed. The timer handle tim must have been 298 * initialized using rte_timer_init(), otherwise, undefined behavior 299 * will occur. 300 * 301 * This function can be called safely from a timer callback. If it 302 * succeeds, the timer is not referenced anymore by the timer library 303 * and the timer structure can be freed (even in the callback 304 * function). 305 * 306 * @param tim 307 * The timer handle. 308 * @return 309 * - 0: Success; the timer is stopped. 310 * - (-1): The timer is in the RUNNING or CONFIG state. 311 */ 312 int rte_timer_stop(struct rte_timer *tim); 313 314 /** 315 * Loop until rte_timer_stop() succeeds. 316 * 317 * After a call to this function, the timer identified by *tim* is 318 * stopped. See rte_timer_stop() for details. 319 * 320 * @param tim 321 * The timer handle. 322 * 323 * @note 324 * This API should not be called inside a timer's callback function to 325 * stop another timer; doing so could hang in certain scenarios. Instead, the 326 * rte_timer_stop() API can be called directly and its return code can 327 * be checked for success or failure. 328 */ 329 void rte_timer_stop_sync(struct rte_timer *tim); 330 331 /** 332 * Test if a timer is pending. 333 * 334 * The rte_timer_pending() function tests the PENDING status 335 * of the timer handle *tim*. A PENDING timer is one that has been 336 * scheduled and whose function has not yet been called. 337 * 338 * @param tim 339 * The timer handle. 340 * @return 341 * - 0: The timer is not pending. 342 * - 1: The timer is pending. 343 */ 344 int rte_timer_pending(struct rte_timer *tim); 345 346 /** 347 * Manage the timer list and execute callback functions. 348 * 349 * This function must be called periodically from EAL lcores 350 * main_loop(). It browses the list of pending timers and runs all 351 * timers that are expired. 352 * 353 * The precision of the timer depends on the call frequency of this 354 * function. However, the more often the function is called, the more 355 * CPU resources it will use. 356 * 357 * @return 358 * - 0: Success 359 * - -EINVAL: timer subsystem not yet initialized 360 */ 361 int rte_timer_manage(void); 362 363 /** 364 * Dump statistics about timers. 365 * 366 * @param f 367 * A pointer to a file for output 368 * @return 369 * - 0: Success 370 * - -EINVAL: timer subsystem not yet initialized 371 */ 372 int rte_timer_dump_stats(FILE *f); 373 374 /** 375 * @warning 376 * @b EXPERIMENTAL: this API may change without prior notice 377 * 378 * This function is the same as rte_timer_reset(), except that it allows a 379 * caller to specify the rte_timer_data instance containing the list to which 380 * the timer should be added. 381 * 382 * @see rte_timer_reset() 383 * 384 * @param timer_data_id 385 * An identifier indicating which instance of timer data should be used for 386 * this operation. 387 * @param tim 388 * The timer handle. 389 * @param ticks 390 * The number of cycles (see rte_get_hpet_hz()) before the callback 391 * function is called. 392 * @param type 393 * The type can be either: 394 * - PERIODICAL: The timer is automatically reloaded after execution 395 * (returns to the PENDING state) 396 * - SINGLE: The timer is one-shot, that is, the timer goes to a 397 * STOPPED state after execution. 398 * @param tim_lcore 399 * The ID of the lcore where the timer callback function has to be 400 * executed. If tim_lcore is LCORE_ID_ANY, the timer library will 401 * launch it on a different core for each call (round-robin). 402 * @param fct 403 * The callback function of the timer. This parameter can be NULL if (and 404 * only if) rte_timer_alt_manage() will be used to manage this timer. 405 * @param arg 406 * The user argument of the callback function. 407 * @return 408 * - 0: Success; the timer is scheduled. 409 * - (-1): Timer is in the RUNNING or CONFIG state. 410 * - -EINVAL: invalid timer_data_id 411 */ 412 __rte_experimental 413 int 414 rte_timer_alt_reset(uint32_t timer_data_id, struct rte_timer *tim, 415 uint64_t ticks, enum rte_timer_type type, 416 unsigned int tim_lcore, rte_timer_cb_t fct, void *arg); 417 418 /** 419 * @warning 420 * @b EXPERIMENTAL: this API may change without prior notice 421 * 422 * This function is the same as rte_timer_stop(), except that it allows a 423 * caller to specify the rte_timer_data instance containing the list from which 424 * this timer should be removed. 425 * 426 * @see rte_timer_stop() 427 * 428 * @param timer_data_id 429 * An identifier indicating which instance of timer data should be used for 430 * this operation. 431 * @param tim 432 * The timer handle. 433 * @return 434 * - 0: Success; the timer is stopped. 435 * - (-1): The timer is in the RUNNING or CONFIG state. 436 * - -EINVAL: invalid timer_data_id 437 */ 438 __rte_experimental 439 int 440 rte_timer_alt_stop(uint32_t timer_data_id, struct rte_timer *tim); 441 442 /** 443 * Callback function type for rte_timer_alt_manage(). 444 */ 445 typedef void (*rte_timer_alt_manage_cb_t)(struct rte_timer *tim); 446 447 /** 448 * @warning 449 * @b EXPERIMENTAL: this API may change without prior notice 450 * 451 * Manage a set of timer lists and execute the specified callback function for 452 * all expired timers. This function is similar to rte_timer_manage(), except 453 * that it allows a caller to specify the timer_data instance that should 454 * be operated on, as well as a set of lcore IDs identifying which timer lists 455 * should be processed. Callback functions of individual timers are ignored. 456 * 457 * @see rte_timer_manage() 458 * 459 * @param timer_data_id 460 * An identifier indicating which instance of timer data should be used for 461 * this operation. 462 * @param poll_lcores 463 * An array of lcore ids identifying the timer lists that should be processed. 464 * NULL is allowed - if NULL, the timer list corresponding to the lcore 465 * calling this routine is processed (same as rte_timer_manage()). 466 * @param n_poll_lcores 467 * The size of the poll_lcores array. If 'poll_lcores' is NULL, this parameter 468 * is ignored. 469 * @param f 470 * The callback function which should be called for all expired timers. 471 * @return 472 * - 0: success 473 * - -EINVAL: invalid timer_data_id 474 */ 475 __rte_experimental 476 int 477 rte_timer_alt_manage(uint32_t timer_data_id, unsigned int *poll_lcores, 478 int n_poll_lcores, rte_timer_alt_manage_cb_t f); 479 480 /** 481 * Callback function type for rte_timer_stop_all(). 482 */ 483 typedef void (*rte_timer_stop_all_cb_t)(struct rte_timer *tim, void *arg); 484 485 /** 486 * @warning 487 * @b EXPERIMENTAL: this API may change without prior notice 488 * 489 * Walk the pending timer lists for the specified lcore IDs, and for each timer 490 * that is encountered, stop it and call the specified callback function to 491 * process it further. 492 * 493 * @param timer_data_id 494 * An identifier indicating which instance of timer data should be used for 495 * this operation. 496 * @param walk_lcores 497 * An array of lcore ids identifying the timer lists that should be processed. 498 * @param nb_walk_lcores 499 * The size of the walk_lcores array. 500 * @param f 501 * The callback function which should be called for each timers. Can be NULL. 502 * @param f_arg 503 * An arbitrary argument that will be passed to f, if it is called. 504 * @return 505 * - 0: success 506 * - EINVAL: invalid timer_data_id 507 */ 508 __rte_experimental 509 int 510 rte_timer_stop_all(uint32_t timer_data_id, unsigned int *walk_lcores, 511 int nb_walk_lcores, rte_timer_stop_all_cb_t f, void *f_arg); 512 513 /** 514 * @warning 515 * @b EXPERIMENTAL: this API may change without prior notice 516 * 517 * This function is the same as rte_timer_dump_stats(), except that it allows 518 * the caller to specify the rte_timer_data instance that should be used. 519 * 520 * @see rte_timer_dump_stats() 521 * 522 * @param timer_data_id 523 * An identifier indicating which instance of timer data should be used for 524 * this operation. 525 * @param f 526 * A pointer to a file for output 527 * @return 528 * - 0: success 529 * - -EINVAL: invalid timer_data_id 530 */ 531 __rte_experimental 532 int 533 rte_timer_alt_dump_stats(uint32_t timer_data_id, FILE *f); 534 535 #ifdef __cplusplus 536 } 537 #endif 538 539 #endif /* _RTE_TIMER_H_ */ 540