xref: /f-stack/dpdk/lib/librte_timer/rte_timer.h (revision 8d76b62e)
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
45 extern "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  */
58 enum 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  */
67 union 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  */
80 struct 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 
88 struct rte_timer;
89 
90 /**
91  * Callback function type for timer expiry.
92  */
93 typedef 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  */
100 struct 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  * @warning
137  * @b EXPERIMENTAL: this API may change without prior notice
138  *
139  * Allocate a timer data instance in shared memory to track a set of pending
140  * timer lists.
141  *
142  * @param id_ptr
143  *   Pointer to variable into which to write the identifier of the allocated
144  *   timer data instance.
145  *
146  * @return
147  *   - 0: Success
148  *   - -ENOSPC: maximum number of timer data instances already allocated
149  */
150 __rte_experimental
151 int rte_timer_data_alloc(uint32_t *id_ptr);
152 
153 /**
154  * @warning
155  * @b EXPERIMENTAL: this API may change without prior notice
156  *
157  * Deallocate a timer data instance.
158  *
159  * @param id
160  *   Identifier of the timer data instance to deallocate.
161  *
162  * @return
163  *   - 0: Success
164  *   - -EINVAL: invalid timer data instance identifier
165  */
166 __rte_experimental
167 int rte_timer_data_dealloc(uint32_t id);
168 
169 /**
170  * Initialize the timer library.
171  *
172  * Initializes internal variables (list, locks and so on) for the RTE
173  * timer library.
174  *
175  * @note
176  *   This function must be called in every process before using the library.
177  *
178  * @return
179  *   - 0: Success
180  *   - -ENOMEM: Unable to allocate memory needed to initialize timer
181  *      subsystem
182  */
183 int rte_timer_subsystem_init(void);
184 
185 /**
186  * @warning
187  * @b EXPERIMENTAL: this API may change without prior notice
188  *
189  * Free timer subsystem resources.
190  */
191 __rte_experimental
192 void rte_timer_subsystem_finalize(void);
193 
194 /**
195  * Initialize a timer handle.
196  *
197  * The rte_timer_init() function initializes the timer handle *tim*
198  * for use. No operations can be performed on a timer before it is
199  * initialized.
200  *
201  * @param tim
202  *   The timer to initialize.
203  */
204 void rte_timer_init(struct rte_timer *tim);
205 
206 /**
207  * Reset and start the timer associated with the timer handle.
208  *
209  * The rte_timer_reset() function resets and starts the timer
210  * associated with the timer handle *tim*. When the timer expires after
211  * *ticks* HPET cycles, the function specified by *fct* will be called
212  * with the argument *arg* on core *tim_lcore*.
213  *
214  * If the timer associated with the timer handle is already running
215  * (in the RUNNING state), the function will fail. The user has to check
216  * the return value of the function to see if there is a chance that the
217  * timer is in the RUNNING state.
218  *
219  * If the timer is being configured on another core (the CONFIG state),
220  * it will also fail.
221  *
222  * If the timer is pending or stopped, it will be rescheduled with the
223  * new parameters.
224  *
225  * @param tim
226  *   The timer handle.
227  * @param ticks
228  *   The number of cycles (see rte_get_hpet_hz()) before the callback
229  *   function is called.
230  * @param type
231  *   The type can be either:
232  *   - PERIODICAL: The timer is automatically reloaded after execution
233  *     (returns to the PENDING state)
234  *   - SINGLE: The timer is one-shot, that is, the timer goes to a
235  *     STOPPED state after execution.
236  * @param tim_lcore
237  *   The ID of the lcore where the timer callback function has to be
238  *   executed. If tim_lcore is LCORE_ID_ANY, the timer library will
239  *   launch it on a different core for each call (round-robin).
240  * @param fct
241  *   The callback function of the timer.
242  * @param arg
243  *   The user argument of the callback function.
244  * @return
245  *   - 0: Success; the timer is scheduled.
246  *   - (-1): Timer is in the RUNNING or CONFIG state.
247  */
248 int rte_timer_reset(struct rte_timer *tim, uint64_t ticks,
249 		    enum rte_timer_type type, unsigned tim_lcore,
250 		    rte_timer_cb_t fct, void *arg);
251 
252 /**
253  * Loop until rte_timer_reset() succeeds.
254  *
255  * Reset and start the timer associated with the timer handle. Always
256  * succeed. See rte_timer_reset() for details.
257  *
258  * @param tim
259  *   The timer handle.
260  * @param ticks
261  *   The number of cycles (see rte_get_hpet_hz()) before the callback
262  *   function is called.
263  * @param type
264  *   The type can be either:
265  *   - PERIODICAL: The timer is automatically reloaded after execution
266  *     (returns to the PENDING state)
267  *   - SINGLE: The timer is one-shot, that is, the timer goes to a
268  *     STOPPED state after execution.
269  * @param tim_lcore
270  *   The ID of the lcore where the timer callback function has to be
271  *   executed. If tim_lcore is LCORE_ID_ANY, the timer library will
272  *   launch it on a different core for each call (round-robin).
273  * @param fct
274  *   The callback function of the timer.
275  * @param arg
276  *   The user argument of the callback function.
277  *
278  * @note
279  *   This API should not be called inside a timer's callback function to
280  *   reset another timer; doing so could hang in certain scenarios. Instead,
281  *   the rte_timer_reset() API can be called directly and its return code
282  *   can be checked for success or failure.
283  */
284 void
285 rte_timer_reset_sync(struct rte_timer *tim, uint64_t ticks,
286 		     enum rte_timer_type type, unsigned tim_lcore,
287 		     rte_timer_cb_t fct, void *arg);
288 
289 /**
290  * Stop a timer.
291  *
292  * The rte_timer_stop() function stops the timer associated with the
293  * timer handle *tim*. It may fail if the timer is currently running or
294  * being configured.
295  *
296  * If the timer is pending or stopped (for instance, already expired),
297  * the function will succeed. The timer handle tim must have been
298  * initialized using rte_timer_init(), otherwise, undefined behavior
299  * will occur.
300  *
301  * This function can be called safely from a timer callback. If it
302  * succeeds, the timer is not referenced anymore by the timer library
303  * and the timer structure can be freed (even in the callback
304  * function).
305  *
306  * @param tim
307  *   The timer handle.
308  * @return
309  *   - 0: Success; the timer is stopped.
310  *   - (-1): The timer is in the RUNNING or CONFIG state.
311  */
312 int rte_timer_stop(struct rte_timer *tim);
313 
314 /**
315  * Loop until rte_timer_stop() succeeds.
316  *
317  * After a call to this function, the timer identified by *tim* is
318  * stopped. See rte_timer_stop() for details.
319  *
320  * @param tim
321  *   The timer handle.
322  *
323  * @note
324  *   This API should not be called inside a timer's callback function to
325  *   stop another timer; doing so could hang in certain scenarios. Instead, the
326  *   rte_timer_stop() API can be called directly and its return code can
327  *   be checked for success or failure.
328  */
329 void rte_timer_stop_sync(struct rte_timer *tim);
330 
331 /**
332  * Test if a timer is pending.
333  *
334  * The rte_timer_pending() function tests the PENDING status
335  * of the timer handle *tim*. A PENDING timer is one that has been
336  * scheduled and whose function has not yet been called.
337  *
338  * @param tim
339  *   The timer handle.
340  * @return
341  *   - 0: The timer is not pending.
342  *   - 1: The timer is pending.
343  */
344 int rte_timer_pending(struct rte_timer *tim);
345 
346 /**
347  * Manage the timer list and execute callback functions.
348  *
349  * This function must be called periodically from EAL lcores
350  * main_loop(). It browses the list of pending timers and runs all
351  * timers that are expired.
352  *
353  * The precision of the timer depends on the call frequency of this
354  * function. However, the more often the function is called, the more
355  * CPU resources it will use.
356  *
357  * @return
358  *   - 0: Success
359  *   - -EINVAL: timer subsystem not yet initialized
360  */
361 int rte_timer_manage(void);
362 
363 /**
364  * Dump statistics about timers.
365  *
366  * @param f
367  *   A pointer to a file for output
368  * @return
369  *   - 0: Success
370  *   - -EINVAL: timer subsystem not yet initialized
371  */
372 int rte_timer_dump_stats(FILE *f);
373 
374 /**
375  * @warning
376  * @b EXPERIMENTAL: this API may change without prior notice
377  *
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.
381  *
382  * @see rte_timer_reset()
383  *
384  * @param timer_data_id
385  *   An identifier indicating which instance of timer data should be used for
386  *   this operation.
387  * @param tim
388  *   The timer handle.
389  * @param ticks
390  *   The number of cycles (see rte_get_hpet_hz()) before the callback
391  *   function is called.
392  * @param type
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.
398  * @param tim_lcore
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).
402  * @param fct
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.
405  * @param arg
406  *   The user argument of the callback function.
407  * @return
408  *   - 0: Success; the timer is scheduled.
409  *   - (-1): Timer is in the RUNNING or CONFIG state.
410  *   - -EINVAL: invalid timer_data_id
411  */
412 __rte_experimental
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  * @warning
420  * @b EXPERIMENTAL: this API may change without prior notice
421  *
422  * This function is the same as rte_timer_stop(), except that it allows a
423  * caller to specify the rte_timer_data instance containing the list from which
424  * this timer should be removed.
425  *
426  * @see rte_timer_stop()
427  *
428  * @param timer_data_id
429  *   An identifier indicating which instance of timer data should be used for
430  *   this operation.
431  * @param tim
432  *   The timer handle.
433  * @return
434  *   - 0: Success; the timer is stopped.
435  *   - (-1): The timer is in the RUNNING or CONFIG state.
436  *   - -EINVAL: invalid timer_data_id
437  */
438 __rte_experimental
439 int
440 rte_timer_alt_stop(uint32_t timer_data_id, struct rte_timer *tim);
441 
442 /**
443  * Callback function type for rte_timer_alt_manage().
444  */
445 typedef void (*rte_timer_alt_manage_cb_t)(struct rte_timer *tim);
446 
447 /**
448  * @warning
449  * @b EXPERIMENTAL: this API may change without prior notice
450  *
451  * Manage a set of timer lists and execute the specified callback function for
452  * all expired timers. This function is similar to rte_timer_manage(), except
453  * that it allows a caller to specify the timer_data instance that should
454  * be operated on, as well as a set of lcore IDs identifying which timer lists
455  * should be processed.  Callback functions of individual timers are ignored.
456  *
457  * @see rte_timer_manage()
458  *
459  * @param timer_data_id
460  *   An identifier indicating which instance of timer data should be used for
461  *   this operation.
462  * @param poll_lcores
463  *   An array of lcore ids identifying the timer lists that should be processed.
464  *   NULL is allowed - if NULL, the timer list corresponding to the lcore
465  *   calling this routine is processed (same as rte_timer_manage()).
466  * @param n_poll_lcores
467  *   The size of the poll_lcores array. If 'poll_lcores' is NULL, this parameter
468  *   is ignored.
469  * @param f
470  *   The callback function which should be called for all expired timers.
471  * @return
472  *   - 0: success
473  *   - -EINVAL: invalid timer_data_id
474  */
475 __rte_experimental
476 int
477 rte_timer_alt_manage(uint32_t timer_data_id, unsigned int *poll_lcores,
478 		     int n_poll_lcores, rte_timer_alt_manage_cb_t f);
479 
480 /**
481  * Callback function type for rte_timer_stop_all().
482  */
483 typedef void (*rte_timer_stop_all_cb_t)(struct rte_timer *tim, void *arg);
484 
485 /**
486  * @warning
487  * @b EXPERIMENTAL: this API may change without prior notice
488  *
489  * Walk the pending timer lists for the specified lcore IDs, and for each timer
490  * that is encountered, stop it and call the specified callback function to
491  * process it further.
492  *
493  * @param timer_data_id
494  *   An identifier indicating which instance of timer data should be used for
495  *   this operation.
496  * @param walk_lcores
497  *   An array of lcore ids identifying the timer lists that should be processed.
498  * @param nb_walk_lcores
499  *   The size of the walk_lcores array.
500  * @param f
501  *   The callback function which should be called for each timers. Can be NULL.
502  * @param f_arg
503  *   An arbitrary argument that will be passed to f, if it is called.
504  * @return
505  *   - 0: success
506  *   - EINVAL: invalid timer_data_id
507  */
508 __rte_experimental
509 int
510 rte_timer_stop_all(uint32_t timer_data_id, unsigned int *walk_lcores,
511 		   int nb_walk_lcores, rte_timer_stop_all_cb_t f, void *f_arg);
512 
513 /**
514  * @warning
515  * @b EXPERIMENTAL: this API may change without prior notice
516  *
517  * This function is the same as rte_timer_dump_stats(), except that it allows
518  * the caller to specify the rte_timer_data instance that should be used.
519  *
520  * @see rte_timer_dump_stats()
521  *
522  * @param timer_data_id
523  *   An identifier indicating which instance of timer data should be used for
524  *   this operation.
525  * @param f
526  *   A pointer to a file for output
527  * @return
528  *   - 0: success
529  *   - -EINVAL: invalid timer_data_id
530  */
531 __rte_experimental
532 int
533 rte_timer_alt_dump_stats(uint32_t timer_data_id, FILE *f);
534 
535 #ifdef __cplusplus
536 }
537 #endif
538 
539 #endif /* _RTE_TIMER_H_ */
540