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 45extern "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 */ 58enum 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 */ 67union 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 */ 80struct 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 88struct rte_timer; 89 90/** 91 * Callback function type for timer expiry. 92 */ 93typedef 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 */ 100struct 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 * Allocate a timer data instance in shared memory to track a set of pending 137 * timer lists. 138 * 139 * @param id_ptr 140 * Pointer to variable into which to write the identifier of the allocated 141 * timer data instance. 142 * 143 * @return 144 * - 0: Success 145 * - -ENOSPC: maximum number of timer data instances already allocated 146 */ 147int rte_timer_data_alloc(uint32_t *id_ptr); 148 149/** 150 * Deallocate a timer data instance. 151 * 152 * @param id 153 * Identifier of the timer data instance to deallocate. 154 * 155 * @return 156 * - 0: Success 157 * - -EINVAL: invalid timer data instance identifier 158 */ 159int rte_timer_data_dealloc(uint32_t id); 160 161/** 162 * Initialize the timer library. 163 * 164 * Initializes internal variables (list, locks and so on) for the RTE 165 * timer library. 166 * 167 * @note 168 * This function must be called in every process before using the library. 169 * 170 * @return 171 * - 0: Success 172 * - -ENOMEM: Unable to allocate memory needed to initialize timer 173 * subsystem 174 */ 175int rte_timer_subsystem_init(void); 176 177/** 178 * Free timer subsystem resources. 179 */ 180void 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 */ 192void 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 */ 236int 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 */ 272void 273rte_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 */ 300int 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 */ 317void 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 */ 332int 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 348int64_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 */ 365int 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 */ 376int 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 */ 413int 414rte_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 */ 435int 436rte_timer_alt_stop(uint32_t timer_data_id, struct rte_timer *tim); 437 438/** 439 * Callback function type for rte_timer_alt_manage(). 440 */ 441typedef 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 */ 468int 469rte_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 */ 475typedef 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 */ 497int 498rte_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 */ 516int 517rte_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