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