1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2010-2014 Intel Corporation
12 * This library provides a timer service to RTE Data Plane execution
13 * units that allows the execution of callback functions asynchronously.
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.
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]
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
33 * See the RTE architecture documentation for more information about the
34 * design of this library.
39 #include <rte_common.h>
40 #include <rte_spinlock.h>
46 #define RTE_TIMER_STOP 0 /**< State: timer is stopped. */
47 #define RTE_TIMER_PENDING 1 /**< State: timer is scheduled. */
48 #define RTE_TIMER_RUNNING 2 /**< State: timer function is running. */
49 #define RTE_TIMER_CONFIG 3 /**< State: timer is being configured. */
51 #define RTE_TIMER_NO_OWNER -2 /**< Timer has no owner. */
54 * Timer type: Periodic or single (one-shot).
62 * Timer status: A union of the state (stopped, pending, running,
63 * config) and an owner (the id of the lcore that owns the timer).
65 union rte_timer_status {
68 uint16_t state; /**< Stop, pending, running, config. */
69 int16_t owner; /**< The lcore that owns the timer. */
71 uint32_t u32; /**< To atomic-set status + owner. */
74 #ifdef RTE_LIBRTE_TIMER_DEBUG
76 * A structure that stores the timer statistics (per-lcore).
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. */
89 * Callback function type for timer expiry.
91 typedef void (*rte_timer_cb_t)(struct rte_timer *, void *);
93 #define MAX_SKIPLIST_DEPTH 10
96 * A structure describing a timer in RTE.
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. */
111 * A C++ static initializer for a timer structure.
113 #define RTE_TIMER_INITIALIZER { \
116 {{RTE_TIMER_STOP, RTE_TIMER_NO_OWNER}}, \
123 * A static initializer for a timer structure.
125 #define RTE_TIMER_INITIALIZER { \
127 .state = RTE_TIMER_STOP, \
128 .owner = RTE_TIMER_NO_OWNER, \
134 * Allocate a timer data instance in shared memory to track a set of pending
138 * Pointer to variable into which to write the identifier of the allocated
139 * timer data instance.
143 * - -ENOSPC: maximum number of timer data instances already allocated
145 int rte_timer_data_alloc(uint32_t *id_ptr);
148 * Deallocate a timer data instance.
151 * Identifier of the timer data instance to deallocate.
155 * - -EINVAL: invalid timer data instance identifier
157 int rte_timer_data_dealloc(uint32_t id);
160 * Initialize the timer library.
162 * Initializes internal variables (list, locks and so on) for the RTE
166 * This function must be called in every process before using the library.
170 * - -ENOMEM: Unable to allocate memory needed to initialize timer
172 * - -EALREADY: timer subsystem was already initialized. Not an error.
174 int rte_timer_subsystem_init(void);
177 * Free timer subsystem resources.
179 void rte_timer_subsystem_finalize(void);
182 * Initialize a timer handle.
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
189 * The timer to initialize.
191 void rte_timer_init(struct rte_timer *tim);
194 * Reset and start the timer associated with the timer handle.
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*.
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.
206 * If the timer is being configured on another core (the CONFIG state),
209 * If the timer is pending or stopped, it will be rescheduled with the
215 * The number of cycles (see rte_get_hpet_hz()) before the callback
216 * function is called.
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.
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).
228 * The callback function of the timer.
230 * The user argument of the callback function.
232 * - 0: Success; the timer is scheduled.
233 * - (-1): Timer is in the RUNNING or CONFIG state.
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);
240 * Loop until rte_timer_reset() succeeds.
242 * Reset and start the timer associated with the timer handle. Always
243 * succeed. See rte_timer_reset() for details.
248 * The number of cycles (see rte_get_hpet_hz()) before the callback
249 * function is called.
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.
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).
261 * The callback function of the timer.
263 * The user argument of the callback function.
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.
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);
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
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
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
296 * - 0: Success; the timer is stopped.
297 * - (-1): The timer is in the RUNNING or CONFIG state.
299 int rte_timer_stop(struct rte_timer *tim);
302 * Loop until rte_timer_stop() succeeds.
304 * After a call to this function, the timer identified by *tim* is
305 * stopped. See rte_timer_stop() for details.
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.
316 void rte_timer_stop_sync(struct rte_timer *tim);
319 * Test if a timer is pending.
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.
328 * - 0: The timer is not pending.
329 * - 1: The timer is pending.
331 int rte_timer_pending(struct rte_timer *tim);
335 * @b EXPERIMENTAL: this API may change without prior notice
337 * Time until the next timer on the current lcore
338 * This function gives the ticks until the next timer will be active.
341 * - -EINVAL: invalid timer data instance identifier
342 * - -ENOENT: no timer pending
343 * - 0: a timer is pending and will run at next rte_timer_manage()
344 * - >0: ticks until the next timer is ready
347 int64_t rte_timer_next_ticks(void);
350 * Manage the timer list and execute callback functions.
352 * This function must be called periodically from EAL lcores
353 * main_loop(). It browses the list of pending timers and runs all
354 * timers that are expired.
356 * The precision of the timer depends on the call frequency of this
357 * function. However, the more often the function is called, the more
358 * CPU resources it will use.
362 * - -EINVAL: timer subsystem not yet initialized
364 int rte_timer_manage(void);
367 * Dump statistics about timers.
370 * A pointer to a file for output
373 * - -EINVAL: timer subsystem not yet initialized
375 int rte_timer_dump_stats(FILE *f);
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.
382 * @see rte_timer_reset()
384 * @param timer_data_id
385 * An identifier indicating which instance of timer data should be used for
390 * The number of cycles (see rte_get_hpet_hz()) before the callback
391 * function is called.
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.
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).
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.
406 * The user argument of the callback function.
408 * - 0: Success; the timer is scheduled.
409 * - (-1): Timer is in the RUNNING or CONFIG state.
410 * - -EINVAL: invalid timer_data_id
413 rte_timer_alt_reset(uint32_t timer_data_id, struct rte_timer *tim,
414 uint64_t ticks, enum rte_timer_type type,
415 unsigned int tim_lcore, rte_timer_cb_t fct, void *arg);
418 * This function is the same as rte_timer_stop(), except that it allows a
419 * caller to specify the rte_timer_data instance containing the list from which
420 * this timer should be removed.
422 * @see rte_timer_stop()
424 * @param timer_data_id
425 * An identifier indicating which instance of timer data should be used for
430 * - 0: Success; the timer is stopped.
431 * - (-1): The timer is in the RUNNING or CONFIG state.
432 * - -EINVAL: invalid timer_data_id
435 rte_timer_alt_stop(uint32_t timer_data_id, struct rte_timer *tim);
438 * Callback function type for rte_timer_alt_manage().
440 typedef void (*rte_timer_alt_manage_cb_t)(struct rte_timer *tim);
443 * Manage a set of timer lists and execute the specified callback function for
444 * all expired timers. This function is similar to rte_timer_manage(), except
445 * that it allows a caller to specify the timer_data instance that should
446 * be operated on, as well as a set of lcore IDs identifying which timer lists
447 * should be processed. Callback functions of individual timers are ignored.
449 * @see rte_timer_manage()
451 * @param timer_data_id
452 * An identifier indicating which instance of timer data should be used for
455 * An array of lcore ids identifying the timer lists that should be processed.
456 * NULL is allowed - if NULL, the timer list corresponding to the lcore
457 * calling this routine is processed (same as rte_timer_manage()).
458 * @param n_poll_lcores
459 * The size of the poll_lcores array. If 'poll_lcores' is NULL, this parameter
462 * The callback function which should be called for all expired timers.
465 * - -EINVAL: invalid timer_data_id
468 rte_timer_alt_manage(uint32_t timer_data_id, unsigned int *poll_lcores,
469 int n_poll_lcores, rte_timer_alt_manage_cb_t f);
472 * Callback function type for rte_timer_stop_all().
474 typedef void (*rte_timer_stop_all_cb_t)(struct rte_timer *tim, void *arg);
477 * Walk the pending timer lists for the specified lcore IDs, and for each timer
478 * that is encountered, stop it and call the specified callback function to
479 * process it further.
481 * @param timer_data_id
482 * An identifier indicating which instance of timer data should be used for
485 * An array of lcore ids identifying the timer lists that should be processed.
486 * @param nb_walk_lcores
487 * The size of the walk_lcores array.
489 * The callback function which should be called for each timers. Can be NULL.
491 * An arbitrary argument that will be passed to f, if it is called.
494 * - EINVAL: invalid timer_data_id
497 rte_timer_stop_all(uint32_t timer_data_id, unsigned int *walk_lcores,
498 int nb_walk_lcores, rte_timer_stop_all_cb_t f, void *f_arg);
501 * This function is the same as rte_timer_dump_stats(), except that it allows
502 * the caller to specify the rte_timer_data instance that should be used.
504 * @see rte_timer_dump_stats()
506 * @param timer_data_id
507 * An identifier indicating which instance of timer data should be used for
510 * A pointer to a file for output
513 * - -EINVAL: invalid timer_data_id
516 rte_timer_alt_dump_stats(uint32_t timer_data_id, FILE *f);
522 #endif /* _RTE_TIMER_H_ */