![]() |
EM-ODP 4.4.0
Event Machine on ODP
|
Data Structures | |
| struct | em_fract_u64_t |
| struct | em_timer_res_param_t |
| struct | em_timer_ring_param_t |
| struct | em_timer_ring_freq_param_t |
| struct | em_timer_attr_t |
| struct | em_tmo_stats_t |
| struct | em_timer_capability_t |
| struct | em_tmo_args_t |
Macros | |
| #define | em_timer_get_all em_timer_list |
| #define | em_timer_get_attr em_timer_attr |
| #define | em_timer_get_freq em_timer_freq |
| #define | em_tmo_get_state em_tmo_state |
| #define | em_tmo_get_stats em_tmo_stats |
| #define | em_tmo_get_type em_tmo_type |
| #define | em_tmo_get_userptr em_tmo_userptr |
| #define | em_tmo_get_timer em_tmo_timer |
Typedefs | |
| typedef enum em_tmo_state_t | em_tmo_state_t |
| typedef enum em_tmo_type_t | em_tmo_type_t |
| typedef uint64_t | em_timer_tick_t |
| typedef struct em_fract_u64_t | em_fract_u64_t |
| typedef struct em_timer_res_param_t | em_timer_res_param_t |
| typedef struct em_timer_ring_param_t | em_timer_ring_param_t |
| typedef struct em_timer_ring_freq_param_t | em_timer_ring_freq_param_t |
| typedef struct em_timer_attr_t | em_timer_attr_t |
| typedef struct em_tmo_stats_t | em_tmo_stats_t |
| typedef struct em_timer_capability_t | em_timer_capability_t |
| typedef struct em_tmo_args_t | em_tmo_args_t |
Enumerations | |
| enum | em_tmo_state_t { EM_TMO_STATE_UNKNOWN = 0 , EM_TMO_STATE_IDLE = 1 , EM_TMO_STATE_ACTIVE = 2 , EM_TMO_STATE_INACTIVE = 3 } |
| enum | em_tmo_type_t { EM_TMO_TYPE_NONE = 0 , EM_TMO_TYPE_ONESHOT = 1 , EM_TMO_TYPE_PERIODIC = 2 } |
Event Machine timer
The timer API can be used to request an event to be sent to a specified queue at a specified time once (one-shot) or at regular intervals (periodic). A timer needs to be created first - it represents a collection of timeouts with certain attributes (e.g. timeout resolution and maximum period). A timer can be mapped to a HW resource on an SoC, thus the number of timers, capabilities and time bases are system specific. Typically only a few timers are supported. The application can specify required capabilities when a timer is created. The creation will fail if the implementation cannot fulfill the required values. Timers are typically created once at system startup.
A timer is a shared resource with proper synchronization for concurrent multi-thread use. It is possible to exclude all multi-thread protections if a timer is used exclusively by a single thread (for potential performance gains). This is done by setting EM_TIMER_FLAG_PRIVATE when creating a timer. Setting this flag means that the application must ensure that only a single thread is using the timer (this also includes the receiver of periodic timeouts due to the ack-functionality). This private-mode is not necessarily implemented on all systems, in which case the flag is ignored as it will not cause any functional difference.
Timeouts (tmo) can be created once a timer exists. Creating a timeout allocates the resources needed to serve the timeout, but does not arm it. This makes it possible to pre-create timeout(s) and set the expiry later at runtime. This can improve performance but also minimizes the possibility that the runtime call setting the expiry would fail, as resources have already been reserved beforehand.
A pending timeout can be cancelled. Note that there is no way to cancel an expired timeout for which the event has already been sent but not yet received by the application. Canceling in this case will return an error to enable the application to detect the situation. For a periodic timer, a cancel will stop further timeouts, but may not be able to prevent the latest event from being received. An active timeout cannot be altered without canceling it first.
A timeout can be reused after the timeout event has been received or when successfully cancelled. Timeouts need to be deleted after use. Deletion frees the resources reserved during creation.
The timeout value is an abstract system and timer dependent tick count. It is assumed that the tick count increases with a static frequency. The frequency can be inquired at runtime for time calculations, e.g. tick frequency divided by 1000 gives ticks for 1ms. The tick frequency is at least equal to the resolution, but can also be higher (implementation can quantize ticks to any underlying implementation). The supported resolution can also be inquired. A clock source can be specified when creating a timer. It defines the time base of the timer for systems with multiple sources implemented (optional). EM_TIMER_CLKSRC_DEFAULT is a portable value that implements a basic monotonic time, that will not wrap back to zero in any reasonable uptime.
Events with major event types EM_EVENT_TYPE_SW, EM_EVENT_TYPE_PACKET and EM_EVENT_TYPE_TIMER can be used as timeout events to indicate expiry. The type EM_EVENT_TYPE_TIMER is an alternative to EM_EVENT_TYPE_SW and works the same way. Additionally, for periodic ring timer only, the type EM_EVENT_TYPE_TIMER_IND is used. This is a special timeout indication event without visible payload.
Regular periodic timeouts: (i.e. NOT periodic ring timer timeouts, see differences further down) A periodic timer requires the application to acknowledge each received timeout event after it has been processed. The acknowledgment activates the next timeout and compensates for the processing delay to keep the original interval. This creates a flow control mechanism and also protects the event handling from races if the same event is reused every time - the next timeout will not be sent before the previous has been acknowledged. The event to be received for each periodic timeout can also be different as the next event is given by the application via the acknowledgment. The target queue cannot be modified after the timeout has been created.
If the acknowledgment of a periodic timeout is done too late (after the next period has already passed), the default action is to skip the missed timeout slot(s) and arm for the next valid slot. If the application never wants to skip a missed timeout it can set the flag EM_TMO_FLAG_NOSKIP when creating a timeout. This causes each acknowledgment to schedule an immediate timeout event until all the missed time slots have been served. This keeps the number of timeouts as expected but may cause an event storm if a long processing delay has occurred.
The timeout handle is needed when acknowledging a periodic timeout event. Because any event can be used for the timeout, the application must itself provide a way to derive the timeout handle from the received timeout event. A typical way is to include the tmo handle within the timeout event. The application also needs to have a mechanism to detect which event is a periodic timeout to be able to acknowledge it via em_tmo_ack().
If the requested timeout tick value for a timeout is in the past or is too close to the current time then the error code EM_ERR_TOONEAR is returned. In this case EM will not call the error handler - instead EM lets the application decide whether to treat the situation as an error or to try again with an updated target time.
Periodic ring timer: There is also an alternative periodic ring timer. It uses a different abstraction and is created and started via separate ring specific APIs. It has three main differences to the regular periodic timeouts:
Ring timers can be thought of as a clock face ticking the pointer forward. One cycle around is the base rate (minimum rate). The same timeout can be inserted into multiple locations evenly spread within the clock face thus multiplying the base rate. The starting offset can be adjusted only up to one timeout period. Depending on platform, this mode may provide better integration with HW and thus have less runtime overhead. However, as it exposes a potential queue overflow and a race hazard (race avoidable by using atomic queue as target), regular periodic timeouts are recommended as a default.
Example usage
| #define em_timer_get_all em_timer_list |
Definition at line 1351 of file api/event_machine_timer.h.
| #define em_timer_get_attr em_timer_attr |
Definition at line 1371 of file api/event_machine_timer.h.
| #define em_timer_get_freq em_timer_freq |
Definition at line 1384 of file api/event_machine_timer.h.
| #define em_tmo_get_state em_tmo_state |
Definition at line 1421 of file api/event_machine_timer.h.
| #define em_tmo_get_stats em_tmo_stats |
Definition at line 1443 of file api/event_machine_timer.h.
| #define em_tmo_get_timer em_tmo_timer |
Definition at line 1524 of file api/event_machine_timer.h.
| #define em_tmo_get_type em_tmo_type |
Definition at line 1487 of file api/event_machine_timer.h.
| #define em_tmo_get_userptr em_tmo_userptr |
Definition at line 1505 of file api/event_machine_timer.h.
| typedef struct em_fract_u64_t em_fract_u64_t |
Fractional 64-bit unsigned value for timer frequency.
| typedef struct em_timer_attr_t em_timer_attr_t |
EM timer attributes.
The type is used when creating a timer or inquiring its configuration later.
This needs to be initialized with em_timer_attr_init(), which fills default values to each field. After that the values can be modified as needed. Values set are considered a requirement, e.g. setting 'resparam.res_ns' to 1000(ns) requires the timer to have at least 1us resolution. The timer creation will fail if the implementation cannot support such a resolution (e.g. if it only goes down to 1500ns). The implementation is free to provide better than requested, but not worse.
To know the implementation specific limits, use em_timer_capability() and em_timer_res_capability().
When creating the alternative periodic ring timer, this type needs to be initialized with em_timer_ring_attr_init() instead. EM_TIMER_FLAG_RING will be set by em_timer_ring_attr_init() so it does not need to be manually set.
| typedef struct em_timer_capability_t em_timer_capability_t |
Timer capability info
| typedef struct em_timer_res_param_t em_timer_res_param_t |
Type for timer resolution parameters.
This structure is used to group timer resolution parameters that may affect each other. All time values are in nanoseconds (ns).
| typedef struct em_timer_ring_freq_param_t em_timer_ring_freq_param_t |
Periodic timer ring frequency parameters.
| typedef struct em_timer_ring_param_t em_timer_ring_param_t |
Periodic timer ring timing parameters.
| typedef uint64_t em_timer_tick_t |
The timer tick has HW and timer specific meaning, but the type is always a 64-bit integer and is normally assumed to be monotonic and not to wrap around. Exceptions with exotic extra timers should be clearly documented.
Definition at line 261 of file api/event_machine_timer.h.
| typedef struct em_tmo_args_t em_tmo_args_t |
tmo optional extra arguments
| typedef enum em_tmo_state_t em_tmo_state_t |
Visible state of a timeout
| typedef struct em_tmo_stats_t em_tmo_stats_t |
Timeout statistics counters
Some fields relate to periodic timeout only (0 on one-shots) and vice versa. New fields may be added later at the end.
| typedef enum em_tmo_type_t em_tmo_type_t |
Type returned by em_tmo_type()
| enum em_tmo_state_t |
Visible state of a timeout
| Enumerator | |
|---|---|
| EM_TMO_STATE_IDLE | just created or canceled |
| EM_TMO_STATE_ACTIVE | armed |
| EM_TMO_STATE_INACTIVE | unused state |
Definition at line 240 of file api/event_machine_timer.h.
| enum em_tmo_type_t |
Type returned by em_tmo_type()
| Enumerator | |
|---|---|
| EM_TMO_TYPE_NONE | unknown or not a timer-related event |
| EM_TMO_TYPE_ONESHOT | event is a oneshot timeout indication |
| EM_TMO_TYPE_PERIODIC | event is a periodic timeout indication |
Definition at line 250 of file api/event_machine_timer.h.
| em_status_t em_timer_attr | ( | em_timer_t | tmr, |
| em_timer_attr_t * | tmr_attr | ||
| ) |
Get timer attributes
Returns the actual capabilities of the given timer.
For frequency-based ring timers the returned 'tmr_attr->freqparam.freq_hz' points to implementation-internal read-only storage that is valid until the timer is deleted with em_timer_delete(); do not modify or free it. 'tmr_attr->freqparam.num' gives the number of valid entries in that array.
| tmr | Timer handle | |
| [out] | tmr_attr | Pointer to em_timer_attr_t to fill |
Definition at line 2521 of file event_machine_timer.c.
| void em_timer_attr_init | ( | em_timer_attr_t * | tmr_attr | ) |
Initialize em_timer_attr_t for normal timers (i.e. NOT periodic ring timers).
Initializes em_timer_attr_t to system specific default values. The user can after initialization adjust the values as needed before calling em_timer_create(). The functions em_timer_capability() and/or em_timer_res_capability() can optionally be used to find valid values.
Always initialize em_timer_attr_t with em_timer_attr_init() before use.
The ring timer specific fields 'ringparam' and 'freqparam' are zeroed by this call since they are not used by em_timer_create(). For ring timers, use em_timer_ring_attr_init() or em_timer_ring_freq_attr_init() instead.
This function will not trigger EM error handler calls internally.
Example for all defaults
| [out] | tmr_attr | Pointer to em_timer_attr_t to be initialized |
Definition at line 514 of file event_machine_timer.c.
| em_status_t em_timer_capability | ( | em_timer_capability_t * | capa, |
| em_timer_clksrc_t | clk_src | ||
| ) |
Inquire timer capabilities
Returns timer capabilities for the given clock source, which is also written to both 'capa->max_res.clk_src' and 'capa->max_tmo.clk_src'. For resolution both 'res_ns' and 'res_hz' are filled.
This function will not trigger error handler calls internally.
| [out] | capa | pointer to em_timer_capability_t to be updated (does not need to be initialized) |
| clk_src | Clock source to use for timer (EM_TIMER_CLKSRC_DEFAULT for system specific default) |
Definition at line 727 of file event_machine_timer.c.
| em_timer_t em_timer_create | ( | const em_timer_attr_t * | tmr_attr | ) |
Create and start a timer resource
Required attributes are given via tmr_attr. The given structure must be initialized with em_timer_attr_init() before setting any field.
Timer resolution can be given as time 'res_ns' or frequency 'res_hz'. The user must choose which one to use by setting the other one to 0.
To use all defaults, initialize tmr_attr with em_timer_attr_init() and pass it as is to em_timer_create().
| tmr_attr | Timer parameters to use, pointer to an initialized em_timer_attr_t |
Definition at line 927 of file event_machine_timer.c.
| em_timer_tick_t em_timer_current_tick | ( | em_timer_t | tmr | ) |
Return the current tick value of the given timer
This can be used for calculating absolute timeouts.
| tmr | Timer handle |
Definition at line 1519 of file event_machine_timer.c.
| em_status_t em_timer_delete | ( | em_timer_t | tmr | ) |
Stop and delete a timer
Delete a timer, free all resources. All timeouts for this timer must have been cancelled and deleted first.
| tmr | Timer handle |
Definition at line 1452 of file event_machine_timer.c.
| uint64_t em_timer_freq | ( | em_timer_t | tmr | ) |
Returns the timer frequency, i.e. ticks per second, for the given timer.
Can be used to convert real time to timer specific ticks.
| tmr | Timer handle |
Definition at line 2597 of file event_machine_timer.c.
| int em_timer_list | ( | em_timer_t | tmr_list[], |
| int | max | ||
| ) |
Get a list of currently active timers.
The timer handles returned via 'tmr_list' can be used for further timer queries or to destroy existing timers.
The return value always reflects the actual number of timers in the EM instance but the output parameter 'tmr_list' is only written up to the given 'max' length.
Note that the return value (number of timers) can be greater than the given 'max'. It is the user's responsibility to check the return value against the given 'max'.
To only get the current number of active timers, without any timer handles output, use the following: num_timers = em_timer_list(NULL, 0);
| [out] | tmr_list | Pointer to an array of timer handles. Use NULL if only interested in the return value. |
| max | Max number of handles that can be written into 'tmr_list'. 'max' is ignored if 'tmr_list' is NULL. |
Definition at line 2497 of file event_machine_timer.c.
| em_timer_tick_t em_timer_ns_to_tick | ( | em_timer_t | tmr, |
| uint64_t | ns | ||
| ) |
Convert nanoseconds (ns) to timer ticks
| tmr | Valid timer handle |
| ns | ns value to convert |
Definition at line 2624 of file event_machine_timer.c.
| em_status_t em_timer_res_capability | ( | em_timer_res_param_t * | res, |
| em_timer_clksrc_t | clk_src | ||
| ) |
Inquire timer capabilities for a specific resolution or maximum timeout
Returns timer capabilities by the given resolution or maximum timeout. Set either the resolution (res.res_ns) or the maximum timeout (res.max_tmo) to the required value and the other to zero, and the function will fill the other fields with valid limits. An error is returned if the given value is not supported. The given clk_src is used to set the values and also written to 'res->clk_src'. Both 'res_ns' and 'res_hz' are filled, so if passed further to em_timer_create(), one of those must be set to 0.
Example for external clock maximum resolution
This function will not trigger error handler calls internally.
| [in,out] | res | Pointer to em_timer_res_param_t with one field set |
| clk_src | Clock source to use for timer (EM_TIMER_CLKSRC_DEFAULT for system specific default) |
Definition at line 794 of file event_machine_timer.c.
| 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 | ||
| ) |
Initialize em_timer_attr_t for periodic ring timers.
Initializes em_timer_attr_t according to given values. After successful return, the attributes can be given to em_timer_ring_create(). Note, that if the implementation cannot use the exact given combination it may update the ring_attr values, but always to meet or exceed the given values. The user can read the new values to determine if they were modified. An error is returned if the given values cannot be met.
Before creating the ring timer, other values like num_tmo, name and max_pending_events can be adjusted as needed. Also, if a non-integer frequency is needed, the base_hz fractional part can be adjusted before em_timer_ring_create().
On successful return ring_attr is initialized with:
This function will not trigger error handler calls.
| [out] | ring_attr | Pointer to em_timer_attr_t to be initialized |
| clk_src | Clock source to use (system specific or portable EM_TIMER_CLKSRC_DEFAULT) | |
| base_hz | Base rate of the ring (minimum rate i.e. longest period) | |
| max_mul | Maximum multiplier (maximum rate = base_hz * max_mul) | |
| res_ns | Required resolution of the timer or 0 to accept default |
Definition at line 584 of file event_machine_timer.c.
| em_status_t em_timer_ring_capability | ( | em_timer_ring_param_t * | ring | ) |
Check periodic ring timer capability.
Returns the ring timer capability based on the given input values. The parameter 'ring' must be initialized with the values required by the user. The ring.res_ns can be 0 and gets replaced by the system default. The values are updated during the call. If EM_OK is returned then the combination of given values are all supported (or exceeded, e.g. better resolution), otherwise values are updated with the closest supported.
As em_timer_ring_attr_init() only takes integer base_hz, this can also be used to verify valid values for modified fractional frequencies to avoid error handler calls from em_timer_ring_create().
This function will not trigger error handler calls.
| [in,out] | ring | timer ring parameters to check |
| EM_OK | Parameter combination is supported |
| EM_ERR_NOT_SUPPORTED | Parameters not supported, values updated to closest |
| (other | error) Unsupported arguments |
Definition at line 827 of file event_machine_timer.c.
| em_timer_t em_timer_ring_create | ( | const em_timer_attr_t * | ring_attr | ) |
Create and start a periodic timer ring (alternative periodic timer)
The required attributes are given via ring_attr, which must have been initialized with em_timer_ring_attr_init() and optionally adjusted for the required timing constraints.
A periodic ring timer is a bit different and will only send EM_EVENT_TYPE_TIMER_IND timeout events, which are automatically provided and cannot be modified. These events are allocated internally and do not carry any user data. User must not allocate or free these events.
Example for 1ms ... 125us periodic ring timer (base 1000 hz, multiplier up to 8):
ring_attr must have been initialized with em_timer_ring_attr_init(). Errors are reported via the EM error handler under EM_ESCOPE_TIMER_RING_CREATE (e.g. invalid attr, unsupported clock source or priority, no free timer slot, ODP pool create/start failure).
| ring_attr | Timer ring parameters to use |
Definition at line 1412 of file event_machine_timer.c.
| 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 | ||
| ) |
Initialize em_timer_attr_t for frequency-based periodic ring timers.
Initializes em_timer_attr_t for use with em_timer_ring_freq_create(). Unlike em_timer_ring_attr_init() which uses a base frequency and multiplier, this function takes an array of constraining frequencies that define the allowed periodic timer frequency range for the pool.
The 'freq_hz' array defines constraining frequencies in ascending order. Timer frequencies requested later (via em_tmo_set_periodic_ring_freq()) must be within the range from freq_hz[0] (minimum) to freq_hz[num - 1] (maximum). Frequencies not present in the array may also be requested but may suffer from inaccuracies if not exactly compatible with the constraining frequencies.
Note, that if the implementation cannot use the exact given combination the freq_hz array entries may be updated in-place with the closest supported values. An error is returned if the given values cannot be met.
Before creating the ring timer, other values like num_tmo, name, priority and max_pending_events can be adjusted as needed.
On successful return ring_attr is initialized with:
This function will not trigger error handler calls.
| [out] | ring_attr | Pointer to em_timer_attr_t to be initialized |
| clk_src | Clock source to use (system specific or portable EM_TIMER_CLKSRC_DEFAULT) | |
| [in,out] | freq_hz | Array of constraining frequencies in hertz (ascending order). May be updated in-place if the implementation adjusts values. |
| num | Number of items in 'freq_hz' array (must be >= 1) | |
| res_ns | Required resolution in ns or 0 to accept default |
Definition at line 661 of file event_machine_timer.c.
| em_status_t em_timer_ring_freq_capability | ( | em_timer_ring_freq_param_t * | ring | ) |
Check frequency-based periodic ring timer capability.
Returns the ring timer capability for the frequency-based periodic timer type (ODP_TIMER_TYPE_PERIODIC_FREQ). The parameter 'ring' must be initialized with the values required by the user. The ring->res_ns can be 0 and gets replaced by the system default.
The ring->freq_hz array must contain the constraining frequencies to check, in ascending order. If EM_OK is returned, the given frequency combination is supported (or exceeded). If EM_ERR_NOT_SUPPORTED is returned, the freq_hz array entries are updated in-place with the closest supported values. The application can then inspect the modified values and decide whether to use them.
This can be used to verify valid frequency values before calling em_timer_ring_freq_create() to avoid error handler calls.
This function will not trigger error handler calls.
| [in,out] | ring | Frequency-based ring timer parameters to check. ring->freq_hz array may be updated in-place. |
| EM_OK | Parameter combination is supported |
| EM_ERR_NOT_SUPPORTED | Frequencies not exactly supported, closest values written to freq_hz array |
| (other | error) Unsupported arguments |
Definition at line 881 of file event_machine_timer.c.
| em_timer_t em_timer_ring_freq_create | ( | const em_timer_attr_t * | ring_attr | ) |
Create and start a frequency-based periodic ring timer
Creates a periodic ring timer using ODP_TIMER_TYPE_PERIODIC_FREQ. The required attributes are given via 'ring_attr', which must have been initialized with em_timer_ring_freq_attr_init() and optionally adjusted for the required timing constraints (num_tmo, name, priority, max_pending_events).
Similar to em_timer_ring_create(), this timer only sends read-only EM_EVENT_TYPE_TIMER_IND timeout events that are automatically provided and cannot be modified. These events are allocated internally and do not carry any user data. The user must not allocate or free these events.
Unlike the base_mul ring timer variant, the frequency-based ring timer allows requesting a specific frequency (in Hz) when activating a timeout via em_tmo_set_periodic_ring_freq(). The allowed frequencies are constrained by the freq_hz array given during attribute initialization.
Example:
ring_attr must have been initialized with em_timer_ring_freq_attr_init(). Errors are reported via the EM error handler under EM_ESCOPE_TIMER_RING_FREQ_CREATE (e.g. invalid attr, unsupported clock source or priority, periodic-freq mode not supported by ODP, no free timer slot, ODP pool create/start failure).
The em_timer_attr_init_t::freqparam.freq_hz array defines constraining frequencies for this timer. The requested frequency for a periodic timeout can be set with em_tmo_set_periodic_ring_freq() and must be within the range defined by the minimum and maximum frequencies in the freq_hz array. Frequencies not present in the array may also be requested but may suffer from inaccuracies if not exactly compatible with the constraining frequencies.
| ring_attr | Timer ring parameters to use. Must have been initialized with em_timer_ring_freq_attr_init(). |
Definition at line 1430 of file event_machine_timer.c.
| uint64_t em_timer_tick_to_ns | ( | em_timer_t | tmr, |
| em_timer_tick_t | ticks | ||
| ) |
Convert timer ticks to nanoseconds (ns)
| tmr | Valid timer handle |
| ticks | Timer specific ticks to convert |
Definition at line 2611 of file event_machine_timer.c.
| uint64_t em_timer_to_u64 | ( | em_timer_t | timer | ) |
Convert a timer handle to an unsigned integer.
| timer | Timer handle to be converted. |
Definition at line 2743 of file event_machine_timer.c.
| em_status_t em_tmo_ack | ( | em_tmo_t | tmo, |
| em_event_t | next_tmo_ev | ||
| ) |
Acknowledge a periodic timeout
All received periodic timeout events must be acknowledged with em_tmo_ack(). No further timeout event(s) will be sent before the user has acknowledged the previous one unless a ring timer is used.
Timeout acknowledgment is usually done at the end of the EO-receive function to prevent race conditions (e.g. if the same event is reused for the next timeout period also). The implementation will adjust for the processing delay so that the time slot will not drift over time.
If em_tmo_ack() is called too late, e.g. the next period(s) is already passed, the implementation by default will skip all the missed time slots and arm for the next future one keeping the original start offset. The application can alter this behaviour with the flag 'EM_TMO_FLAG_NOSKIP' when creating a timeout: no past timeout will be skipped and each late acknowledgment will immediately trigger sending the next timeout event until the current time has been reached. Note that using 'EM_TMO_FLAG_NOSKIP' may result in an event storm if a large number of timeouts have been unacknowledged for a longer time (limited by application response latency). Timing problems will not call the EM error handler.
If the timeout has been canceled, but the cancel happened too late for the current period, the timeout event will still be delivered. The em_tmo_ack() call for this event will return 'EM_ERR_CANCELED' and does not call the error handler. This error code signals that the timeout event was the last one coming for that, now cancelled, timeout.
The application may reuse the same received timeout event or provide a new one for the next timeout via 'next_tmo_ev'. With a periodic ring timer, the actual received event must be always be passed via 'next_tmo_ev'.
The given event should not be touched after calling this function until it has been received again or after the timeout is successfully cancelled and event returned.
A regular periodic timeout (i.e. not a ring one) will stop if em_tmo_ack() returns an error other than related to timing. Unless the timeout was canceled, the implementation will call the EM error handler in this case (the error/exception can be handled also there).
em_tmo_ack() can only be used with regular periodic timeouts. For periodic ring timeouts, use em_tmo_ring_ack() instead.
| tmo | Timeout handle |
| next_tmo_ev | Next timeout event handle. Can be the received one for regular periodic timeouts. Must be the received one for periodic ring timeouts. |
| EM_OK | Success, event taken. |
| EM_ERR_CANCELED | Timer cancelled, last event - no further timeout events coming, event not taken. |
| (other_codes) | Failure, event not taken. |
Definition at line 2405 of file event_machine_timer.c.
| em_status_t em_tmo_cancel | ( | em_tmo_t | tmo, |
| em_event_t * | cur_event | ||
| ) |
Cancel a timeout
Cancels a timeout preventing future expiration. Returns the timeout event if the timeout has not expired. A timeout that has already expired, or just is about to, is too late to be cancelled and the timeout event will be delivered to the destination queue. In this case the error 'EM_ERR_TOONEAR' is returned - no EM error handler is called.
Periodic timeout: cancel may fail if attempted too close to the next period. This can be considered normal and indicates that at least one more timeout event will be delivered to the user. In this case, the error 'EM_ERR_TOONEAR' is returned and no valid event is output. The EM error handler is not called is this scenario. The user calls em_tmo_ack()/em_tmo_ring_ack() for each received periodic timeout event. The em_tmo_ack()/em_tmo_ring_ack() function returns 'EM_ERR_CANCELED' for the last timeout event from the cancelled periodic timeout to let the user know that it is now OK to e.g. delete the timeout.
| tmo | Timeout handle | |
| [out] | cur_event | Event handle pointer to return the pending timeout event for a successful cancel or EM_EVENT_UNDEF if cancel fails (e.g. called too late) |
| EM_OK | Cancel successful, timeout event returned. |
| EM_ERR_TOONEAR | Timeout already expired, too late to cancel. EM error handler is not called. |
| (other_codes) | Failure |
Definition at line 2230 of file event_machine_timer.c.
| em_tmo_t em_tmo_create | ( | em_timer_t | tmr, |
| em_tmo_flag_t | flags, | ||
| em_queue_t | queue | ||
| ) |
Allocate a new timeout
Create a new timeout. Allocates the necessary internal resources from the given timer and prepares for em_tmo_set_abs/rel/periodic().
Scheduled queues are always supported as timeout event destinations. LOCAL or OUTPUT queues can not be used as timeout targets. Support for unscheduled queues is implementation specific.
Flags are used to select functionality:
The NOSKIP flag is ignored if used timer is a periodic timer ring.
| tmr | Timer handle |
| flags | Functionality flags |
| queue | Target queue where the timeout event should be delivered |
Definition at line 1530 of file event_machine_timer.c.
| 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 | ||
| ) |
Allocate a new timeout with extra arguments
Similar to em_tmo_create() but with an additional 'args' pointer. This API can be used with any timer type, but 'args->userptr' is only meaningful for ring timers using events of type EM_EVENT_TYPE_TIMER_IND that can carry a 'userptr'.
| tmr | Timer handle |
| flags | Functionality flags |
| queue | Target queue where the timeout event should be delivered |
| args | Optional pointer holding extra arguments e.g. userptr for ring timers. NULL ok. |
Definition at line 1535 of file event_machine_timer.c.
| em_status_t em_tmo_delete | ( | em_tmo_t | tmo | ) |
Delete a timeout
The deleted timeout must be inactive i.e. it must be successfully canceled or the last timeout event must have been received (following too late a cancel). A periodic or a periodic ring timeout can be deleted after a successful cancel or after em_tmo_ack()/em_tmo_ring_ack() returned EM_ERR_CANCELED. This indicates that the acknowledged timeout is canceled and that it was the last timeout event coming for that periodic timeout.
After and during this call, the tmo handle is not valid anymore and must not be used by or passed to other timer APIs.
| tmo | Timeout handle |
Definition at line 1662 of file event_machine_timer.c.
| em_status_t em_tmo_ring_ack | ( | em_tmo_t | tmo, |
| em_event_t | tmo_ev | ||
| ) |
Acknowledge a ring timeout event.
All received periodic ring timeout events must be acknowledged with em_tmo_ring_ack(). This function can only be used with periodic ring timers.
The received timeout event must always be passed back via 'tmo_ev' and must not be freed or modified by the application.
Timeout acknowledgment is usually done at the end of the EO-receive function. Unlike em_tmo_ack(), the ring timer implementation manages timing internally and does not support skip or noskip behavior.
If the timeout has been canceled, the return value 'EM_ERR_CANCELED' indicates that this was the last timeout event for the given timeout. The timeout can then be deleted.
| tmo | Timeout handle (must be a ring timeout) |
| tmo_ev | Received timeout event handle (must be the received one) |
| EM_OK | Success, event taken. |
| EM_ERR_CANCELED | Timer cancelled, last event - no further timeout events coming, event taken. |
| (other_codes) | Failure, event not taken. |
Definition at line 2462 of file event_machine_timer.c.
| em_status_t em_tmo_set_abs | ( | em_tmo_t | tmo, |
| em_timer_tick_t | ticks_abs, | ||
| em_event_t | tmo_ev | ||
| ) |
Activate a oneshot timeout with absolute time.
Activates a oneshot timeout to expire at a specific absolute time. The given timeout event will be sent to the queue given to em_tmo_create() when the timeout expires.
It is not possible to send timeouts with an event group, but the application can assign the event group when receiving the timeout event, see em_event_group_assign().
The timeout event should not be accessed after it has been given to the timer, similar to sending an event.
Even if not guaranteed, the implementation should make sure that this call can fail only in exceptional situations (em_tmo_create() should pre-allocate needed resources).
The allowed minimum and maximum timeouts can be inquired with em_timer_res_capability().
An active timeout can not be modified. The timeout needs to be canceled and then set again with new arguments.
An inactive timeout can be reused by calling em_tmo_set_abs/rel() again. The timeout becomes inactive after the oneshot timeout event has been received or after it has been successfully cancelled.
The return code EM_ERR_BUSY indicates that the timeout could not be activated due to resource limitations. This can be a temporary situation and retrying with the same or updated arguments will likely succeed.
This function is for activating oneshot timeouts only. To activate periodic timeouts use em_tmo_set_periodic() (or em_tmo_set_periodic_ring()).
| tmo | Timeout handle |
| ticks_abs | Expiration time in absolute timer specific ticks |
| tmo_ev | Timeout event |
| EM_OK | Success, event taken. |
| EM_ERR_TOONEAR | Failure, the tick value is in past or too close to the current time. Error handler not called, event not taken. |
| EM_ERR_BUSY | Failure, resources are busy. Error handler not called, event not taken. |
| (other_codes) | Failure, event not taken. |
Definition at line 1733 of file event_machine_timer.c.
| 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 | ||
| ) |
Activate a periodic timeout
Used to activate periodic timeouts. The first period can be different from the repetitive period by providing an absolute start time. Set 'start_abs' to 0 if the repetitive period can start from the moment of the call.
The timeout event will be sent to the queue given to em_tmo_create() when the first timeout expires. The receiver then needs to call em_tmo_ack() to allow the timer to send the next event for the following period.
The return code EM_ERR_BUSY indicates that the timeout could not be activated due to resource limitations. This can be a temporary situation and retrying with the same or updated arguments will likely succeed.
This function can only be used with periodic timeouts (created with flag EM_TMO_FLAG_PERIODIC).
| tmo | Timeout handle |
| start_abs | Absolute start time (or 0 for period starting at call time) |
| period | Period in timer specific ticks |
| tmo_ev | Timeout event handle |
| EM_OK | Success, event taken |
| EM_ERR_TOONEAR | Failure, the tick value is in past or too close to the current time. Error handler not called, event not taken. |
| EM_ERR_BUSY | Failure, resources are busy. Error handler not called, event not taken. |
| (other_codes) | Failure, event not taken. |
Definition at line 1893 of file event_machine_timer.c.
| em_status_t em_tmo_set_periodic_ring | ( | em_tmo_t | tmo, |
| em_timer_tick_t | start_abs, | ||
| uint64_t | multiplier | ||
| ) |
Activate a periodic timeout on a periodic ring timer
Use 'start_abs' value 0 to start the timer relative to current time. To adjust the offset of timeouts, an absolute tick can also be given, but the maximum distance from the current time can only be up to one period. The periodic rate of the timeout event is 'base_hz' (given when creating the timer) multiplied by the given 'multiplier'. For example 1000Hz 'base_hz' with a 'multiplier' of 8 will give a 125us period.
A timeout event of type EM_EVENT_TYPE_TIMER_IND is automatically allocated, and will be sent to the queue given to em_tmo_create() when the timeout expires. The user needs to call em_tmo_ring_ack() when receiving the timeout event, similar as with a regular periodic timeout. However, with a ring timer there is no guaranteed flow control - new events may be sent even before the user has called em_tmo_ring_ack(). This means that the same event may be in the input queue multiple times if the application can not keep up with the period rate. If the destination queue is not atomic, the same event can also be concurrently received by multiple cores. This is a race hazard the user must prepare for. Additionally, the used timeout event can not be changed via em_tmo_ring_ack(), the actual received event must always be passed to it.
The return code EM_ERR_BUSY indicates that the timeout could not be activated due to resource limitations. This can be a temporary situation and retrying with the same or updated arguments will likely succeed.
This function can only be used with periodic timeouts from a ring timer. The timeout indication event is read-only and can be accessed only via accessor APIs.
| tmo | Timeout handle |
| start_abs | Absolute start time (or 0 for period starting at call time) |
| multiplier | Rate multiplier (period rate = multiplier * timer base_hz) |
| EM_OK | Success |
| EM_ERR_TOONEAR | Failure, start tick value is past or too close to current time or multiplier is too high. |
| EM_ERR_TOOFAR | Failure, start tick value exceeds one period. |
| EM_ERR_BUSY | Failure, resources are busy. |
| (other_codes) | Failure |
Definition at line 1985 of file event_machine_timer.c.
| 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 | ||
| ) |
Activate a periodic timeout on a frequency-based periodic ring timer
Similar to em_tmo_set_periodic_ring(), but instead of a base_hz multiplier, the timeout rate is specified directly as a frequency in hertz. The given 'freq_hz' must be within the range of constraining frequencies that were provided when creating the timer via em_timer_ring_freq_create() (i.e. from freq_hz[0] to freq_hz[num - 1]). Frequencies that are not present in the constraining array may also be requested, but these may suffer from inaccuracies (e.g. drift or jitter) if not exactly compatible with the constraining frequencies.
The 'freq_hz' value must be non-zero. An em_fract_u64_t value is non-zero when 'integer' or 'numer' is non-zero. If 'numer' is non-zero, 'denom' must also be non-zero.
Use 'start_abs' value 0 to start the timer relative to current time. To adjust the offset of timeouts, an absolute tick can also be given, but the maximum distance from the current time can only be up to one period.
A timeout event of type EM_EVENT_TYPE_TIMER_IND is automatically allocated, and will be sent to the queue given to em_tmo_create() when the timeout expires. The user needs to call em_tmo_ring_ack() when receiving the timeout event. As with em_tmo_set_periodic_ring(), there is no guaranteed flow control unless max_pending_events was configured - new events may be sent even before the user has called em_tmo_ring_ack().
The return code EM_ERR_BUSY indicates that the timeout could not be activated due to resource limitations. This can be a temporary situation and retrying with the same or updated arguments will likely succeed.
The same inactive tmo handle may be reused with a different 'freq_hz' value on subsequent calls. Changing 'freq_hz' between calls causes the underlying implementation timer resource to be freed and re-allocated, which has timing-cost implications. The tmo must be in EM_TMO_STATE_IDLE (newly created or successfully canceled) when the frequency is changed.
This function can only be used with periodic timeouts from a frequency-based ring timer (created via em_timer_ring_freq_create()). The timeout indication event is read-only and can be accessed only via accessor APIs.
| tmo | Timeout handle |
| start_abs | Absolute start time (or 0 for period starting at call time) |
| freq_hz | Requested periodic frequency in hertz (fractional). Must be non-zero. If 'freq_hz.numer' is non-zero, 'freq_hz.denom' must also be non-zero. |
| EM_OK | Success |
| EM_ERR_TOONEAR | Failure, start tick value is past or too close to current time. |
| EM_ERR_TOOFAR | Failure, start tick value exceeds one period. |
| EM_ERR_BUSY | Failure, resources are busy. |
| (other_codes) | Failure |
Definition at line 2106 of file event_machine_timer.c.
| em_status_t em_tmo_set_rel | ( | em_tmo_t | tmo, |
| em_timer_tick_t | ticks_rel, | ||
| em_event_t | tmo_ev | ||
| ) |
Activate a timeout with a relative time.
Similar to em_tmo_set_abs(), but instead of an absolute time uses a timeout value relative to the moment of the call.
The return code EM_ERR_BUSY indicates that the timeout could not be activated due to resource limitations. This can be a temporary situation and retrying with the same or updated arguments will likely succeed.
This function is for activating oneshot timeouts only. To activate periodic timeouts use em_tmo_set_periodic() (or em_tmo_set_periodic_ring()).
| tmo | Timeout handle |
| ticks_rel | Expiration time in relative timer specific ticks |
| tmo_ev | Timeout event handle |
| EM_OK | Success, event taken. |
| EM_ERR_TOONEAR | Failure, the tick value is too low. Error handler not called, event not taken. |
| EM_ERR_BUSY | Failure, resources are busy. Error handler not called, event not taken. |
| (other_codes) | Failure, event not taken. |
Definition at line 1814 of file event_machine_timer.c.
| em_tmo_state_t em_tmo_state | ( | em_tmo_t | tmo | ) |
Returns the current state of the given timeout.
Note that the returned state may change at any time if the timeout expires or is manipulated by other threads.
| tmo | Timeout handle |
Definition at line 2637 of file event_machine_timer.c.
| em_status_t em_tmo_stats | ( | em_tmo_t | tmo, |
| em_tmo_stats_t * | stat | ||
| ) |
Returns the statistic counters for a timeout.
Returns a snapshot of the current counters of the given timeout. Statistics can be accessed while the timeout is valid, i.e. tmo created but not deleted.
Counter support is optional. If counters are not supported, the function returns 'EM_ERR_NOT_IMPLEMENTED'. A quick way to detect whether counters are supported is to call the function with 'stat=NULL' and check the return value.
| tmo | Timeout handle | |
| [out] | stat | Pointer to em_tmo_stats_t to receive the values (NULL ok) |
Definition at line 2651 of file event_machine_timer.c.
| em_timer_t em_tmo_timer | ( | em_tmo_t | tmo | ) |
Returns the associated timer handle from a timeout handle
The associated timer handle is returned from a valid timeout. Can be used to e.g. read the current timer tick without having the timer handle:
| tmo | Valid timeout handle |
Definition at line 2729 of file event_machine_timer.c.
| uint64_t em_tmo_to_u64 | ( | em_tmo_t | tmo | ) |
Convert a timeout handle to an unsigned integer.
| tmo | Timeout handle to be converted. |
Definition at line 2748 of file event_machine_timer.c.
| em_tmo_type_t em_tmo_type | ( | em_event_t | event, |
| em_tmo_t * | tmo, | ||
| bool | reset | ||
| ) |
Ask if the given event is currently used as a timeout indication event.
This function can be used with any valid event handle to ask if it is used as a timeout indication event. Events are updated to a tmo-type when going through the timer API.
A successful timeout cancel (event returned) will reset the event type to 'EM_TMO_TYPE_NONE'.
The related tmo handle can be retrieved via the 'tmo' argument. This can be useful when calling em_tmo_ack() for periodic timeouts:
| event | Event handle to check. | |
| [out] | tmo | em_tmo_t pointer to output the related tmo handle. Use NULL if not interested in the tmo handle. |
| reset | Set to 'true' to reset the event's tmo type to 'EM_TMO_TYPE_NONE' to e.g. enable non-timer related reuse of the event. |
Definition at line 2674 of file event_machine_timer.c.
| void * em_tmo_userptr | ( | em_event_t | event, |
| em_tmo_t * | tmo | ||
| ) |
Returns the optional user pointer for a periodic ring timeout.
Can only be used with an event received as a timeout event for a periodic ring, i.e. for events of type 'EM_EVENT_TYPE_TIMER_IND' only. Other event types will return NULL.
| event | Event received as timeout | |
| [out] | tmo | Optionally returns associated tmo handle. NULL ok. |
Definition at line 2708 of file event_machine_timer.c.