From 0d84aa03b480a6944c33b2547717c25d143caef4 Mon Sep 17 00:00:00 2001 From: Matias Elo Date: Thu, 12 Sep 2024 10:11:56 +0300 Subject: [PATCH] WIP: api: event: add generic event vector API Signed-off-by: Matias Elo --- include/odp/api/spec/event.h | 219 +++++++++++++++++++++++++++++ include/odp/api/spec/event_types.h | 88 ++++++++++++ include/odp/api/spec/queue.h | 15 ++ include/odp/api/spec/queue_types.h | 47 +++++++ 4 files changed, 369 insertions(+) diff --git a/include/odp/api/spec/event.h b/include/odp/api/spec/event.h index e5684c6347..690575309b 100644 --- a/include/odp/api/spec/event.h +++ b/include/odp/api/spec/event.h @@ -276,6 +276,225 @@ uint32_t odp_event_flow_id(odp_event_t event); */ void odp_event_flow_id_set(odp_event_t event, uint32_t flow_id); +/* + * + * Event vector handling routines + * ******************************************************** + * + */ + +/** + * Get event vector handle from event + * + * Converts an ODP_EVENT_VECTOR type event to an event vector handle. + * + * @param ev Event handle + * + * @return Event vector handle + * + * @see odp_event_type() + */ +odp_event_vector_t odp_event_vector_from_event(odp_event_t ev); + +/** + * Convert event vector handle to event + * + * @param evv Event vector handle + * + * @return Event handle + */ +odp_event_t odp_event_vector_to_event(odp_event_vector_t evv); + +/** + * Allocate event vector from event vector pool + * + * Allocates an event vector from the specified event vector pool. The pool must + * have been created with the ODP_POOL_VECTOR type. + * + * A newly allocated vector shall not contain any events, instead, alloc + * operation shall reserve the space for odp_pool_param_t::vector::max_size + * events. + * + * @param pool Event vector pool handle + * + * @return Handle of allocated event vector + * @retval ODP_EVENT_VECTOR_INVALID Event vector could not be allocated + */ +odp_event_vector_t odp_event_vector_alloc(odp_pool_t pool); + +/** + * Free event vector + * + * Frees the event vector into the event vector pool it was allocated from. + * + * This API just frees the vector, not any events inside the vector. Application + * can use odp_event_free() to free the vector and events inside the vector. + * + * @param evv Event vector handle + */ +void odp_event_vector_free(odp_event_vector_t evv); + +/** + * Get event vector table + * + * Event vector table is an array of events (odp_event_t) stored in contiguous + * memory location. Upon completion of this API, the implementation returns the + * event table pointer in event_tbl. + * + * @param evv Event vector handle + * @param[out] event_tbl Points to event vector table + * + * @return Number of events available in the vector. + * + * @note The maximum number of events this vector can hold is defined by + * odp_pool_param_t::vector::max_size. The return value of this function will + * not be greater than odp_pool_param_t::vector::max_size + * + * @note The event_tbl points to the event vector table. Application can edit + * the event handles in the table directly (up to odp_pool_param_t::vector::max_size). + * Application must update the size of the table using odp_event_vector_size_set() + * when there is a change in the size of the vector. + * + * @note Invalid event handles (ODP_EVENT_INVALID) are not allowed to be + * stored in the table to allow consumers of odp_event_vector_t handle to have + * optimized implementation. So consumption of events in the middle of the + * vector would call for moving the remaining events up to form a contiguous + * array of events and update the size of the new vector using + * odp_event_vector_size_set(). + * + * @note The table memory is backed by a vector pool buffer. The ownership of + * the table memory is linked to the ownership of the event. I.e. after sending + * the event to a queue, the sender loses ownership to the table also. + */ +uint32_t odp_event_vector_tbl(odp_event_vector_t evv, odp_event_t **event_tbl); + +/** + * Number of events in a vector + * + * @param evv Event vector handle + * + * @return The number of events available in the vector + */ +uint32_t odp_event_vector_size(odp_event_vector_t evv); + +/** + * Type of events stored in event vector + * + * Returns the event type of the events stored in the event vector. If all events within the vector + * are of same type, this function returns the event type. If the events are of different types or + * the vector is empty, ODP_EVENT_ANY is returned. + * + * @param evv Event vector handle + * + * @return Event type + */ +odp_event_type_t odp_event_vector_type(odp_event_vector_t evv); + +/** + * Set the number of events stored in a vector + * + * Update the number of events stored in a vector. When the application is + * producing an event vector, this function shall be used by the application + * to set the number of events available in this vector. + * + * @param evv Event vector handle + * @param size Number of events in this vector + * + * @note The maximum number of events this vector can hold is defined by + * odp_pool_param_t::vector::max_size. The size value must not be greater than + * odp_pool_param_t::vector::max_size + * + * @note All handles in the vector table (0 .. size - 1) need to be valid event + * handles. + * + * @see odp_event_vector_tbl() + */ +void odp_event_vector_size_set(odp_event_vector_t evv, uint32_t size); + +/** + * Event vector user area + * + * Returns pointer to the user area associated with the event vector. Size of + * the area is fixed and defined in vector pool parameters. + * + * @param evv Event vector handle + * + * @return Pointer to the user area of the event vector + * @retval NULL The event vector does not have user area + */ +void *odp_event_vector_user_area(odp_event_vector_t evv); + +/** + * Check user flag + * + * Implementation clears user flag during new event vector creation (e.g. alloc + * and event input) and reset. User may set the flag with odp_event_vector_user_flag_set(). + * Implementation never sets the flag, only clears it. The flag may be useful + * e.g. to mark when the user area content is valid. + * + * @param evv Event vector handle + * + * @retval 0 User flag is clear + * @retval >0 User flag is set + */ +int odp_event_vector_user_flag(odp_event_vector_t evv); + +/** + * Set user flag + * + * Set (or clear) the user flag. + * + * @param evv Event vector handle + * @param val New value for the flag. Zero clears the flag, other values set the flag. + */ +void odp_event_vector_user_flag_set(odp_event_vector_t evv, int val); + +/** + * Check that event vector is valid + * + * This function can be used for debugging purposes to check if an event vector + * handle represents a valid event vector. The level of error checks depends on + * the implementation. Considerable number of cpu cycles may be consumed + * depending on the level. The call should not crash if the event vector handle + * is corrupted. + * + * @param evv Event vector handle + * + * @retval 0 Event vector is not valid + * @retval 1 Event vector is valid + */ +int odp_event_vector_valid(odp_event_vector_t evv); + +/** + * Event vector pool + * + * Returns handle to the event vector pool where the event vector was allocated + * from. + * + * @param evv Event vector handle + * + * @return Event vector pool handle + */ +odp_pool_t odp_event_vector_pool(odp_event_vector_t evv); + +/** + * Print event vector debug information + * + * Print all event vector debug information to ODP log. + * + * @param evv Event vector handle + */ +void odp_event_vector_print(odp_event_vector_t evv); + +/** + * Get printable value for event vector handle + * + * @param evv Handle to be converted for debugging + * + * @return uint64_t value that can be used to print/display this handle + */ +uint64_t odp_event_vector_to_u64(odp_event_vector_t evv); + /** * @} */ diff --git a/include/odp/api/spec/event_types.h b/include/odp/api/spec/event_types.h index b967e2871a..eadc254c80 100644 --- a/include/odp/api/spec/event_types.h +++ b/include/odp/api/spec/event_types.h @@ -26,11 +26,21 @@ extern "C" { * ODP event */ +/** + * @typedef odp_event_vector_t + * ODP event vector + */ + /** * @def ODP_EVENT_INVALID * Invalid event */ +/** + * @def ODP_EVENT_VECTOR_INVALID + * Invalid event vector + */ + /** * @typedef odp_event_type_t * Event type @@ -52,6 +62,8 @@ extern "C" { * - Timeout event (odp_timeout_t) from a timer * - ODP_EVENT_IPSEC_STATUS * - IPSEC status update event (odp_ipsec_status_t) + * - ODP_EVENT_VECTOR + * - Vector of events (odp_event_t) as odp_event_vector_t * - ODP_EVENT_PACKET_VECTOR * - Vector of packet events (odp_packet_t) as odp_packet_vector_t * - ODP_EVENT_PACKET_TX_COMPL @@ -102,6 +114,82 @@ extern "C" { * operation. */ +/** + * Event vector configuration + */ +typedef struct odp_event_vector_config_t { + /** Enable event vector + * + * When true, event vector is enabled and configured with vector config + * parameters. Otherwise, event vector configuration parameters are + * ignored. When vectors are enabled, events may be delivered both as + * event vector events and normal events. The default value is false. + */ + odp_bool_t enable; + + /** Vector pool + * + * Vector pool to allocate the vectors to hold events. The pool must + * have been created with the ODP_POOL_VECTOR type. + */ + odp_pool_t pool; + + /** Maximum time to wait for events + * + * Maximum timeout in nanoseconds to wait for the producer to form the + * vector of events (odp_event_vector_t). This value should be + * in the range of odp_event_vector_capability_t::min_tmo_ns to + * odp_event_vector_capability_t::max_tmo_ns. + */ + uint64_t max_tmo_ns; + + /** Maximum number of events in a vector + * + * The event subsystem forms event vector events when either it reaches + * odp_event_vector_config_t::max_tmo_ns or producer reaches max_size + * events. This value should be in the range of + * odp_event_vector_capability_t::min_size to + * odp_event_vector_capability_t::max_size. + * + * @note The maximum number of events this vector can hold is defined + * by odp_pool_param_t::vector::max_size with odp_event_vector_config_t::pool. + * The max_size should not be greater than odp_pool_param_t::vector::max_size. + */ + uint32_t max_size; + +} odp_event_vector_config_t; + +/** + * Event vector capabilities + */ +typedef struct odp_event_vector_capability_t { + /** Event vector availability */ + odp_support_t supported; + + /** Maximum number of events that can be accumulated into an event + * vector by a producer. + * + * odp_event_vector_config_t::max_size should not be greater than this + * value. */ + uint32_t max_size; + + /** Minimum value allowed to be configured to + * odp_event_vector_config_t::max_size */ + uint32_t min_size; + + /** Maximum timeout in nanoseconds for the producer to wait for the + * vector of events + * + * odp_event_vector_config_t::max_tmo_ns should not be greater than this + * value. */ + uint64_t max_tmo_ns; + + /** Minimum value allowed to be configured to + * odp_event_vector_config_t::max_tmo_ns */ + uint64_t min_tmo_ns; + +} odp_event_vector_capability_t; + /** * @} */ diff --git a/include/odp/api/spec/queue.h b/include/odp/api/spec/queue.h index f12c3a1852..739c199161 100644 --- a/include/odp/api/spec/queue.h +++ b/include/odp/api/spec/queue.h @@ -193,6 +193,21 @@ int odp_queue_enq(odp_queue_t queue, odp_event_t ev); */ int odp_queue_enq_multi(odp_queue_t queue, const odp_event_t events[], int num); +/** + * Enqueue an event to a queue vector context + * + * What happens if a vector event is enqueued to a vector context? E.g.vector + * within a vector. + * + * @param queue Queue handle + * @param vector_index Index of the vector context + * @param evv Event vector handle + * + * @retval 0 on success + * @retval <0 on failure + */ +int odp_queue_enq_vector(odp_queue_t queue, uint32_t vector_index, odp_event_vector_t evv); + /** * Dequeue an event from a queue * diff --git a/include/odp/api/spec/queue_types.h b/include/odp/api/spec/queue_types.h index 057df405a6..2b075ebd16 100644 --- a/include/odp/api/spec/queue_types.h +++ b/include/odp/api/spec/queue_types.h @@ -16,6 +16,7 @@ extern "C" { #endif +#include #include /** @defgroup odp_queue ODP QUEUE @@ -218,6 +219,11 @@ typedef struct odp_queue_capability_t { } odp_queue_capability_t; +/** + * @def ODP_QUEUE_MAX_VECTORS + * Maximum number of vector contexts per queue + */ + /** * ODP Queue parameters */ @@ -291,8 +297,49 @@ typedef struct odp_queue_param_t { * default size. The default value is 0. */ uint32_t size; + /* Number of vector contexts */ + uint32_t num_vector; + + /** Vector parameters + * + * When num_vector > 1, events destined to this queue are vectorized + * using vector 0 by default. To utilize other vector contexts use + * odp_queue_enq_vector(). + * + * odp_queue_t references: + * - odp_cls_cos_param_t.queue + * - odp_comp_session_param_t.compl_queue + * - odp_crypto_session_param_t.compl_queue + * - odp_dma_compl_param_t.queue + * - odp_ipsec_inbound_config_t.default_queue + * - odp_ipsec_sa_param_t.dest_queue + * - odp_ml_compl_param_t.queue + * - odp_packet_tx_compl_opt_t.queue + * - odp_timer_alloc() + * + * Open Questions: + * - Add e.g. odp_queue_vector_context_create()/destroy() for sharing + * vector contexts between queues? + * - Forbid storing vector events within vectors? + * - Plain queue support? + * - What to do with the old odp_packet_vector APIs? + */ + struct { + odp_pool_t pool; + uint64_t max_tmo_ns; + uint32_t max_size; + odp_event_type_t type; /* Any? */ + } vector[ODP_QUEUE_MAX_VECTORS]; /* Needs to be more dynamic? */ + } odp_queue_param_t; +/** + * Enqueue an event to a queue with selected vector context + * + * Within a queue event order may vary depending on the vector context. + */ +int odp_queue_enq_vector(odp_queue_t queue, uint32_t vector_id, odp_event_t ev); + /** * Queue information * Retrieve information about a queue with odp_queue_info()