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