EM-ODP 4.4.0
Event Machine on ODP
Loading...
Searching...
No Matches
em_queue.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2015-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
31/**
32 * @file
33 * EM internal queue functions
34 */
35
36#ifndef EM_QUEUE_H_
37#define EM_QUEUE_H_
38
39#include <stddef.h>
40#include <stdint.h>
41
42#include <odp_api.h>
43
44#include <event_machine.h>
45
46#include "em_eo_types.h"
47#include "em_event_inline.h"
48#include "em_mem.h"
49#include "em_queue_types.h"
50
51#ifdef __cplusplus
52extern "C" {
53#endif
54
55em_status_t queue_init(queue_tbl_t *const queue_tbl,
56 queue_pool_t *const queue_pool,
57 queue_pool_t *const queue_pool_static,
58 queue_pool_t *const queue_pool_aggr);
59
62
63em_queue_t queue_alloc(em_queue_t queue, const char **err_str /*out*/);
64em_status_t queue_free(em_queue_t queue);
65
66void queue_setup_common(const char *name, const em_queue_param_t *param,
67 queue_elem_t *q_elem /*in/out*/);
68
69em_queue_t queue_create_param(const char *name, const em_queue_param_t *param,
70 const char **err_str /*out*/);
71
72/**
73 * Apply em_queue_conf_t fields onto an em_queue_param_t.
74 *
75 * Maps 'flags', 'min_events' and (for output queues) 'output_conf' from
76 * 'conf' onto 'param'. If 'conf' is NULL, 'param' is left untouched so the
77 * defaults set by em_queue_param_init() remain in effect.
78 *
79 * 'param->type' must be set by the caller before calling this helper, as it
80 * controls whether 'output_conf' is copied.
81 */
82void queue_param_apply_conf(em_queue_param_t *param /*in,out*/,
83 const em_queue_conf_t *conf);
84
85em_status_t queue_delete(queue_elem_t *const queue_elem, const char **err_str /*out*/);
86
88
90
92
94
96 int is_setup /* vs. is_teardown */);
97em_status_t queue_state_change(queue_elem_t *const queue_elem, queue_state_t new_state);
98
100
101unsigned int queue_count(void);
102
103size_t queue_name(const queue_elem_t *const q_elem,
104 char name[/*out*/], const size_t maxlen);
105
106/** Print information about all EM queues */
107void print_queue_info(void);
108/** Print queue capabilities */
109void print_queue_capa(void);
110void print_queue_prio_info(void);
111void print_queue_elem_info(void);
112
113/** Get the string of a queue state */
114const char *queue_state_str(queue_state_t state);
115/** Get the string of a queue type */
116const char *queue_type_str(em_queue_type_t type);
117
118/**
119 * Enqueue multiple events into an unscheduled queue.
120 * Internal func, application should use em_send_multi() instead.
121 */
122static inline unsigned int
123queue_unsched_enqueue_multi(const em_event_t events[], int num,
124 const queue_elem_t *const q_elem)
125{
126 odp_event_t odp_events[num];
127 odp_queue_t odp_queue = q_elem->odp_queue;
128 int ret;
129
130 if (unlikely(EM_CHECK_LEVEL > 1 && odp_queue == ODP_QUEUE_INVALID))
131 return 0;
132
133 if (unlikely(EM_CHECK_LEVEL > 0 &&
134 q_elem->state != EM_QUEUE_STATE_UNSCHEDULED))
135 return 0;
136
137 events_em2odp(events, odp_events/*out*/, num);
138
139 /*
140 * Convert a vector's inner-event table to odp-form (drop evgen) before
141 * enqueue, but only for an aggregator-parent destination
142 * (flags.has_aggr): only its dequeue reads the inner table as raw odp
143 * events (esv_aggr_inner_em2usr()). A plain unscheduled queue's dequeue
144 * is scalar and the user read / em_free() paths are evgen-tolerant, so
145 * the conversion would be dead work there. Mirrors the has_aggr-gated
146 * dequeue in queue_dequeue_multi().
147 *
148 * Note: send_sched_multi() must convert unconditionally because
149 * flush_scheduler_events() force-scans leftover scheduled vectors
150 * regardless of has_aggr; unscheduled queues have no such flush path.
151 */
152 if (esv_enabled() && q_elem->flags.has_aggr) {
153 odp_event_type_t odp_etypes[num];
154
155 for (int i = 0; i < num; i++)
156 odp_etypes[i] = odp_event_type(odp_events[i]);
157
158 for (int i = 0; i < num; i++) {
159 if (odp_etypes[i] == ODP_EVENT_PACKET_VECTOR)
160 pktvec_tbl2odp(odp_events[i]);
161 else if (odp_etypes[i] == ODP_EVENT_VECTOR)
162 evvec_tbl2odp(odp_events[i]);
163 }
164
165 ret = odp_queue_enq_multi(odp_queue, odp_events, num);
166
167 if (likely(ret == num))
168 return num; /* Success! */
169
170 /* Restore the inner-table of the events that failed to enqueue */
171 int enq = ret < 0 ? 0 : ret;
172
173 for (int i = enq; i < num; i++) {
174 if (odp_etypes[i] == ODP_EVENT_PACKET_VECTOR)
175 pktvec_tbl2odp_revert(odp_events[i]);
176 else if (odp_etypes[i] == ODP_EVENT_VECTOR)
177 evvec_tbl2odp_revert(odp_events[i]);
178 }
179
180 return enq; /* enq < num */
181 }
182
183 /* No inner-table conversion needed (ESV off or non-aggregator queue) */
184 ret = odp_queue_enq_multi(odp_queue, odp_events, num);
185 if (unlikely(ret < 0))
186 return 0;
187
188 return ret;
189}
190
191/**
192 * Enqueue en event into an unscheduled queue.
193 * Internal func, application should use em_send() instead.
194 */
195static inline em_status_t
196queue_unsched_enqueue(em_event_t event, const queue_elem_t *const q_elem)
197{
198 odp_event_t odp_event = event_em2odp(event);
199 odp_queue_t odp_queue = q_elem->odp_queue;
200 int ret;
201
202 if (unlikely(EM_CHECK_LEVEL > 1 &&
203 (odp_event == ODP_EVENT_INVALID ||
204 odp_queue == ODP_QUEUE_INVALID)))
205 return EM_ERR_NOT_FOUND;
206
207 if (unlikely(EM_CHECK_LEVEL > 0 &&
208 q_elem->state != EM_QUEUE_STATE_UNSCHEDULED))
209 return EM_ERR_BAD_STATE;
210
211 /*
212 * Convert the vector inner-event table to odp-form before enqueue only
213 * for an aggregator-parent destination (flags.has_aggr); a plain
214 * unscheduled queue never reads it as raw odp. See
215 * queue_unsched_enqueue_multi() for the full rationale.
216 */
217 if (esv_enabled() && q_elem->flags.has_aggr) {
218 odp_event_type_t odp_etype = odp_event_type(odp_event);
219
220 if (odp_etype == ODP_EVENT_PACKET_VECTOR)
221 pktvec_tbl2odp(odp_event);
222 else if (odp_etype == ODP_EVENT_VECTOR)
223 evvec_tbl2odp(odp_event);
224
225 ret = odp_queue_enq(odp_queue, odp_event);
226 /*
227 * Always check the ODP enqueue result: this is a real runtime
228 * operation failure from the underlying library, not an optional
229 * EM_CHECK_LEVEL-controlled parameter/state validation.
230 */
231 if (unlikely(ret != 0)) {
232 /* Restore EM vector inner-table before returning to user */
233 if (odp_etype == ODP_EVENT_PACKET_VECTOR)
234 pktvec_tbl2odp_revert(odp_event);
235 else if (odp_etype == ODP_EVENT_VECTOR)
236 evvec_tbl2odp_revert(odp_event);
237
238 return EM_ERR_LIB_FAILED;
239 }
240
241 return EM_OK;
242 }
243
244 /* No inner-table conversion needed (ESV off or non-aggregator queue) */
245 ret = odp_queue_enq(odp_queue, odp_event);
246 if (unlikely(ret != 0))
247 return EM_ERR_LIB_FAILED;
248
249 return EM_OK;
250}
251
252static inline int
253next_local_queue_events(stash_entry_t entry_tbl[/*out*/], int num_events)
254{
255 em_locm_t *const locm = &em_locm;
256
257 if (locm->local_queues.empty)
258 return 0;
259
261
262 for (int i = 0; i < EM_QUEUE_PRIO_NUM; i++) {
263 /* from hi to lo prio: next prio if local queue is empty */
264 if (locm->local_queues.prio[prio].empty_prio) {
265 prio--;
266 continue;
267 }
268
269 odp_stash_t stash = locm->local_queues.prio[prio].stash;
270 int num = odp_stash_get_u64(stash, &entry_tbl[0].u64 /*[out]*/,
271 num_events);
272 if (num > 0)
273 return num;
274
275 locm->local_queues.prio[prio].empty_prio = 1;
276 prio--;
277 }
278
279 locm->local_queues.empty = 1;
280 return 0;
281}
282
283#ifdef __cplusplus
284}
285#endif
286
287#endif /* EM_QUEUE_H_ */
ENV_LOCAL em_locm_t em_locm
const char * queue_state_str(queue_state_t state)
Definition em_queue.c:2404
em_status_t queue_enable(queue_elem_t *const q_elem)
Definition em_queue.c:1953
void queue_param_apply_conf(em_queue_param_t *param, const em_queue_conf_t *conf)
Definition em_queue.c:1020
em_status_t queue_disable(queue_elem_t *const q_elem)
Definition em_queue.c:1992
em_status_t queue_term_local(void)
Definition em_queue.c:542
em_status_t queue_init(queue_tbl_t *const queue_tbl, queue_pool_t *const queue_pool, queue_pool_t *const queue_pool_static, queue_pool_t *const queue_pool_aggr)
Definition em_queue.c:330
em_status_t queue_disable_all(eo_elem_t *const eo_elem)
Definition em_queue.c:2012
void queue_setup_common(const char *name, const em_queue_param_t *param, queue_elem_t *q_elem)
Definition em_queue.c:1241
em_status_t queue_state_change(queue_elem_t *const queue_elem, queue_state_t new_state)
Definition em_queue.c:1905
em_queue_t queue_alloc(em_queue_t queue, const char **err_str)
Definition em_queue.c:598
const char * queue_type_str(em_queue_type_t type)
Definition em_queue.c:2432
em_status_t queue_state_change__check(queue_state_t old_state, queue_state_t new_state, int is_setup)
Definition em_queue.c:1853
em_status_t queue_enable_all(eo_elem_t *const eo_elem)
Definition em_queue.c:1973
em_status_t queue_state_change_all(eo_elem_t *const eo_elem, queue_state_t new_state)
Definition em_queue.c:1918
em_status_t queue_init_local(void)
Definition em_queue.c:474
void print_queue_capa(void)
Definition em_queue.c:2162
em_status_t queue_delete(queue_elem_t *const queue_elem, const char **err_str)
Definition em_queue.c:1080
void print_queue_info(void)
Definition em_queue.c:2480
uint8_t queue_state_t
#define EM_QUEUE_PRIO_NUM
#define EM_CHECK_LEVEL
#define EM_OK
uint32_t em_status_t
@ EM_ERR_NOT_FOUND
@ EM_ERR_BAD_STATE
@ EM_ERR_LIB_FAILED
uint32_t em_queue_type_t
uint32_t em_queue_prio_t
local_queues_t local_queues
Definition em_mem.h:241
odp_queue_t odp_queue
queue_state_t state
queue_elem_flags_t flags