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