dpdk/lib/librte_timer/rte_timer.h
<<
>>
Prefs
   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