EM-ODP 4.4.0
Event Machine on ODP
Loading...
Searching...
No Matches
api/event_machine_timer.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2016-2026, Nokia Solutions and Networks
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * * Neither the name of the copyright holder nor the names of its
15 * contributors may be used to endorse or promote products derived
16 * from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30#ifndef EVENT_MACHINE_TIMER_H_
31#define EVENT_MACHINE_TIMER_H_
32
33#pragma GCC visibility push(default)
34
35/**
36 * @file
37 * Event Machine timer
38 * @defgroup em_timer Event timer
39 * Event Machine timer
40 * @{
41 *
42 * The timer API can be used to request an event to be sent to a specified
43 * queue at a specified time once (one-shot) or at regular intervals (periodic).
44 * A timer needs to be created first - it represents a collection of timeouts
45 * with certain attributes (e.g. timeout resolution and maximum period).
46 * A timer can be mapped to a HW resource on an SoC, thus the number of timers,
47 * capabilities and time bases are system specific. Typically only a few timers
48 * are supported.
49 * The application can specify required capabilities when a timer is created.
50 * The creation will fail if the implementation cannot fulfill the required
51 * values. Timers are typically created once at system startup.
52 *
53 * A timer is a shared resource with proper synchronization for concurrent
54 * multi-thread use. It is possible to exclude all multi-thread protections if a
55 * timer is used exclusively by a single thread (for potential performance
56 * gains). This is done by setting EM_TIMER_FLAG_PRIVATE when creating a timer.
57 * Setting this flag means that the application must ensure that only a single
58 * thread is using the timer (this also includes the receiver of periodic
59 * timeouts due to the ack-functionality). This private-mode is not necessarily
60 * implemented on all systems, in which case the flag is ignored as it will not
61 * cause any functional difference.
62 *
63 * Timeouts (tmo) can be created once a timer exists. Creating a timeout
64 * allocates the resources needed to serve the timeout, but does not arm it.
65 * This makes it possible to pre-create timeout(s) and set the expiry
66 * later at runtime. This can improve performance but also minimizes the
67 * possibility that the runtime call setting the expiry would fail, as resources
68 * have already been reserved beforehand.
69 *
70 * A pending timeout can be cancelled. Note that there is no way to cancel an
71 * expired timeout for which the event has already been sent but not yet
72 * received by the application. Canceling in this case will return an error
73 * to enable the application to detect the situation. For a periodic timer,
74 * a cancel will stop further timeouts, but may not be able to prevent the
75 * latest event from being received. An active timeout cannot be altered without
76 * canceling it first.
77 *
78 * A timeout can be reused after the timeout event has been received or when
79 * successfully cancelled. Timeouts need to be deleted after use. Deletion frees
80 * the resources reserved during creation.
81 *
82 * The timeout value is an abstract system and timer dependent tick count.
83 * It is assumed that the tick count increases with a static frequency.
84 * The frequency can be inquired at runtime for time calculations, e.g. tick
85 * frequency divided by 1000 gives ticks for 1ms. The tick frequency is at least
86 * equal to the resolution, but can also be higher (implementation can quantize
87 * ticks to any underlying implementation). The supported resolution can also be
88 * inquired.
89 * A clock source can be specified when creating a timer. It defines the time
90 * base of the timer for systems with multiple sources implemented (optional).
91 * EM_TIMER_CLKSRC_DEFAULT is a portable value that implements a basic
92 * monotonic time, that will not wrap back to zero in any reasonable uptime.
93 *
94 * Events with major event types EM_EVENT_TYPE_SW, EM_EVENT_TYPE_PACKET and
95 * EM_EVENT_TYPE_TIMER can be used as timeout events to indicate expiry. The
96 * type EM_EVENT_TYPE_TIMER is an alternative to EM_EVENT_TYPE_SW and works the
97 * same way. Additionally, for periodic ring timer only, the type
98 * EM_EVENT_TYPE_TIMER_IND is used. This is a special timeout indication event
99 * without visible payload.
100 *
101 * Regular periodic timeouts:
102 * (i.e. NOT periodic ring timer timeouts, see differences further down)
103 * A periodic timer requires the application to acknowledge each received
104 * timeout event after it has been processed. The acknowledgment activates the
105 * next timeout and compensates for the processing delay to keep the original
106 * interval. This creates a flow control mechanism and also protects the event
107 * handling from races if the same event is reused every time - the next
108 * timeout will not be sent before the previous has been acknowledged.
109 * The event to be received for each periodic timeout can also be different as
110 * the next event is given by the application via the acknowledgment.
111 * The target queue cannot be modified after the timeout has been created.
112 *
113 * If the acknowledgment of a periodic timeout is done too late (after the next
114 * period has already passed), the default action is to skip the missed timeout
115 * slot(s) and arm for the next valid slot. If the application never wants to
116 * skip a missed timeout it can set the flag EM_TMO_FLAG_NOSKIP when creating a
117 * timeout. This causes each acknowledgment to schedule an immediate timeout
118 * event until all the missed time slots have been served. This keeps the number
119 * of timeouts as expected but may cause an event storm if a long processing
120 * delay has occurred.
121 *
122 * The timeout handle is needed when acknowledging a periodic timeout event.
123 * Because any event can be used for the timeout, the application must itself
124 * provide a way to derive the timeout handle from the received timeout event.
125 * A typical way is to include the tmo handle within the timeout event.
126 * The application also needs to have a mechanism to detect which event is a
127 * periodic timeout to be able to acknowledge it via em_tmo_ack().
128 *
129 * If the requested timeout tick value for a timeout is in the past or is too
130 * close to the current time then the error code EM_ERR_TOONEAR is returned.
131 * In this case EM will not call the error handler - instead EM lets the
132 * application decide whether to treat the situation as an error or to try again
133 * with an updated target time.
134 *
135 * Periodic ring timer:
136 * There is also an alternative periodic ring timer. It uses a different
137 * abstraction and is created and started via separate ring specific APIs.
138 * It has three main differences to the regular periodic timeouts:
139 * 1. Only a pre-defined read-only event type can be used and is provided
140 * by the timer (EM_EVENT_TYPE_TIMER_IND).
141 * 2. Flow control is optional. Set em_timer_attr_t::max_pending_events to
142 * enable it (check supported range via em_timer_capability()). Without
143 * flow control, the user needs to be prepared to see the same event
144 * enqueued multiple times if handling of the received timeouts is not
145 * fast enough.
146 * 3. A limited set of period times are supported per timer (the base rate or
147 * an integer multiple thereof).
148 *
149 * Ring timers can be thought of as a clock face ticking the pointer forward.
150 * One cycle around is the base rate (minimum rate). The same timeout can be
151 * inserted into multiple locations evenly spread within the clock face thus
152 * multiplying the base rate. The starting offset can be adjusted only up to
153 * one timeout period.
154 * Depending on platform, this mode may provide better integration with HW and
155 * thus have less runtime overhead. However, as it exposes a potential queue
156 * overflow and a race hazard (race avoidable by using atomic queue as target),
157 * regular periodic timeouts are recommended as a default.
158 *
159 * Example usage
160 * @code
161 *
162 * // This would typically be done at application init.
163 * // Accept all defaults but change the name
164 * em_timer_attr_t attr;
165 * em_timer_attr_init(&attr);
166 * strncpy(attr.name, "myTimer", EM_TIMER_NAME_LEN);
167 * em_timer_t tmr = em_timer_create(&attr);
168 * if(tmr == EM_TIMER_UNDEF) {
169 * // handle error here or via the error handler
170 * }
171 *
172 * // At runtime - create a timeout resource.
173 * // Can be done in advance to save time if the target queue is known.
174 * em_tmo_t tmo = em_tmo_create(tmr, EM_TIMER_FLAG_ONESHOT, target_queue);
175 * if(tmo == EM_TMO_UNDEF) {
176 * // no such timer or out of resources
177 * // handle error here or via error handler
178 * }
179 *
180 * // Get the timer tick frequency
181 * uint64_t hz = em_timer_freq(tmr);
182 *
183 * // Activate a 10ms timeout from now.
184 * // Very unlikely to fail with valid arguments.
185 * if (em_tmo_set_rel(tmo, hz / 100, my_tmo_event) != EM_OK) {
186 * // handle error here or via error handler
187 * }
188 *
189 * @endcode
190 *
191 */
192#include <inttypes.h>
193
198
199#ifdef __cplusplus
200extern "C" {
201#endif
202
203/**
204 * @typedef em_timer_t
205 * System specific type for a timer handle.
206 */
207
208/**
209 * @typedef em_tmo_t
210 * System specific type for a timeout handle.
211 */
212
213/**
214 * @typedef em_timer_flag_t
215 * System specific type for timer flags.
216 * This is system specific, but all implementations must define
217 * EM_TIMER_FLAG_DEFAULT and EM_TIMER_FLAG_PRIVATE, of which the latter is used
218 * to skip API synchronization for single threaded apps.
219 * Flags can be combined by bitwise OR.
220 */
221
222/**
223 * @typedef em_tmo_flag_t
224 * System specific enum type for timeout flags.
225 * This is system specific, but all implementations must define
226 * EM_TMO_FLAG_ONESHOT, EM_TMO_FLAG_PERIODIC and EM_TMO_FLAG_NOSKIP.
227 * Flags can be combined by bitwise OR.
228 */
229
230/**
231 * @typedef em_timer_clksrc_t
232 * System specific enum type for timer clock source.
233 * This is system specific, but all implementations must define
234 * EM_TIMER_CLKSRC_DEFAULT.
235 */
236
237/**
238 * Visible state of a timeout
239 */
240typedef enum em_tmo_state_t {
241 EM_TMO_STATE_UNKNOWN = 0,
242 EM_TMO_STATE_IDLE = 1, /**< just created or canceled */
243 EM_TMO_STATE_ACTIVE = 2, /**< armed */
244 EM_TMO_STATE_INACTIVE = 3 /**< unused state */
246
247/**
248 * Type returned by em_tmo_type()
249 */
250typedef enum em_tmo_type_t {
251 EM_TMO_TYPE_NONE = 0, /**< unknown or not a timer-related event */
252 EM_TMO_TYPE_ONESHOT = 1, /**< event is a oneshot timeout indication */
253 EM_TMO_TYPE_PERIODIC = 2, /**< event is a periodic timeout indication */
255
256/**
257 * The timer tick has HW and timer specific meaning, but the type is always a
258 * 64-bit integer and is normally assumed to be monotonic and not to wrap
259 * around. Exceptions with exotic extra timers should be clearly documented.
260 */
261typedef uint64_t em_timer_tick_t;
262
263/**
264 * Fractional 64-bit unsigned value for timer frequency.
265 */
266typedef struct em_fract_u64_t {
267 /** Int */
268 uint64_t integer;
269
270 /** Numerator. Set 0 for integers */
271 uint64_t numer;
272
273 /** Denominator */
274 uint64_t denom;
276
277/**
278 * Type for timer resolution parameters.
279 *
280 * This structure is used to group timer resolution parameters that may affect
281 * each other. All time values are in nanoseconds (ns).
282 *
283 * @note This type used both as capability and configuration. When used as
284 * configuration either res_ns or res_hz must be 0 (for em_timer_create()).
285 * @see em_timer_capability(), em_timer_create()
286 */
287typedef struct em_timer_res_param_t {
288 /** Clock source (system specific) */
289 em_timer_clksrc_t clk_src;
290 /** resolution, ns */
291 uint64_t res_ns;
292 /** resolution, hz */
293 uint64_t res_hz;
294 /** minimum timeout, ns */
295 uint64_t min_tmo;
296 /** maximum timeout, ns */
297 uint64_t max_tmo;
299
300/**
301 * Periodic timer ring timing parameters.
302 */
303typedef struct em_timer_ring_param_t {
304 /** Clock source (system specific) */
305 em_timer_clksrc_t clk_src;
306 /** Base rate, i.e. minimum period rate */
308 /** Maximum base rate multiplier needed. 1 for single rate = base_hz */
309 uint64_t max_mul;
310 /** Resolution */
311 uint64_t res_ns;
313
314/**
315 * Periodic timer ring frequency parameters.
316 */
318 /** Clock source (system specific) */
319 em_timer_clksrc_t clk_src;
320 /**
321 * Array of constraining frequencies (ascending).
322 *
323 * Ownership: as passed to em_timer_ring_freq_attr_init() and
324 * em_timer_ring_freq_create() this pointer is caller-owned and must
325 * remain valid until em_timer_ring_freq_create() returns. The array
326 * contents may be updated in-place by the implementation to reflect
327 * the closest supported values.
328 *
329 * When returned by em_timer_attr() the pointer refers to
330 * implementation-internal read-only storage that is valid until the
331 * timer is deleted with em_timer_delete(); do not modify or free it.
332 */
334 /** Number of items in freq_hz */
336 /** Resolution */
339
340/**
341 * EM timer attributes.
342 *
343 * The type is used when creating a timer or inquiring its configuration later.
344 *
345 * This needs to be initialized with em_timer_attr_init(), which fills default
346 * values to each field. After that the values can be modified as needed.
347 * Values set are considered a requirement, e.g. setting 'resparam.res_ns' to
348 * 1000(ns) requires the timer to have at least 1us resolution. The timer
349 * creation will fail if the implementation cannot support such a resolution
350 * (e.g. if it only goes down to 1500ns).
351 * The implementation is free to provide better than requested, but not worse.
352 *
353 * To know the implementation specific limits, use em_timer_capability() and
354 * em_timer_res_capability().
355 *
356 * When creating the alternative periodic ring timer, this type needs to be
357 * initialized with em_timer_ring_attr_init() instead. EM_TIMER_FLAG_RING will
358 * be set by em_timer_ring_attr_init() so it does not need to be manually set.
359 *
360 * @see em_timer_attr_init(), em_timer_create(),
361 * em_timer_ring_attr_init(), em_timer_ring_create(),
362 * em_timer_attr_init(), em_timer_attr()
363 */
364typedef struct em_timer_attr_t {
365 /**
366 * Resolution parameters for em_timer_create().
367 * Used when creating normal one shot or periodic timers, but not when
368 * creating periodic ring timers (see ringparam below instead).
369 * (cleared by em_timer_ring_attr_init() when using a ring timer)
370 */
372
373 /** Maximum simultaneous timeouts */
374 uint32_t num_tmo;
375 /** Extra flags. A set flag is a requirement */
377 /** Optional name for this timer */
378 char name[EM_TIMER_NAME_LEN];
379
380 /**
381 * Timer priority.
382 *
383 * Timeouts from a higher priority timer are served with priority over
384 * timeouts from a lower priority timer. The prioritization algorithm
385 * is implementation specific. Lower priority timeouts may get delayed
386 * due to higher priority timeout processing. Valid values range from
387 * zero to 'em_timer_capability_t::max_priority' (or
388 * 'em_timer_capability_t::ring.max_priority' for ring timers).
389 * The default value is zero (lowest priority).
390 */
391 uint16_t priority;
392 /**
393 * Parameters specifically for em_timer_ring_create().
394 * Used when creating an alternative periodic ring timer.
395 * (cleared by em_timer_attr_init() since not needed in that case)
396 */
398 /**
399 * Parameters specifically for em_timer_ring_freq_create().
400 * Used when creating an alternative periodic ring timer with frequency
401 * list.
402 * (cleared by em_timer_attr_init() since not needed in that case)
403 */
405 /**
406 * Maximum pending events for ring timer flow control.
407 *
408 * Only used for ring timers. Default value 0 means no flow control is
409 * used. Valid values for the max_pending_events can be asked with
410 * em_timer_capability() and are from
411 * 'em_timer_capability_t::ring.min_pending_events' to
412 * 'em_timer_capability_t::ring.max_pending_events'.
413 * 'em_timer_capability_t::ring.max_pending_events' == 0 means that flow
414 * control is not supported and this field must be left at 0.
415 * With flow control, the implementation will ensure that at most this
416 * many timeout events are pending in the target queue at any time.
417 * Without flow control, there is no limit to the number of pending
418 * timeouts. If flow control is requested but not supported, or
419 * requested values are out of range, an error is returned in the timer
420 * creation.
421 */
423 /**
424 * Internal check - don't touch!
425 *
426 * EM will verify that em_timer_attr_init() has been called before
427 * creating a timer
428 */
431
432/**
433 * Timeout statistics counters
434 *
435 * Some fields relate to periodic timeout only (0 on one-shots) and vice versa.
436 * New fields may be added later at the end.
437 */
438typedef struct em_tmo_stats_t {
439 /** number of periodic ack() calls */
440 uint64_t num_acks;
441 /** number of delayed periodic ack() calls. 0 with ring timer */
442 uint64_t num_late_ack;
443 /** number of skipped periodic timeslots due to late ack. 0 with ring timer */
446
447/**
448 * Timer capability info
449 */
450typedef struct em_timer_capability_t {
451 /** Number of supported timers of all types */
452 uint32_t max_timers;
453 /** Maximum number of simultaneous timeouts. 0 means only limited by memory */
454 uint32_t max_num_tmo;
455 /** Highest supported resolution and related limits for a timeout */
457 /** Longest supported timeout and related resolution */
459 /** Maximum priority for timer */
460 uint16_t max_priority;
461
462 /** alternate periodic ring */
463 struct {
464 /** Support flags for periodic ring types */
465 struct {
466 /** Support for base multiplier type */
467 uint32_t base_mul : 1;
468 /** Support for frequency list type */
469 uint32_t freq : 1;
471 /** Maximum ring timers */
472 uint32_t max_rings;
473 /** Maximum simultaneous ring timeouts */
474 uint32_t max_num_tmo;
475 /** Maximum priority for ring timers */
476 uint16_t max_priority;
477 /**
478 * Minimum base_hz for base_mul ring timers.
479 * Valid only when 'support.base_mul' is set, otherwise zero.
480 */
482 /**
483 * Maximum base_hz for base_mul ring timers.
484 * Valid only when 'support.base_mul' is set, otherwise zero.
485 */
487 /**
488 * Minimum allowed value for
489 * 'em_timer_attr.max_pending_events'. Meaningful only
490 * when ring.max_pending_events > 0 (flow control supported).
491 */
493 /**
494 * Maximum pending events for ring timer flow control
495 * 'em_timer_attr.max_pending_events'. 0 means that
496 * flow control is not supported.
497 */
499 /**
500 * Minimum frequency for PERIODIC_FREQ ring timers.
501 * Valid only when 'support.freq' is set, otherwise zero.
502 */
504 /**
505 * Maximum frequency for PERIODIC_FREQ ring timers.
506 * Valid only when 'support.freq' is set, otherwise zero.
507 */
510
512
513/**
514 * tmo optional extra arguments
515 *
516 */
517typedef struct em_tmo_args_t {
518 /** can be used with ring timer, see em_tmo_userptr() */
519 void *userptr;
521
522/**
523 * Initialize em_timer_attr_t for normal timers (i.e. NOT periodic ring timers).
524 *
525 * Initializes em_timer_attr_t to system specific default values.
526 * The user can after initialization adjust the values as needed before
527 * calling em_timer_create(). The functions em_timer_capability() and/or
528 * em_timer_res_capability() can optionally be used to find valid values.
529 *
530 * Always initialize em_timer_attr_t with em_timer_attr_init() before use.
531 *
532 * The ring timer specific fields 'ringparam' and 'freqparam' are zeroed by
533 * this call since they are not used by em_timer_create(). For ring timers,
534 * use em_timer_ring_attr_init() or em_timer_ring_freq_attr_init() instead.
535 *
536 * This function will not trigger EM error handler calls internally.
537 *
538 * Example for all defaults
539 * @code
540 * em_timer_attr_t tmr_attr;
541 * em_timer_attr_init(&tmr_attr);
542 * em_timer_t tmr = em_timer_create(&tmr_attr);
543 * @endcode
544 *
545 * @param[out] tmr_attr Pointer to em_timer_attr_t to be initialized
546 *
547 * @see em_timer_capability, em_timer_create
548 */
549void em_timer_attr_init(em_timer_attr_t *tmr_attr);
550
551/**
552 * Initialize em_timer_attr_t for periodic ring timers.
553 *
554 * Initializes em_timer_attr_t according to given values.
555 * After successful return, the attributes can be given to em_timer_ring_create().
556 * Note, that if the implementation cannot use the exact given combination it may
557 * update the ring_attr values, but always to meet or exceed the given values.
558 * The user can read the new values to determine if they were modified.
559 * An error is returned if the given values cannot be met.
560 *
561 * Before creating the ring timer, other values like num_tmo, name and
562 * max_pending_events can be adjusted as needed. Also, if a non-integer
563 * frequency is needed, the base_hz fractional part can be adjusted before
564 * em_timer_ring_create().
565 *
566 * On successful return ring_attr is initialized with:
567 * - flags = EM_TIMER_FLAG_RING
568 * - ringparam = { clk_src, base_hz (integer only), max_mul, res_ns }
569 * (values may be lowered by the implementation to fit
570 * capability limits; res_ns == 0 means ODP default)
571 * - num_tmo = EM_ODP_DEFAULT_RING_TMOS, clamped down to
572 * capability max if smaller
573 * - name = "" (em_timer_ring_create() assigns a default name)
574 * - priority = 0
575 * - max_pending_events = 0 (no flow control)
576 * - resparam = zeroed (not used by ring timers)
577 *
578 * This function will not trigger error handler calls.
579 *
580 * @param[out] ring_attr Pointer to em_timer_attr_t to be initialized
581 * @param clk_src Clock source to use (system specific or portable
582 * EM_TIMER_CLKSRC_DEFAULT)
583 * @param base_hz Base rate of the ring (minimum rate i.e. longest period)
584 * @param max_mul Maximum multiplier (maximum rate = base_hz * max_mul)
585 * @param res_ns Required resolution of the timer or 0 to accept default
586 *
587 * @return EM_OK if the given clk_src and other values are supported
588 *
589 * @see em_timer_ring_capability(), em_timer_ring_create()
590 */
592 em_timer_clksrc_t clk_src,
593 uint64_t base_hz,
594 uint64_t max_mul,
595 uint64_t res_ns);
596
597/**
598 * Initialize em_timer_attr_t for frequency-based periodic ring timers.
599 *
600 * Initializes em_timer_attr_t for use with em_timer_ring_freq_create().
601 * Unlike em_timer_ring_attr_init() which uses a base frequency and multiplier,
602 * this function takes an array of constraining frequencies that define the
603 * allowed periodic timer frequency range for the pool.
604 *
605 * The 'freq_hz' array defines constraining frequencies in ascending order.
606 * Timer frequencies requested later (via em_tmo_set_periodic_ring_freq()) must
607 * be within the range from freq_hz[0] (minimum) to freq_hz[num - 1]
608 * (maximum). Frequencies not present in the array may also be requested but
609 * may suffer from inaccuracies if not exactly compatible with the constraining
610 * frequencies.
611 *
612 * Note, that if the implementation cannot use the exact given combination the
613 * freq_hz array entries may be updated in-place with the closest supported
614 * values. An error is returned if the given values cannot be met.
615 *
616 * Before creating the ring timer, other values like num_tmo, name, priority
617 * and max_pending_events can be adjusted as needed.
618 *
619 * On successful return ring_attr is initialized with:
620 * - flags = EM_TIMER_FLAG_RING_FREQ
621 * - freqparam = { clk_src, freq_hz, num, res_ns }
622 * (res_ns may be updated by the implementation; 0
623 * means ODP default. freq_hz array stays owned by
624 * the caller and must remain valid until
625 * em_timer_ring_freq_create() returns.)
626 * - num_tmo = EM_ODP_DEFAULT_RING_TMOS, clamped down to
627 * capability max if smaller
628 * - name = "" (em_timer_ring_freq_create() assigns a default)
629 * - priority = 0
630 * - max_pending_events = 0 (no flow control)
631 * - ringparam, resparam = zeroed (not used by freq-based ring timers)
632 *
633 * This function will not trigger error handler calls.
634 *
635 * @param[out] ring_attr Pointer to em_timer_attr_t to be initialized
636 * @param clk_src Clock source to use (system specific or portable
637 * EM_TIMER_CLKSRC_DEFAULT)
638 * @param[in,out] freq_hz Array of constraining frequencies in hertz
639 * (ascending order). May be updated in-place if the
640 * implementation adjusts values.
641 * @param num Number of items in 'freq_hz' array (must be >= 1)
642 * @param res_ns Required resolution in ns or 0 to accept default
643 *
644 * @return EM_OK if the given clk_src and other values are supported
645 *
646 * @see em_timer_ring_freq_capability(), em_timer_ring_freq_create()
647 */
649 em_timer_clksrc_t clk_src,
650 em_fract_u64_t *freq_hz,
651 uint32_t num,
652 uint64_t res_ns);
653
654/**
655 * Inquire timer capabilities
656 *
657 * Returns timer capabilities for the given clock source, which is also written
658 * to both 'capa->max_res.clk_src' and 'capa->max_tmo.clk_src'.
659 * For resolution both 'res_ns' and 'res_hz' are filled.
660 *
661 * This function will not trigger error handler calls internally.
662 *
663 * @param[out] capa pointer to em_timer_capability_t to be updated
664 * (does not need to be initialized)
665 * @param clk_src Clock source to use for timer
666 * (EM_TIMER_CLKSRC_DEFAULT for system specific default)
667 * @return EM_OK if the given clk_src is supported (capa updated)
668 *
669 * @see em_timer_capability_t, em_timer_res_capability
670 */
671em_status_t em_timer_capability(em_timer_capability_t *capa, em_timer_clksrc_t clk_src);
672
673/**
674 * Inquire timer capabilities for a specific resolution or maximum timeout
675 *
676 * Returns timer capabilities by the given resolution or maximum timeout.
677 * Set either the resolution (res.res_ns) or the maximum timeout (res.max_tmo)
678 * to the required value and the other to zero, and the function will fill the
679 * other fields with valid limits.
680 * An error is returned if the given value is not supported.
681 * The given clk_src is used to set the values and also written to 'res->clk_src'.
682 * Both 'res_ns' and 'res_hz' are filled, so if passed further to em_timer_create(),
683 * one of those must be set to 0.
684 *
685 * Example for external clock maximum resolution
686 * @code
687 * em_timer_attr_t *tmr_attr;
688 * em_timer_capability_t capa;
689 *
690 * em_timer_attr_init(&tmr_attr);
691 * if (em_timer_capability(&capa, EM_TIMER_CLKSRC_EXT) != EM_OK) {
692 * // external clock not supported
693 * }
694 * tmr_attr.resparam = capa.max_res;
695 * tmr_attr.resparam.res_hz = 0;
696 * tmr = em_timer_create(&tmr_attr);
697 * @endcode
698 *
699 * This function will not trigger error handler calls internally.
700 *
701 * @param[in,out] res Pointer to em_timer_res_param_t with one field set
702 * @param clk_src Clock source to use for timer
703 * (EM_TIMER_CLKSRC_DEFAULT for system specific default)
704 * @return EM_OK if the input value is supported (res updated)
705 *
706 * @see em_timer_capability
707 */
708em_status_t em_timer_res_capability(em_timer_res_param_t *res, em_timer_clksrc_t clk_src);
709
710/**
711 * @brief Check periodic ring timer capability.
712 *
713 * Returns the ring timer capability based on the given input values.
714 * The parameter 'ring' must be initialized with the values required by the user.
715 * The ring.res_ns can be 0 and gets replaced by the system default.
716 * The values are updated during the call. If EM_OK is returned then the
717 * combination of given values are all supported (or exceeded, e.g. better
718 * resolution), otherwise values are updated with the closest supported.
719 *
720 * As em_timer_ring_attr_init() only takes integer base_hz, this can also be
721 * used to verify valid values for modified fractional frequencies to avoid
722 * error handler calls from em_timer_ring_create().
723 *
724 * This function will not trigger error handler calls.
725 *
726 * @param[in,out] ring timer ring parameters to check
727 *
728 * @retval EM_OK Parameter combination is supported
729 * @retval EM_ERR_NOT_SUPPORTED Parameters not supported, values updated to closest
730 * @retval (other error) Unsupported arguments
731 */
733
734/**
735 * @brief Check frequency-based periodic ring timer capability.
736 *
737 * Returns the ring timer capability for the frequency-based periodic timer type
738 * (ODP_TIMER_TYPE_PERIODIC_FREQ). The parameter 'ring' must be initialized with
739 * the values required by the user. The ring->res_ns can be 0 and gets replaced
740 * by the system default.
741 *
742 * The ring->freq_hz array must contain the constraining frequencies to check,
743 * in ascending order. If EM_OK is returned, the given frequency combination is
744 * supported (or exceeded). If EM_ERR_NOT_SUPPORTED is returned, the freq_hz
745 * array entries are updated in-place with the closest supported values. The
746 * application can then inspect the modified values and decide whether to use
747 * them.
748 *
749 * This can be used to verify valid frequency values before calling
750 * em_timer_ring_freq_create() to avoid error handler calls.
751 *
752 * This function will not trigger error handler calls.
753 *
754 * @param[in,out] ring Frequency-based ring timer parameters to check.
755 * ring->freq_hz array may be updated in-place.
756 *
757 * @retval EM_OK Parameter combination is supported
758 * @retval EM_ERR_NOT_SUPPORTED Frequencies not exactly supported, closest
759 * values written to freq_hz array
760 * @retval (other error) Unsupported arguments
761 *
762 * @see em_timer_ring_freq_attr_init(), em_timer_ring_freq_create()
763 */
765
766/**
767 * Create and start a timer resource
768 *
769 * Required attributes are given via tmr_attr. The given structure must be
770 * initialized with em_timer_attr_init() before setting any field.
771 *
772 * Timer resolution can be given as time 'res_ns' or frequency 'res_hz'.
773 * The user must choose which one to use by setting the other one to 0.
774 *
775 * To use all defaults, initialize tmr_attr with em_timer_attr_init() and pass
776 * it as is to em_timer_create().
777 *
778 * @param tmr_attr Timer parameters to use, pointer to an initialized em_timer_attr_t
779 * @note NULL is no longer supported, pointer must be to an initialized em_timer_attr_t
780 *
781 * @return Timer handle on success or EM_TIMER_UNDEF on error
782 *
783 * @see em_timer_attr_init(), em_timer_capability()
784 */
785em_timer_t em_timer_create(const em_timer_attr_t *tmr_attr);
786
787/**
788 * Create and start a periodic timer ring (alternative periodic timer)
789 *
790 * The required attributes are given via ring_attr, which must have been
791 * initialized with em_timer_ring_attr_init() and optionally adjusted for the
792 * required timing constraints.
793 *
794 * A periodic ring timer is a bit different and will only send
795 * EM_EVENT_TYPE_TIMER_IND timeout events, which are automatically provided and
796 * cannot be modified. These events are allocated internally and do not carry
797 * any user data. User must not allocate or free these events.
798 *
799 * Example for 1ms ... 125us periodic ring timer (base 1000 hz, multiplier up to 8):
800 * @code
801 * em_timer_attr_t attr;
802 * if (em_timer_ring_attr_init(&attr, EM_TIMER_CLKSRC_DEFAULT, 1000, 8, 0) != EM_OK) {
803 * // given values not supported
804 * }
805 *
806 * em_timer_t tmr = em_timer_ring_create(&attr);
807 * if (tmr == EM_TIMER_UNDEF) {
808 * // handle error here or via error handler
809 * }
810 * @endcode
811 *
812 * ring_attr must have been initialized with em_timer_ring_attr_init().
813 * Errors are reported via the EM error handler under
814 * EM_ESCOPE_TIMER_RING_CREATE (e.g. invalid attr, unsupported clock source
815 * or priority, no free timer slot, ODP pool create/start failure).
816 *
817 * @param ring_attr Timer ring parameters to use
818 *
819 * @return Timer handle on success or EM_TIMER_UNDEF on error
820 *
821 * @see em_timer_ring_attr_init
822 */
823em_timer_t em_timer_ring_create(const em_timer_attr_t *ring_attr);
824
825/**
826 * Create and start a frequency-based periodic ring timer
827 *
828 * Creates a periodic ring timer using ODP_TIMER_TYPE_PERIODIC_FREQ. The
829 * required attributes are given via 'ring_attr', which must have been
830 * initialized with em_timer_ring_freq_attr_init() and optionally adjusted for
831 * the required timing constraints (num_tmo, name, priority, max_pending_events).
832 *
833 * Similar to em_timer_ring_create(), this timer only sends read-only
834 * EM_EVENT_TYPE_TIMER_IND timeout events that are automatically provided and
835 * cannot be modified. These events are allocated internally and do not carry
836 * any user data. The user must not allocate or free these events.
837 *
838 * Unlike the base_mul ring timer variant, the frequency-based ring timer
839 * allows requesting a specific frequency (in Hz) when activating a timeout
840 * via em_tmo_set_periodic_ring_freq(). The allowed frequencies are constrained
841 * by the freq_hz array given during attribute initialization.
842 *
843 * Example:
844 * @code
845 * em_timer_attr_t attr;
846 * em_fract_u64_t freqs[2] = {{.integer = 100}, {.integer = 10000}};
847 *
848 * if (em_timer_ring_freq_attr_init(&attr, EM_TIMER_CLKSRC_DEFAULT,
849 * freqs, 2, 0) != EM_OK) {
850 * // given values not supported
851 * }
852 *
853 * em_timer_t tmr = em_timer_ring_freq_create(&attr);
854 * if (tmr == EM_TIMER_UNDEF) {
855 * // handle error here or via error handler
856 * }
857 * @endcode
858 *
859 * ring_attr must have been initialized with em_timer_ring_freq_attr_init().
860 * Errors are reported via the EM error handler under
861 * EM_ESCOPE_TIMER_RING_FREQ_CREATE (e.g. invalid attr, unsupported clock
862 * source or priority, periodic-freq mode not supported by ODP, no free
863 * timer slot, ODP pool create/start failure).
864 *
865 * The em_timer_attr_init_t::freqparam.freq_hz array defines constraining
866 * frequencies for this timer. The requested frequency for a periodic timeout
867 * can be set with em_tmo_set_periodic_ring_freq() and must be within the range
868 * defined by the minimum and maximum frequencies in the freq_hz array.
869 * Frequencies not present in the array may also be requested but may suffer
870 * from inaccuracies if not exactly compatible with the constraining
871 * frequencies.
872 *
873 * @param ring_attr Timer ring parameters to use. Must have been initialized
874 * with em_timer_ring_freq_attr_init().
875 *
876 * @return Timer handle on success or EM_TIMER_UNDEF on error
877 *
878 * @see em_timer_ring_freq_attr_init(), em_timer_ring_freq_capability(),
879 * em_tmo_set_periodic_ring_freq()
880 */
881em_timer_t em_timer_ring_freq_create(const em_timer_attr_t *ring_attr);
882
883/**
884 * Stop and delete a timer
885 *
886 * Delete a timer, free all resources.
887 * All timeouts for this timer must have been cancelled and deleted first.
888 *
889 * @param tmr Timer handle
890 *
891 * @return EM_OK on success
892 */
893em_status_t em_timer_delete(em_timer_t tmr);
894
895/**
896 * Return the current tick value of the given timer
897 *
898 * This can be used for calculating absolute timeouts.
899 *
900 * @param tmr Timer handle
901 *
902 * @return Current time in timer specific ticks or 0 on non-existing timer
903 */
905
906/**
907 * Allocate a new timeout
908 *
909 * Create a new timeout. Allocates the necessary internal resources from the
910 * given timer and prepares for em_tmo_set_abs/rel/periodic().
911 *
912 * Scheduled queues are always supported as timeout event destinations. LOCAL or
913 * OUTPUT queues can not be used as timeout targets. Support for unscheduled
914 * queues is implementation specific.
915 *
916 * Flags are used to select functionality:
917 * - EM_TMO_FLAG_ONESHOT creates a one-shot timeout and
918 * - EM_TMO_FLAG_PERIODIC creates a periodic timeout.
919 * The flag EM_TMO_FLAG_NOSKIP can, in the periodic case, be 'OR':d into the
920 * flags to make the timeout acknowledgment never skip a missed timeout (the
921 * default is to skip missed time slots).
922 *
923 * The NOSKIP flag is ignored if used timer is a periodic timer ring.
924 *
925 * @param tmr Timer handle
926 * @param flags Functionality flags
927 * @param queue Target queue where the timeout event should be delivered
928 *
929 * @return Timeout handle on success or EM_TMO_UNDEF on failure
930 */
931em_tmo_t em_tmo_create(em_timer_t tmr, em_tmo_flag_t flags, em_queue_t queue);
932
933/**
934 * Allocate a new timeout with extra arguments
935 *
936 * Similar to em_tmo_create() but with an additional 'args' pointer. This API
937 * can be used with any timer type, but 'args->userptr' is only meaningful for
938 * ring timers using events of type EM_EVENT_TYPE_TIMER_IND that can carry a
939 * 'userptr'.
940 *
941 * @param tmr Timer handle
942 * @param flags Functionality flags
943 * @param queue Target queue where the timeout event should be delivered
944 * @param args Optional pointer holding extra arguments e.g. userptr for
945 * ring timers. NULL ok.
946 *
947 * @return Timeout handle on success or EM_TMO_UNDEF on failure
948 * @see em_tmo_create
949 */
950em_tmo_t em_tmo_create_arg(em_timer_t tmr, em_tmo_flag_t flags, em_queue_t queue,
951 em_tmo_args_t *args);
952
953/**
954 * Delete a timeout
955 *
956 * The deleted timeout must be inactive i.e. it must be successfully canceled or
957 * the last timeout event must have been received (following too late a cancel).
958 * A periodic or a periodic ring timeout can be deleted after a successful
959 * cancel or after em_tmo_ack()/em_tmo_ring_ack() returned EM_ERR_CANCELED.
960 * This indicates that the acknowledged timeout is canceled and that it was the
961 * last timeout event coming for that periodic timeout.
962 *
963 * After and during this call, the tmo handle is not valid anymore and must not
964 * be used by or passed to other timer APIs.
965 *
966 * @param tmo Timeout handle
967 *
968 * @return EM_OK on success
969 */
971
972/**
973 * Activate a oneshot timeout with absolute time.
974 *
975 * Activates a oneshot timeout to expire at a specific absolute time. The given
976 * timeout event will be sent to the queue given to em_tmo_create() when the
977 * timeout expires.
978 *
979 * It is not possible to send timeouts with an event group, but the application
980 * can assign the event group when receiving the timeout event, see
981 * em_event_group_assign().
982 *
983 * The timeout event should not be accessed after it has been given to the
984 * timer, similar to sending an event.
985 *
986 * Even if not guaranteed, the implementation should make sure that this call
987 * can fail only in exceptional situations (em_tmo_create() should pre-allocate
988 * needed resources).
989 *
990 * The allowed minimum and maximum timeouts can be inquired with
991 * em_timer_res_capability().
992 *
993 * An active timeout can not be modified. The timeout needs to be canceled and
994 * then set again with new arguments.
995 *
996 * An inactive timeout can be reused by calling em_tmo_set_abs/rel() again. The
997 * timeout becomes inactive after the oneshot timeout event has been received
998 * or after it has been successfully cancelled.
999 *
1000 * The return code EM_ERR_BUSY indicates that the timeout could not be activated
1001 * due to resource limitations. This can be a temporary situation and retrying
1002 * with the same or updated arguments will likely succeed.
1003 *
1004 * This function is for activating oneshot timeouts only. To activate
1005 * periodic timeouts use em_tmo_set_periodic() (or em_tmo_set_periodic_ring()).
1006 *
1007 * @param tmo Timeout handle
1008 * @param ticks_abs Expiration time in absolute timer specific ticks
1009 * @param tmo_ev Timeout event
1010 *
1011 * @retval EM_OK Success, event taken.
1012 * @retval EM_ERR_TOONEAR Failure, the tick value is in past or too close to
1013 * the current time. Error handler not called,
1014 * event not taken.
1015 * @retval EM_ERR_BUSY Failure, resources are busy. Error handler not
1016 * called, event not taken.
1017 * @retval (other_codes) Failure, event not taken.
1018 *
1019 * @see em_timer_res_capability()
1020 */
1022 em_event_t tmo_ev);
1023
1024/**
1025 * Activate a timeout with a relative time.
1026 *
1027 * Similar to em_tmo_set_abs(), but instead of an absolute time uses a timeout
1028 * value relative to the moment of the call.
1029 *
1030 * The return code EM_ERR_BUSY indicates that the timeout could not be activated
1031 * due to resource limitations. This can be a temporary situation and retrying
1032 * with the same or updated arguments will likely succeed.
1033 *
1034 * This function is for activating oneshot timeouts only. To activate
1035 * periodic timeouts use em_tmo_set_periodic() (or em_tmo_set_periodic_ring()).
1036 *
1037 * @param tmo Timeout handle
1038 * @param ticks_rel Expiration time in relative timer specific ticks
1039 * @param tmo_ev Timeout event handle
1040 *
1041 * @retval EM_OK Success, event taken.
1042 * @retval EM_ERR_TOONEAR Failure, the tick value is too low.
1043 * Error handler not called, event not taken.
1044 * @retval EM_ERR_BUSY Failure, resources are busy. Error handler not
1045 * called, event not taken.
1046 * @retval (other_codes) Failure, event not taken.
1047 *
1048 * @see em_tmo_set_abs(), em_tmo_set_periodic()
1049 */
1051 em_event_t tmo_ev);
1052
1053/**
1054 * Activate a periodic timeout
1055 *
1056 * Used to activate periodic timeouts. The first period can be different from
1057 * the repetitive period by providing an absolute start time.
1058 * Set 'start_abs' to 0 if the repetitive period can start from the moment of
1059 * the call.
1060 *
1061 * The timeout event will be sent to the queue given to em_tmo_create() when the
1062 * first timeout expires. The receiver then needs to call em_tmo_ack() to allow
1063 * the timer to send the next event for the following period.
1064 *
1065 * The return code EM_ERR_BUSY indicates that the timeout could not be activated
1066 * due to resource limitations. This can be a temporary situation and retrying
1067 * with the same or updated arguments will likely succeed.
1068 *
1069 * This function can only be used with periodic timeouts (created with flag
1070 * EM_TMO_FLAG_PERIODIC).
1071 *
1072 * @param tmo Timeout handle
1073 * @param start_abs Absolute start time (or 0 for period starting at call time)
1074 * @param period Period in timer specific ticks
1075 * @param tmo_ev Timeout event handle
1076 *
1077 * @retval EM_OK Success, event taken
1078 * @retval EM_ERR_TOONEAR Failure, the tick value is in past or too close to
1079 * the current time.
1080 * Error handler not called, event not taken.
1081 * @retval EM_ERR_BUSY Failure, resources are busy. Error handler not
1082 * called, event not taken.
1083 * @retval (other_codes) Failure, event not taken.
1084 *
1085 * @see em_tmo_ack()
1086 */
1088 em_timer_tick_t start_abs,
1089 em_timer_tick_t period,
1090 em_event_t tmo_ev);
1091
1092/**
1093 * Activate a periodic timeout on a periodic ring timer
1094 *
1095 * Use 'start_abs' value 0 to start the timer relative to current time. To
1096 * adjust the offset of timeouts, an absolute tick can also be given, but the
1097 * maximum distance from the current time can only be up to one period.
1098 * The periodic rate of the timeout event is 'base_hz' (given when creating the
1099 * timer) multiplied by the given 'multiplier'. For example 1000Hz 'base_hz'
1100 * with a 'multiplier' of 8 will give a 125us period.
1101 *
1102 * A timeout event of type EM_EVENT_TYPE_TIMER_IND is automatically allocated,
1103 * and will be sent to the queue given to em_tmo_create() when the timeout
1104 * expires. The user needs to call em_tmo_ring_ack() when receiving the timeout
1105 * event, similar as with a regular periodic timeout. However, with a ring timer
1106 * there is no guaranteed flow control - new events may be sent even before the
1107 * user has called em_tmo_ring_ack(). This means that the same event may be in
1108 * the input queue multiple times if the application can not keep up with the
1109 * period rate. If the destination queue is not atomic, the same event can also
1110 * be concurrently received by multiple cores. This is a race hazard the user
1111 * must prepare for. Additionally, the used timeout event can not be changed via
1112 * em_tmo_ring_ack(), the actual received event must always be passed to it.
1113 *
1114 * The return code EM_ERR_BUSY indicates that the timeout could not be activated
1115 * due to resource limitations. This can be a temporary situation and retrying
1116 * with the same or updated arguments will likely succeed.
1117 *
1118 * This function can only be used with periodic timeouts from a ring timer.
1119 * The timeout indication event is read-only and can be accessed only via
1120 * accessor APIs.
1121 *
1122 * @param tmo Timeout handle
1123 * @param start_abs Absolute start time (or 0 for period starting at call time)
1124 * @param multiplier Rate multiplier (period rate = multiplier * timer base_hz)
1125 *
1126 * @retval EM_OK Success
1127 * @retval EM_ERR_TOONEAR Failure, start tick value is past or too close
1128 * to current time or multiplier is too high.
1129 * @retval EM_ERR_TOOFAR Failure, start tick value exceeds one period.
1130 * @retval EM_ERR_BUSY Failure, resources are busy.
1131 * @retval (other_codes) Failure
1132 *
1133 * @see em_tmo_user_ptr(), em_tmo_type(), em_timer_create_ring()
1134 * @see em_tmo_ring_ack()
1135 */
1137 em_timer_tick_t start_abs,
1138 uint64_t multiplier);
1139
1140/**
1141 * Activate a periodic timeout on a frequency-based periodic ring timer
1142 *
1143 * Similar to em_tmo_set_periodic_ring(), but instead of a base_hz multiplier,
1144 * the timeout rate is specified directly as a frequency in hertz. The given
1145 * 'freq_hz' must be within the range of constraining frequencies that were
1146 * provided when creating the timer via em_timer_ring_freq_create()
1147 * (i.e. from freq_hz[0] to freq_hz[num - 1]). Frequencies that are not
1148 * present in the constraining array may also be requested, but these may
1149 * suffer from inaccuracies (e.g. drift or jitter) if not exactly compatible
1150 * with the constraining frequencies.
1151 *
1152 * The 'freq_hz' value must be non-zero. An em_fract_u64_t value is non-zero
1153 * when 'integer' or 'numer' is non-zero. If 'numer' is non-zero, 'denom' must
1154 * also be non-zero.
1155 *
1156 * Use 'start_abs' value 0 to start the timer relative to current time. To
1157 * adjust the offset of timeouts, an absolute tick can also be given, but the
1158 * maximum distance from the current time can only be up to one period.
1159 *
1160 * A timeout event of type EM_EVENT_TYPE_TIMER_IND is automatically allocated,
1161 * and will be sent to the queue given to em_tmo_create() when the timeout
1162 * expires. The user needs to call em_tmo_ring_ack() when receiving the timeout
1163 * event. As with em_tmo_set_periodic_ring(), there is no guaranteed flow
1164 * control unless max_pending_events was configured - new events may be sent
1165 * even before the user has called em_tmo_ring_ack().
1166 *
1167 * The return code EM_ERR_BUSY indicates that the timeout could not be activated
1168 * due to resource limitations. This can be a temporary situation and retrying
1169 * with the same or updated arguments will likely succeed.
1170 *
1171 * The same inactive tmo handle may be reused with a different 'freq_hz' value
1172 * on subsequent calls. Changing 'freq_hz' between calls causes the underlying
1173 * implementation timer resource to be freed and re-allocated, which has
1174 * timing-cost implications. The tmo must be in EM_TMO_STATE_IDLE
1175 * (newly created or successfully canceled) when the frequency is changed.
1176 *
1177 * This function can only be used with periodic timeouts from a frequency-based
1178 * ring timer (created via em_timer_ring_freq_create()). The timeout indication
1179 * event is read-only and can be accessed only via accessor APIs.
1180 *
1181 * @param tmo Timeout handle
1182 * @param start_abs Absolute start time (or 0 for period starting at call time)
1183 * @param freq_hz Requested periodic frequency in hertz (fractional).
1184 * Must be non-zero. If 'freq_hz.numer' is non-zero,
1185 * 'freq_hz.denom' must also be non-zero.
1186 *
1187 * @retval EM_OK Success
1188 * @retval EM_ERR_TOONEAR Failure, start tick value is past or too close
1189 * to current time.
1190 * @retval EM_ERR_TOOFAR Failure, start tick value exceeds one period.
1191 * @retval EM_ERR_BUSY Failure, resources are busy.
1192 * @retval (other_codes) Failure
1193 *
1194 * @see em_timer_ring_freq_create(), em_tmo_ring_ack(), em_fract_u64_t
1195 */
1197 em_timer_tick_t start_abs,
1198 em_fract_u64_t freq_hz);
1199
1200/**
1201 * Cancel a timeout
1202 *
1203 * Cancels a timeout preventing future expiration. Returns the timeout event
1204 * if the timeout has not expired.
1205 * A timeout that has already expired, or just is about to, is too late to be
1206 * cancelled and the timeout event will be delivered to the destination queue.
1207 * In this case the error 'EM_ERR_TOONEAR' is returned - no EM error handler is
1208 * called.
1209 *
1210 * Periodic timeout: cancel may fail if attempted too close to the next period.
1211 * This can be considered normal and indicates that at least one more timeout
1212 * event will be delivered to the user. In this case, the error 'EM_ERR_TOONEAR'
1213 * is returned and no valid event is output. The EM error handler is not called
1214 * is this scenario.
1215 * The user calls em_tmo_ack()/em_tmo_ring_ack() for each received periodic
1216 * timeout event. The em_tmo_ack()/em_tmo_ring_ack() function returns
1217 * 'EM_ERR_CANCELED' for the last timeout event from the cancelled periodic
1218 * timeout to let the user know that it is now OK to e.g. delete the timeout.
1219 *
1220 * @param tmo Timeout handle
1221 * @param[out] cur_event Event handle pointer to return the pending
1222 * timeout event for a successful cancel or
1223 * EM_EVENT_UNDEF if cancel fails (e.g. called too late)
1224 *
1225 * @retval EM_OK Cancel successful, timeout event returned.
1226 * @retval EM_ERR_TOONEAR Timeout already expired, too late to cancel.
1227 * EM error handler is not called.
1228 * @retval (other_codes) Failure
1229 *
1230 * @see em_tmo_set_abs(), em_tmo_set_rel(), em_tmo_set_periodic(),
1231 * em_tmo_set_periodic_ring()
1232 * @see em_tmo_ack(), em_tmo_ring_ack() for periodic timeouts
1233 */
1234em_status_t em_tmo_cancel(em_tmo_t tmo, em_event_t *cur_event);
1235
1236/**
1237 * Acknowledge a periodic timeout
1238 *
1239 * All received periodic timeout events must be acknowledged with em_tmo_ack().
1240 * No further timeout event(s) will be sent before the user has acknowledged
1241 * the previous one unless a ring timer is used.
1242 *
1243 * Timeout acknowledgment is usually done at the end of the EO-receive function
1244 * to prevent race conditions (e.g. if the same event is reused for the next
1245 * timeout period also). The implementation will adjust for the processing delay
1246 * so that the time slot will not drift over time.
1247 *
1248 * If em_tmo_ack() is called too late, e.g. the next period(s) is already
1249 * passed, the implementation by default will skip all the missed time slots and
1250 * arm for the next future one keeping the original start offset. The
1251 * application can alter this behaviour with the flag 'EM_TMO_FLAG_NOSKIP' when
1252 * creating a timeout: no past timeout will be skipped and each late
1253 * acknowledgment will immediately trigger sending the next timeout event until
1254 * the current time has been reached.
1255 * Note that using 'EM_TMO_FLAG_NOSKIP' may result in an event storm if a large
1256 * number of timeouts have been unacknowledged for a longer time (limited by
1257 * application response latency). Timing problems will not call the EM error
1258 * handler.
1259 *
1260 * If the timeout has been canceled, but the cancel happened too late for the
1261 * current period, the timeout event will still be delivered. The em_tmo_ack()
1262 * call for this event will return 'EM_ERR_CANCELED' and does not call the error
1263 * handler. This error code signals that the timeout event was the last one
1264 * coming for that, now cancelled, timeout.
1265 *
1266 * The application may reuse the same received timeout event or provide a new
1267 * one for the next timeout via 'next_tmo_ev'. With a periodic ring timer, the
1268 * actual received event must be always be passed via 'next_tmo_ev'.
1269 *
1270 * The given event should not be touched after calling this function until it
1271 * has been received again or after the timeout is successfully cancelled and
1272 * event returned.
1273 *
1274 * A regular periodic timeout (i.e. not a ring one) will stop if em_tmo_ack()
1275 * returns an error other than related to timing. Unless the timeout was
1276 * canceled, the implementation will call the EM error handler in this case
1277 * (the error/exception can be handled also there).
1278 *
1279 * em_tmo_ack() can only be used with regular periodic timeouts. For periodic
1280 * ring timeouts, use em_tmo_ring_ack() instead.
1281 *
1282 * @param tmo Timeout handle
1283 * @param next_tmo_ev Next timeout event handle.
1284 * Can be the received one for regular periodic timeouts.
1285 * Must be the received one for periodic ring timeouts.
1286 *
1287 * @retval EM_OK Success, event taken.
1288 * @retval EM_ERR_CANCELED Timer cancelled, last event - no further timeout
1289 * events coming, event not taken.
1290 * @retval (other_codes) Failure, event not taken.
1291 */
1292em_status_t em_tmo_ack(em_tmo_t tmo, em_event_t next_tmo_ev);
1293
1294/**
1295 * Acknowledge a ring timeout event.
1296 *
1297 * All received periodic ring timeout events must be acknowledged with
1298 * em_tmo_ring_ack(). This function can only be used with periodic ring timers.
1299 *
1300 * The received timeout event must always be passed back via 'tmo_ev' and
1301 * must not be freed or modified by the application.
1302 *
1303 * Timeout acknowledgment is usually done at the end of the EO-receive
1304 * function. Unlike em_tmo_ack(), the ring timer implementation manages
1305 * timing internally and does not support skip or noskip behavior.
1306 *
1307 * If the timeout has been canceled, the return value 'EM_ERR_CANCELED'
1308 * indicates that this was the last timeout event for the given timeout.
1309 * The timeout can then be deleted.
1310 *
1311 * @param tmo Timeout handle (must be a ring timeout)
1312 * @param tmo_ev Received timeout event handle (must be the received one)
1313 *
1314 * @retval EM_OK Success, event taken.
1315 * @retval EM_ERR_CANCELED Timer cancelled, last event - no further timeout
1316 * events coming, event taken.
1317 * @retval (other_codes) Failure, event not taken.
1318 *
1319 * @see em_tmo_ack() for regular periodic timeouts
1320 * @see em_tmo_set_periodic_ring(), em_tmo_cancel(), em_timer_ring_create()
1321 */
1322em_status_t em_tmo_ring_ack(em_tmo_t tmo, em_event_t tmo_ev);
1323
1324/**
1325 * Get a list of currently active timers.
1326 *
1327 * The timer handles returned via 'tmr_list' can be used for further timer
1328 * queries or to destroy existing timers.
1329 *
1330 * The return value always reflects the actual number of timers in the
1331 * EM instance but the output parameter 'tmr_list' is only written up to the
1332 * given 'max' length.
1333 *
1334 * Note that the return value (number of timers) can be greater than the given
1335 * 'max'. It is the user's responsibility to check the return value against the
1336 * given 'max'.
1337 *
1338 * To only get the current number of active timers, without any timer handles
1339 * output, use the following: num_timers = em_timer_list(NULL, 0);
1340 *
1341 * @param[out] tmr_list Pointer to an array of timer handles.
1342 * Use NULL if only interested in the return value.
1343 * @param max Max number of handles that can be written into
1344 * 'tmr_list'. 'max' is ignored if 'tmr_list' is NULL.
1345 *
1346 * @return The number of active timers
1347 */
1348int em_timer_list(em_timer_t tmr_list[], int max);
1349
1350/* Backwards compatible naming ("get") */
1351#define em_timer_get_all em_timer_list
1352
1353/**
1354 * Get timer attributes
1355 *
1356 * Returns the actual capabilities of the given timer.
1357 *
1358 * For frequency-based ring timers the returned 'tmr_attr->freqparam.freq_hz'
1359 * points to implementation-internal read-only storage that is valid until the
1360 * timer is deleted with em_timer_delete(); do not modify or free it.
1361 * 'tmr_attr->freqparam.num' gives the number of valid entries in that array.
1362 *
1363 * @param tmr Timer handle
1364 * @param[out] tmr_attr Pointer to em_timer_attr_t to fill
1365 *
1366 * @return EM_OK on success
1367 */
1368em_status_t em_timer_attr(em_timer_t tmr, em_timer_attr_t *tmr_attr);
1369
1370/* Backwards compatible naming ("get") */
1371#define em_timer_get_attr em_timer_attr
1372/**
1373 * Returns the timer frequency, i.e. ticks per second, for the given timer.
1374 *
1375 * Can be used to convert real time to timer specific ticks.
1376 *
1377 * @param tmr Timer handle
1378 *
1379 * @return ticks per second (Hz), or 0 for non-existing timer
1380 */
1381uint64_t em_timer_freq(em_timer_t tmr);
1382
1383/* Backwards compatible naming ("get") */
1384#define em_timer_get_freq em_timer_freq
1385
1386/**
1387 * Convert timer ticks to nanoseconds (ns)
1388 *
1389 * @param tmr Valid timer handle
1390 * @param ticks Timer specific ticks to convert
1391 *
1392 * @return converted amount in ns
1393 */
1394uint64_t em_timer_tick_to_ns(em_timer_t tmr, em_timer_tick_t ticks);
1395
1396/**
1397 * Convert nanoseconds (ns) to timer ticks
1398 *
1399 * @param tmr Valid timer handle
1400 * @param ns ns value to convert
1401 *
1402 * @return converted amount in timer ticks
1403 */
1404em_timer_tick_t em_timer_ns_to_tick(em_timer_t tmr, uint64_t ns);
1405
1406/**
1407 * Returns the current state of the given timeout.
1408 *
1409 * Note that the returned state may change at any time if the timeout expires
1410 * or is manipulated by other threads.
1411 *
1412 * @param tmo Timeout handle
1413 *
1414 * @return current timeout state (EM_TMO_STATE_UNKNOWN on error)
1415 *
1416 * @see em_tmo_state_t
1417 */
1419
1420/* Backwards compatible naming ("get") */
1421#define em_tmo_get_state em_tmo_state
1422
1423/**
1424 * Returns the statistic counters for a timeout.
1425 *
1426 * Returns a snapshot of the current counters of the given timeout.
1427 * Statistics can be accessed while the timeout is valid, i.e. tmo created but
1428 * not deleted.
1429 *
1430 * Counter support is optional. If counters are not supported, the function
1431 * returns 'EM_ERR_NOT_IMPLEMENTED'.
1432 * A quick way to detect whether counters are supported is to call the function
1433 * with 'stat=NULL' and check the return value.
1434 *
1435 * @param tmo Timeout handle
1436 * @param[out] stat Pointer to em_tmo_stats_t to receive the values (NULL ok)
1437 *
1438 * @return EM_OK on success
1439 */
1441
1442/* Backwards compatible naming ("get") */
1443#define em_tmo_get_stats em_tmo_stats
1444
1445/**
1446 * Ask if the given event is currently used as a timeout indication event.
1447 *
1448 * This function can be used with any valid event handle to ask if it is used as
1449 * a timeout indication event.
1450 * Events are updated to a tmo-type when going through the timer API.
1451 * @note Because a received timeout event is owned by the application, and not
1452 * necessarily passing through the timer API anymore, this type will not be
1453 * reset until the event is freed, reused as another timeout or explicitly reset
1454 * by setting the 'reset' argument to true. This reset should be done if
1455 * re-using the received timeout event for something else than a timeout to
1456 * avoid wrong interpretations.
1457 *
1458 * A successful timeout cancel (event returned) will reset the event type to
1459 * 'EM_TMO_TYPE_NONE'.
1460 *
1461 * @note The 'reset' argument is ignored if the given event is of type
1462 * 'EM_EVENT_TYPE_TIMER_IND'.
1463 *
1464 * The related tmo handle can be retrieved via the 'tmo' argument. This
1465 * can be useful when calling em_tmo_ack() for periodic timeouts:
1466 * @code
1467 * em_tmo_t tmo;
1468 *
1469 * if (em_tmo_type(event, &tmo, false) == EM_TMO_TYPE_PERIODIC)
1470 * retval = em_tmo_ack(tmo, event);
1471 * @endcode
1472 *
1473 * @param event Event handle to check.
1474 * @param[out] tmo em_tmo_t pointer to output the related tmo handle.
1475 * Use NULL if not interested in the tmo handle.
1476 * @param reset Set to 'true' to reset the event's tmo type to
1477 * 'EM_TMO_TYPE_NONE' to e.g. enable non-timer related reuse
1478 * of the event.
1479 *
1480 * @return The type of the timeout or 'EM_TMO_TYPE_NONE' if event is not related
1481 * to a timeout
1482 * @see em_tmo_type_t
1483 */
1484em_tmo_type_t em_tmo_type(em_event_t event, em_tmo_t *tmo, bool reset);
1485
1486/* Backwards compatible naming ("get") */
1487#define em_tmo_get_type em_tmo_type
1488
1489/**
1490 * Returns the optional user pointer for a periodic ring timeout.
1491 *
1492 * Can only be used with an event received as a timeout event for a periodic
1493 * ring, i.e. for events of type 'EM_EVENT_TYPE_TIMER_IND' only. Other event
1494 * types will return NULL.
1495 *
1496 * @param event Event received as timeout
1497 * @param[out] tmo Optionally returns associated tmo handle. NULL ok.
1498 *
1499 * @return A pointer given when creating the associated tmo or
1500 * NULL if the event is not a ring timeout event.
1501 */
1502void *em_tmo_userptr(em_event_t event, em_tmo_t *tmo);
1503
1504/* Backwards compatible naming ("get") */
1505#define em_tmo_get_userptr em_tmo_userptr
1506
1507/**
1508 * Returns the associated timer handle from a timeout handle
1509 *
1510 * The associated timer handle is returned from a valid timeout. Can be used to
1511 * e.g. read the current timer tick without having the timer handle:
1512 * @code
1513 * em_timer_tick_t tick = em_timer_current_tick(em_tmo_timer(tmo));
1514 * @endcode
1515 *
1516 * @param tmo Valid timeout handle
1517 *
1518 * @return The associated timer handle or
1519 * 'EM_TIMER_UNDEF' if the tmo is not valid
1520 */
1521em_timer_t em_tmo_timer(em_tmo_t tmo);
1522
1523/* Backwards compatible naming ("get") */
1524#define em_tmo_get_timer em_tmo_timer
1525
1526/**
1527 * Convert a timer handle to an unsigned integer.
1528 *
1529 * @param timer Timer handle to be converted.
1530 * @return A 'uint64_t' value that can be used to print/display the handle
1531 *
1532 * @note This routine is intended to be used for diagnostic purposes
1533 * to enable applications to e.g. generate a printable value that represents
1534 * an em_timer_t handle.
1535 */
1536uint64_t em_timer_to_u64(em_timer_t timer);
1537
1538/**
1539 * Convert a timeout handle to an unsigned integer.
1540 *
1541 * @param tmo Timeout handle to be converted.
1542 * @return A 'uint64_t' value that can be used to print/display the handle.
1543 *
1544 * @note This routine is intended to be used for diagnostic purposes
1545 * to enable applications to e.g. generate a printable value that represents
1546 * an em_tmo_t handle.
1547 */
1548uint64_t em_tmo_to_u64(em_tmo_t tmo);
1549
1550/**
1551 * @}
1552 */
1553#ifdef __cplusplus
1554}
1555#endif
1556
1557#pragma GCC visibility pop
1558#endif /* EVENT_MACHINE_TIMER_H_ */
uint32_t em_status_t
em_status_t em_timer_capability(em_timer_capability_t *capa, em_timer_clksrc_t clk_src)
em_status_t em_tmo_set_abs(em_tmo_t tmo, em_timer_tick_t ticks_abs, em_event_t tmo_ev)
em_status_t em_timer_ring_freq_capability(em_timer_ring_freq_param_t *ring)
Check frequency-based periodic ring timer capability.
int em_timer_list(em_timer_t tmr_list[], int max)
uint64_t em_timer_freq(em_timer_t tmr)
uint64_t em_tmo_to_u64(em_tmo_t tmo)
em_status_t em_tmo_stats(em_tmo_t tmo, em_tmo_stats_t *stat)
em_status_t em_timer_delete(em_timer_t tmr)
em_status_t em_timer_ring_attr_init(em_timer_attr_t *ring_attr, em_timer_clksrc_t clk_src, uint64_t base_hz, uint64_t max_mul, uint64_t res_ns)
em_status_t em_timer_ring_freq_attr_init(em_timer_attr_t *ring_attr, em_timer_clksrc_t clk_src, em_fract_u64_t *freq_hz, uint32_t num, uint64_t res_ns)
em_timer_tick_t em_timer_ns_to_tick(em_timer_t tmr, uint64_t ns)
em_tmo_state_t em_tmo_state(em_tmo_t tmo)
void * em_tmo_userptr(em_event_t event, em_tmo_t *tmo)
em_tmo_t em_tmo_create(em_timer_t tmr, em_tmo_flag_t flags, em_queue_t queue)
em_timer_t em_timer_create(const em_timer_attr_t *tmr_attr)
em_status_t em_tmo_set_periodic_ring(em_tmo_t tmo, em_timer_tick_t start_abs, uint64_t multiplier)
em_status_t em_tmo_delete(em_tmo_t tmo)
em_status_t em_tmo_cancel(em_tmo_t tmo, em_event_t *cur_event)
em_tmo_type_t em_tmo_type(em_event_t event, em_tmo_t *tmo, bool reset)
em_timer_t em_timer_ring_create(const em_timer_attr_t *ring_attr)
em_status_t em_tmo_set_periodic(em_tmo_t tmo, em_timer_tick_t start_abs, em_timer_tick_t period, em_event_t tmo_ev)
em_timer_tick_t em_timer_current_tick(em_timer_t tmr)
em_status_t em_tmo_ring_ack(em_tmo_t tmo, em_event_t tmo_ev)
em_timer_t em_timer_ring_freq_create(const em_timer_attr_t *ring_attr)
em_status_t em_tmo_set_rel(em_tmo_t tmo, em_timer_tick_t ticks_rel, em_event_t tmo_ev)
em_status_t em_tmo_set_periodic_ring_freq(em_tmo_t tmo, em_timer_tick_t start_abs, em_fract_u64_t freq_hz)
uint64_t em_timer_tick_to_ns(em_timer_t tmr, em_timer_tick_t ticks)
uint64_t em_timer_to_u64(em_timer_t timer)
em_tmo_t em_tmo_create_arg(em_timer_t tmr, em_tmo_flag_t flags, em_queue_t queue, em_tmo_args_t *args)
em_status_t em_timer_attr(em_timer_t tmr, em_timer_attr_t *tmr_attr)
void em_timer_attr_init(em_timer_attr_t *tmr_attr)
em_timer_t em_tmo_timer(em_tmo_t tmo)
em_status_t em_timer_ring_capability(em_timer_ring_param_t *ring)
Check periodic ring timer capability.
em_status_t em_tmo_ack(em_tmo_t tmo, em_event_t next_tmo_ev)
uint64_t em_timer_tick_t
em_status_t em_timer_res_capability(em_timer_res_param_t *res, em_timer_clksrc_t clk_src)
@ EM_TMO_STATE_INACTIVE
@ EM_TMO_STATE_ACTIVE
@ EM_TMO_TYPE_ONESHOT
@ EM_TMO_TYPE_PERIODIC
em_timer_ring_freq_param_t freqparam
em_timer_ring_param_t ringparam
char name[EM_TIMER_NAME_LEN]
em_timer_res_param_t resparam
struct em_timer_capability_t::@27::@28 support
struct em_timer_capability_t::@27 ring