EM-ODP 4.4.0
Event Machine on ODP
Loading...
Searching...
No Matches
em_error.c
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 * EM Error Handling
33 */
34
35#ifndef _GNU_SOURCE
36#define _GNU_SOURCE
37#endif
38
39#ifdef HAVE_CONFIG_H
40#include "config.h"
41#endif
42
43#include <libgen.h> /* basename() */
44#include <stdarg.h>
45#include <stdbool.h>
46#include <stddef.h>
47#include <stdint.h>
48#include <stdio.h>
49#include <stdlib.h>
50#include <string.h>
51
52#include <odp_api.h>
53#include <odp/helper/odph_api.h>
54
55#include <event_machine.h>
57
58#include "em_eo.h"
59#include "em_eo_types.h"
60#include "em_error.h"
61#include "em_error_types.h"
62#include "em_event_types.h"
63#include "em_libconfig.h"
64#include "em_mem.h"
65#include "em_queue_types.h"
66
67static int error_handler_initialized; /* static always initialized to 0 */
68
69static early_log_t early_log = {default_log, vdefault_log};
70
71static em_status_t early_error_handler(em_eo_t eo, em_status_t error,
72 em_escope_t escope, va_list args);
73
74/* String names for em_status_e (index = enum value). */
75static const char *const err_status_name_tbl[] = {
76#define ERR_STR(name)\
77 [name] = #name
78
79 /* Keep the order same as in em_status_e */
80 ERR_STR(EM_ERR_BAD_ARG),
81 ERR_STR(EM_ERR_BAD_STATE),
82 ERR_STR(EM_ERR_BAD_ID),
83 ERR_STR(EM_ERR_BAD_TYPE),
84 ERR_STR(EM_ERR_BAD_CONTEXT),
85 ERR_STR(EM_ERR_BAD_POINTER),
86 ERR_STR(EM_ERR_NOT_CREATED),
87 ERR_STR(EM_ERR_NOT_FREE),
88 ERR_STR(EM_ERR_NOT_FOUND),
91 ERR_STR(EM_ERR_NOT_SUPPORTED),
92 ERR_STR(EM_ERR_ALLOC_FAILED),
94 ERR_STR(EM_ERR_LIB_FAILED),
95 ERR_STR(EM_ERR_TOO_LARGE),
96 ERR_STR(EM_ERR_TOO_SMALL),
97 ERR_STR(EM_ERR_EVENT_STATE),
98 ERR_STR(EM_ERR_TIMEOUT),
99 ERR_STR(EM_ERR_TOONEAR),
100 ERR_STR(EM_ERR_TOOFAR),
101 ERR_STR(EM_ERR_CANCELED),
102 ERR_STR(EM_ERR_BUSY),
103 ERR_STR(EM_ERR)
104#undef ERR_STR
105};
106
107COMPILE_TIME_ASSERT(ODPH_ARRAY_SIZE(err_status_name_tbl) == EM_ERR + 1, ERR_TBL_SIZE);
108
109/* Make sure that EM internally used error scopes are "seen" by EM_ESCOPE() */
110COMPILE_TIME_ASSERT(EM_ESCOPE(EM_ESCOPE_API_MASK),
111 EM_ESCOPE_API_IS_NOT_PART_EM_ESCOPE__ERROR);
112COMPILE_TIME_ASSERT(EM_ESCOPE(EM_ESCOPE_INTERNAL_MASK),
113 EM_ESCOPE_INTERNAL_IS_NOT_PART_OF_EM_ESCOPE__ERROR);
114
115/*
116 * String names for em_escope_t - EM API escopes:
117 */
118#define ESCOPE_API_IDX(escope) ((escope) & ~EM_ESCOPE_API_MASK)
119
120static const char *const escope_api_name_tbl[EM_ESCOPE_API_LAST -
121 EM_ESCOPE_API_FIRST + 1] = {
122#define ESCOPE_API_STR(escope) \
123 [ESCOPE_API_IDX(escope)] = #escope
124
125 /* EM API escopes: Atomic Group */
126 ESCOPE_API_STR(EM_ESCOPE_ATOMIC_GROUP_CREATE),
127 ESCOPE_API_STR(EM_ESCOPE_ATOMIC_GROUP_DELETE),
128 ESCOPE_API_STR(EM_ESCOPE_ATOMIC_GROUP_FIND),
129 ESCOPE_API_STR(EM_ESCOPE_ATOMIC_GROUP_FIRST),
130 ESCOPE_API_STR(EM_ESCOPE_ATOMIC_GROUP_NAME),
131 ESCOPE_API_STR(EM_ESCOPE_ATOMIC_GROUP_NEXT),
132 ESCOPE_API_STR(EM_ESCOPE_ATOMIC_GROUP_QUEUE_FIRST),
133 ESCOPE_API_STR(EM_ESCOPE_ATOMIC_GROUP_QUEUE_NEXT),
134 ESCOPE_API_STR(EM_ESCOPE_QUEUE_CREATE_AG),
135 ESCOPE_API_STR(EM_ESCOPE_QUEUE_CREATE_STATIC_AG),
136 /* EM API escopes: Core */
137 ESCOPE_API_STR(EM_ESCOPE_CORE_COUNT),
138 ESCOPE_API_STR(EM_ESCOPE_CORE_ID),
139 /* EM API escopes: Dispatcher */
140 ESCOPE_API_STR(EM_ESCOPE_DISPATCH),
141 ESCOPE_API_STR(EM_ESCOPE_DISPATCH_DURATION),
142 ESCOPE_API_STR(EM_ESCOPE_DISPATCH_EVENTS),
143 ESCOPE_API_STR(EM_ESCOPE_DISPATCH_NS),
144 ESCOPE_API_STR(EM_ESCOPE_DISPATCH_OPT_INIT),
145 ESCOPE_API_STR(EM_ESCOPE_DISPATCH_REGISTER_ENTER_CB),
146 ESCOPE_API_STR(EM_ESCOPE_DISPATCH_REGISTER_EXIT_CB),
147 ESCOPE_API_STR(EM_ESCOPE_DISPATCH_ROUNDS),
148 ESCOPE_API_STR(EM_ESCOPE_DISPATCH_UNREGISTER_ENTER_CB),
149 ESCOPE_API_STR(EM_ESCOPE_DISPATCH_UNREGISTER_EXIT_CB),
150 /* EM API escopes: EO */
151 ESCOPE_API_STR(EM_ESCOPE_EO_ADD_QUEUE),
152 ESCOPE_API_STR(EM_ESCOPE_EO_ADD_QUEUE_SYNC),
153 ESCOPE_API_STR(EM_ESCOPE_EO_CONTEXT),
154 ESCOPE_API_STR(EM_ESCOPE_EO_CREATE),
155 ESCOPE_API_STR(EM_ESCOPE_EO_CREATE_MULTIRCV),
156 ESCOPE_API_STR(EM_ESCOPE_EO_CREATE_PARAM),
157 ESCOPE_API_STR(EM_ESCOPE_EO_CURRENT),
158 ESCOPE_API_STR(EM_ESCOPE_EO_DELETE),
159 ESCOPE_API_STR(EM_ESCOPE_EO_FIND),
160 ESCOPE_API_STR(EM_ESCOPE_EO_FIRST),
161 ESCOPE_API_STR(EM_ESCOPE_EO_MULTIRCV_PARAM_INIT),
162 ESCOPE_API_STR(EM_ESCOPE_EO_NAME),
163 ESCOPE_API_STR(EM_ESCOPE_EO_NEXT),
164 ESCOPE_API_STR(EM_ESCOPE_EO_PARAM_INIT),
165 ESCOPE_API_STR(EM_ESCOPE_EO_QUEUE_FIRST),
166 ESCOPE_API_STR(EM_ESCOPE_EO_QUEUE_NEXT),
167 ESCOPE_API_STR(EM_ESCOPE_EO_REGISTER_ERROR_HANDLER),
168 ESCOPE_API_STR(EM_ESCOPE_EO_REMOVE_QUEUE),
169 ESCOPE_API_STR(EM_ESCOPE_EO_REMOVE_QUEUE_ALL),
170 ESCOPE_API_STR(EM_ESCOPE_EO_REMOVE_QUEUE_ALL_SYNC),
171 ESCOPE_API_STR(EM_ESCOPE_EO_REMOVE_QUEUE_SYNC),
172 ESCOPE_API_STR(EM_ESCOPE_EO_START),
173 ESCOPE_API_STR(EM_ESCOPE_EO_START_SYNC),
174 ESCOPE_API_STR(EM_ESCOPE_EO_STATE),
175 ESCOPE_API_STR(EM_ESCOPE_EO_STOP),
176 ESCOPE_API_STR(EM_ESCOPE_EO_STOP_SYNC),
177 ESCOPE_API_STR(EM_ESCOPE_EO_UNREGISTER_ERROR_HANDLER),
178 /* EM API escopes: Error */
179 ESCOPE_API_STR(EM_ESCOPE_ERROR),
180 ESCOPE_API_STR(EM_ESCOPE_REGISTER_ERROR_HANDLER),
181 ESCOPE_API_STR(EM_ESCOPE_UNREGISTER_ERROR_HANDLER),
182 /* EM API escopes: Event Group */
183 ESCOPE_API_STR(EM_ESCOPE_EVENT_GROUP_ABORT),
184 ESCOPE_API_STR(EM_ESCOPE_EVENT_GROUP_APPLY),
185 ESCOPE_API_STR(EM_ESCOPE_EVENT_GROUP_ASSIGN),
186 ESCOPE_API_STR(EM_ESCOPE_EVENT_GROUP_CREATE),
187 ESCOPE_API_STR(EM_ESCOPE_EVENT_GROUP_CURRENT),
188 ESCOPE_API_STR(EM_ESCOPE_EVENT_GROUP_DELETE),
189 ESCOPE_API_STR(EM_ESCOPE_EVENT_GROUP_FIRST),
190 ESCOPE_API_STR(EM_ESCOPE_EVENT_GROUP_INCREMENT),
191 ESCOPE_API_STR(EM_ESCOPE_EVENT_GROUP_IS_READY),
192 ESCOPE_API_STR(EM_ESCOPE_EVENT_GROUP_NEXT),
193 ESCOPE_API_STR(EM_ESCOPE_EVENT_GROUP_NOTIF),
194 ESCOPE_API_STR(EM_ESCOPE_EVENT_GROUP_PROCESSING_END),
195 ESCOPE_API_STR(EM_ESCOPE_SEND_GROUP),
196 ESCOPE_API_STR(EM_ESCOPE_SEND_GROUP_MULTI),
197 /* EM API escopes: Event */
198 ESCOPE_API_STR(EM_ESCOPE_ALLOC),
199 ESCOPE_API_STR(EM_ESCOPE_ALLOC_MULTI),
200 ESCOPE_API_STR(EM_ESCOPE_EVENT_CLONE),
201 ESCOPE_API_STR(EM_ESCOPE_EVENT_CLONE_PART),
202 ESCOPE_API_STR(EM_ESCOPE_EVENT_HAS_REF),
203 ESCOPE_API_STR(EM_ESCOPE_EVENT_MARK_FREE),
204 ESCOPE_API_STR(EM_ESCOPE_EVENT_MARK_FREE_MULTI),
205 ESCOPE_API_STR(EM_ESCOPE_EVENT_MARK_SEND),
206 ESCOPE_API_STR(EM_ESCOPE_EVENT_POINTER),
207 ESCOPE_API_STR(EM_ESCOPE_EVENT_POINTER_AND_SIZE),
208 ESCOPE_API_STR(EM_ESCOPE_EVENT_POOL),
209 ESCOPE_API_STR(EM_ESCOPE_EVENT_POOL_SUBPOOL),
210 ESCOPE_API_STR(EM_ESCOPE_EVENT_REF),
211 ESCOPE_API_STR(EM_ESCOPE_EVENT_SAME_TYPE_MULTI),
212 ESCOPE_API_STR(EM_ESCOPE_EVENT_SET_TYPE),
213 ESCOPE_API_STR(EM_ESCOPE_EVENT_SIZE),
214 ESCOPE_API_STR(EM_ESCOPE_EVENT_TYPE),
215 ESCOPE_API_STR(EM_ESCOPE_EVENT_TYPE_MULTI),
216 ESCOPE_API_STR(EM_ESCOPE_EVENT_UAREA),
217 ESCOPE_API_STR(EM_ESCOPE_EVENT_UAREA_ID),
218 ESCOPE_API_STR(EM_ESCOPE_EVENT_UAREA_ID_SET),
219 ESCOPE_API_STR(EM_ESCOPE_EVENT_UAREA_INFO),
220 ESCOPE_API_STR(EM_ESCOPE_EVENT_UNMARK_FREE),
221 ESCOPE_API_STR(EM_ESCOPE_EVENT_UNMARK_FREE_MULTI),
222 ESCOPE_API_STR(EM_ESCOPE_EVENT_UNMARK_SEND),
223 ESCOPE_API_STR(EM_ESCOPE_EVENT_VECTOR_FREE),
224 ESCOPE_API_STR(EM_ESCOPE_EVENT_VECTOR_INFO),
225 ESCOPE_API_STR(EM_ESCOPE_EVENT_VECTOR_MAX_SIZE),
226 ESCOPE_API_STR(EM_ESCOPE_EVENT_VECTOR_SIZE),
227 ESCOPE_API_STR(EM_ESCOPE_EVENT_VECTOR_SIZE_SET),
228 ESCOPE_API_STR(EM_ESCOPE_EVENT_VECTOR_TBL),
229 ESCOPE_API_STR(EM_ESCOPE_EVENT_VECTOR_TYPE),
230 ESCOPE_API_STR(EM_ESCOPE_EVENT_VECTOR_TYPE_SET),
231 ESCOPE_API_STR(EM_ESCOPE_FREE),
232 ESCOPE_API_STR(EM_ESCOPE_FREE_MULTI),
233 ESCOPE_API_STR(EM_ESCOPE_SEND),
234 ESCOPE_API_STR(EM_ESCOPE_SEND_MULTI),
235 /* EM API escopes: Event Packet */
236 ESCOPE_API_STR(EM_ESCOPE_PACKET_HEADROOM),
237 ESCOPE_API_STR(EM_ESCOPE_PACKET_POINTER),
238 ESCOPE_API_STR(EM_ESCOPE_PACKET_POINTER_AND_SIZE),
239 ESCOPE_API_STR(EM_ESCOPE_PACKET_PULL_HEAD),
240 ESCOPE_API_STR(EM_ESCOPE_PACKET_PULL_TAIL),
241 ESCOPE_API_STR(EM_ESCOPE_PACKET_PUSH_HEAD),
242 ESCOPE_API_STR(EM_ESCOPE_PACKET_PUSH_TAIL),
243 ESCOPE_API_STR(EM_ESCOPE_PACKET_RESET),
244 ESCOPE_API_STR(EM_ESCOPE_PACKET_RESIZE),
245 ESCOPE_API_STR(EM_ESCOPE_PACKET_SIZE),
246 ESCOPE_API_STR(EM_ESCOPE_PACKET_TAILROOM),
247 ESCOPE_API_STR(EM_ESCOPE_PACKET_CONCAT),
248 /* EM API escopes: Hooks */
249 ESCOPE_API_STR(EM_ESCOPE_HOOKS_REGISTER_ALLOC),
250 ESCOPE_API_STR(EM_ESCOPE_HOOKS_REGISTER_FREE),
251 ESCOPE_API_STR(EM_ESCOPE_HOOKS_REGISTER_SEND),
252 ESCOPE_API_STR(EM_ESCOPE_HOOKS_REGISTER_TO_ACTIVE),
253 ESCOPE_API_STR(EM_ESCOPE_HOOKS_REGISTER_TO_IDLE),
254 ESCOPE_API_STR(EM_ESCOPE_HOOKS_REGISTER_WHILE_IDLE),
255 ESCOPE_API_STR(EM_ESCOPE_HOOKS_UNREGISTER_ALLOC),
256 ESCOPE_API_STR(EM_ESCOPE_HOOKS_UNREGISTER_FREE),
257 ESCOPE_API_STR(EM_ESCOPE_HOOKS_UNREGISTER_SEND),
258 ESCOPE_API_STR(EM_ESCOPE_HOOKS_UNREGISTER_TO_ACTIVE),
259 ESCOPE_API_STR(EM_ESCOPE_HOOKS_UNREGISTER_TO_IDLE),
260 ESCOPE_API_STR(EM_ESCOPE_HOOKS_UNREGISTER_WHILE_IDLE),
261 /* EM API escopes: Init / Term */
262 ESCOPE_API_STR(EM_ESCOPE_CONF_INIT),
263 ESCOPE_API_STR(EM_ESCOPE_CONF_LOCAL_INIT),
264 ESCOPE_API_STR(EM_ESCOPE_CONF_OPTS),
265 ESCOPE_API_STR(EM_ESCOPE_CONF_LOCAL_OPTS),
266 ESCOPE_API_STR(EM_ESCOPE_INIT),
267 ESCOPE_API_STR(EM_ESCOPE_INIT_CORE),
268 ESCOPE_API_STR(EM_ESCOPE_INIT_LOCAL),
269 ESCOPE_API_STR(EM_ESCOPE_TERM),
270 ESCOPE_API_STR(EM_ESCOPE_TERM_CORE),
271 ESCOPE_API_STR(EM_ESCOPE_TERM_LOCAL),
272 ESCOPE_API_STR(EM_ESCOPE_TERM_LOCAL_INIT),
273 ESCOPE_API_STR(EM_ESCOPE_CFGFILE_OPTS),
274 /* EM API escopes: Pool */
275 ESCOPE_API_STR(EM_ESCOPE_POOL_CFG_INIT),
276 ESCOPE_API_STR(EM_ESCOPE_POOL_CREATE),
277 ESCOPE_API_STR(EM_ESCOPE_POOL_DELETE),
278 ESCOPE_API_STR(EM_ESCOPE_POOL_FIND),
279 ESCOPE_API_STR(EM_ESCOPE_POOL_FIRST),
280 ESCOPE_API_STR(EM_ESCOPE_POOL_INFO),
281 ESCOPE_API_STR(EM_ESCOPE_POOL_NAME),
282 ESCOPE_API_STR(EM_ESCOPE_POOL_NEXT),
283 ESCOPE_API_STR(EM_ESCOPE_POOL_NUM_SUBPOOLS),
284 ESCOPE_API_STR(EM_ESCOPE_POOL_STATS),
285 ESCOPE_API_STR(EM_ESCOPE_POOL_STATS_RESET),
286 ESCOPE_API_STR(EM_ESCOPE_POOL_STATS_SELECTED),
287 ESCOPE_API_STR(EM_ESCOPE_POOL_SUBPOOL_STATS),
288 ESCOPE_API_STR(EM_ESCOPE_POOL_SUBPOOL_STATS_RESET),
289 ESCOPE_API_STR(EM_ESCOPE_POOL_SUBPOOL_STATS_SELECTED),
290 ESCOPE_API_STR(EM_ESCOPE_POOL_STATS_OPT),
291 /* EM API escopes: Queue Group */
292 ESCOPE_API_STR(EM_ESCOPE_QUEUE_GROUP_CREATE),
293 ESCOPE_API_STR(EM_ESCOPE_QUEUE_GROUP_CREATE_SYNC),
294 ESCOPE_API_STR(EM_ESCOPE_QUEUE_GROUP_DELETE),
295 ESCOPE_API_STR(EM_ESCOPE_QUEUE_GROUP_DELETE_SYNC),
296 ESCOPE_API_STR(EM_ESCOPE_QUEUE_GROUP_FIND),
297 ESCOPE_API_STR(EM_ESCOPE_QUEUE_GROUP_FIRST),
298 ESCOPE_API_STR(EM_ESCOPE_QUEUE_GROUP_MASK),
299 ESCOPE_API_STR(EM_ESCOPE_QUEUE_GROUP_MODIFY),
300 ESCOPE_API_STR(EM_ESCOPE_QUEUE_GROUP_MODIFY_SYNC),
301 ESCOPE_API_STR(EM_ESCOPE_QUEUE_GROUP_NAME),
302 ESCOPE_API_STR(EM_ESCOPE_QUEUE_GROUP_NEXT),
303 ESCOPE_API_STR(EM_ESCOPE_QUEUE_GROUP_QUEUE_FIRST),
304 ESCOPE_API_STR(EM_ESCOPE_QUEUE_GROUP_QUEUE_NEXT),
305 /* EM API escopes: Queue */
306 ESCOPE_API_STR(EM_ESCOPE_QUEUE_AGGR_CONF_INIT),
307 ESCOPE_API_STR(EM_ESCOPE_QUEUE_AGGR),
308 ESCOPE_API_STR(EM_ESCOPE_QUEUE_AGGR_INFO),
309 ESCOPE_API_STR(EM_ESCOPE_QUEUE_AGGR_LIST),
310 ESCOPE_API_STR(EM_ESCOPE_QUEUE_AGGR_NUM),
311 ESCOPE_API_STR(EM_ESCOPE_QUEUE_AGROUP),
312 ESCOPE_API_STR(EM_ESCOPE_QUEUE_CONTEXT),
313 ESCOPE_API_STR(EM_ESCOPE_QUEUE_CREATE),
314 ESCOPE_API_STR(EM_ESCOPE_QUEUE_CREATE_STATIC),
315 ESCOPE_API_STR(EM_ESCOPE_QUEUE_CREATE_PARAM),
316 ESCOPE_API_STR(EM_ESCOPE_QUEUE_CURRENT),
317 ESCOPE_API_STR(EM_ESCOPE_QUEUE_DELETE),
318 ESCOPE_API_STR(EM_ESCOPE_QUEUE_DEQUEUE),
319 ESCOPE_API_STR(EM_ESCOPE_QUEUE_DEQUEUE_MULTI),
320 ESCOPE_API_STR(EM_ESCOPE_QUEUE_FIND),
321 ESCOPE_API_STR(EM_ESCOPE_QUEUE_FIRST),
322 ESCOPE_API_STR(EM_ESCOPE_QUEUE_INDEX),
323 ESCOPE_API_STR(EM_ESCOPE_QUEUE_NAME),
324 ESCOPE_API_STR(EM_ESCOPE_QUEUE_NEXT),
325 ESCOPE_API_STR(EM_ESCOPE_QUEUE_NUM_PRIO),
326 ESCOPE_API_STR(EM_ESCOPE_QUEUE_PARAM_INIT),
327 ESCOPE_API_STR(EM_ESCOPE_QUEUE_PRIORITY),
328 ESCOPE_API_STR(EM_ESCOPE_QUEUE_QGROUP),
329 ESCOPE_API_STR(EM_ESCOPE_QUEUE_SET_CONTEXT),
330 ESCOPE_API_STR(EM_ESCOPE_QUEUE_TYPE),
331 ESCOPE_API_STR(EM_ESCOPE_QUEUE_STATIC_HANDLE),
332 /* EM API escopes: Scheduler */
333 ESCOPE_API_STR(EM_ESCOPE_ATOMIC_PROCESSING_END),
334 ESCOPE_API_STR(EM_ESCOPE_ORDERED_PROCESSING_END),
335 ESCOPE_API_STR(EM_ESCOPE_PRESCHEDULE),
336 ESCOPE_API_STR(EM_ESCOPE_SCHED_CONTEXT_TYPE_CURRENT),
337 /* EM API escopes: Timer */
338 ESCOPE_API_STR(EM_ESCOPE_TIMER_ALL),
339 ESCOPE_API_STR(EM_ESCOPE_TIMER_ATTR),
340 ESCOPE_API_STR(EM_ESCOPE_TIMER_ATTR_INIT),
341 ESCOPE_API_STR(EM_ESCOPE_TIMER_CAPABILITY),
342 ESCOPE_API_STR(EM_ESCOPE_TIMER_CREATE),
343 ESCOPE_API_STR(EM_ESCOPE_TIMER_CUR_TICK),
344 ESCOPE_API_STR(EM_ESCOPE_TIMER_DELETE),
345 ESCOPE_API_STR(EM_ESCOPE_TIMER_FREQ),
346 ESCOPE_API_STR(EM_ESCOPE_TIMER_NS_TO_TICK),
347 ESCOPE_API_STR(EM_ESCOPE_TIMER_RES_CAPABILITY),
348 ESCOPE_API_STR(EM_ESCOPE_TIMER_RING_CREATE),
349 ESCOPE_API_STR(EM_ESCOPE_TIMER_RING_FREQ_CREATE),
350 ESCOPE_API_STR(EM_ESCOPE_TIMER_TICK_TO_NS),
351 ESCOPE_API_STR(EM_ESCOPE_TMO_ACK),
352 ESCOPE_API_STR(EM_ESCOPE_TMO_CANCEL),
353 ESCOPE_API_STR(EM_ESCOPE_TMO_CREATE),
354 ESCOPE_API_STR(EM_ESCOPE_TMO_CREATE_ARG),
355 ESCOPE_API_STR(EM_ESCOPE_TMO_DELETE),
356 ESCOPE_API_STR(EM_ESCOPE_TMO_SET_ABS),
357 ESCOPE_API_STR(EM_ESCOPE_TMO_SET_PERIODIC),
358 ESCOPE_API_STR(EM_ESCOPE_TMO_SET_PERIODIC_RING),
359 ESCOPE_API_STR(EM_ESCOPE_TMO_SET_PERIODIC_RING_FREQ),
360 ESCOPE_API_STR(EM_ESCOPE_TMO_SET_REL),
361 ESCOPE_API_STR(EM_ESCOPE_TMO_STATE),
362 ESCOPE_API_STR(EM_ESCOPE_TMO_STATS),
363 ESCOPE_API_STR(EM_ESCOPE_TMO_TIMER),
364 ESCOPE_API_STR(EM_ESCOPE_TMO_TYPE),
365 ESCOPE_API_STR(EM_ESCOPE_TMO_USERPTR),
366 ESCOPE_API_STR(EM_ESCOPE_TMO_RING_ACK)
367
368#undef ESCOPE_API_STR
369};
370
371COMPILE_TIME_ASSERT(ODPH_ARRAY_SIZE(escope_api_name_tbl) <=
372 ESCOPE_API_IDX(EM_ESCOPE_API_LAST) + 1, ERR_ESCOPE_API_TBL_SIZE);
373
374/*
375 * String names for em_escope_t - EM internal escopes:
376 */
377#define ESCOPE_INTERNAL_IDX(escope) ((escope) & ~EM_ESCOPE_INTERNAL_MASK)
378
379static const char *const escope_internal_name_tbl[EM_ESCOPE_INTERNAL_LAST -
380 EM_ESCOPE_INTERNAL_FIRST + 1] = {
381#define ESCOPE_INTERNAL_STR(escope) \
382 [ESCOPE_INTERNAL_IDX(escope)] = #escope
383
384 /* EM internal escopes: Event Chaining */
385 ESCOPE_INTERNAL_STR(EM_ESCOPE_EVENT_SEND_DEVICE),
386 ESCOPE_INTERNAL_STR(EM_ESCOPE_EVENT_SEND_DEVICE_MULTI),
387 /* EM internal escopes: Event Group */
388 ESCOPE_INTERNAL_STR(EM_ESCOPE_EVENT_GROUP_UPDATE),
389 ESCOPE_INTERNAL_STR(EM_ESCOPE_EVENT_GROUP_UPDATE_PRECNT),
390 ESCOPE_INTERNAL_STR(EM_ESCOPE_EVENT_GROUP_UPDATE_POSTCNT),
391 /* EM internal escopes: EO */
392 ESCOPE_INTERNAL_STR(EM_ESCOPE_EO_LOCAL_FUNC_CALL_REQ),
393 ESCOPE_INTERNAL_STR(EM_ESCOPE_EO_REMOVE_QUEUE_ALL_DONE_CB),
394 ESCOPE_INTERNAL_STR(EM_ESCOPE_EO_REMOVE_QUEUE_ALL_SYNC_DONE_CB),
395 ESCOPE_INTERNAL_STR(EM_ESCOPE_EO_REMOVE_QUEUE_DONE_CB),
396 ESCOPE_INTERNAL_STR(EM_ESCOPE_EO_REMOVE_QUEUE_SYNC_DONE_CB),
397 ESCOPE_INTERNAL_STR(EM_ESCOPE_EO_START_DONE_CB),
398 ESCOPE_INTERNAL_STR(EM_ESCOPE_EO_START_SYNC_DONE_CB),
399 ESCOPE_INTERNAL_STR(EM_ESCOPE_EO_STOP_DONE_CB),
400 ESCOPE_INTERNAL_STR(EM_ESCOPE_EO_STOP_SYNC_DONE_CB),
401 /* EM internal escopes: Queue */
402 ESCOPE_INTERNAL_STR(EM_ESCOPE_QUEUE_DISABLE),
403 ESCOPE_INTERNAL_STR(EM_ESCOPE_QUEUE_DISABLE_ALL),
404 ESCOPE_INTERNAL_STR(EM_ESCOPE_QUEUE_ENABLE),
405 ESCOPE_INTERNAL_STR(EM_ESCOPE_QUEUE_ENABLE_ALL),
406 ESCOPE_INTERNAL_STR(EM_ESCOPE_QUEUE_STATE_CHANGE),
407 /* EM internal escopes: Queue Groups */
408 ESCOPE_INTERNAL_STR(EM_ESCOPE_QUEUE_GROUP_ADD_CORE),
409 ESCOPE_INTERNAL_STR(EM_ESCOPE_QUEUE_GROUP_REM_CORE),
410 /* EM internal escopes: Other */
411 ESCOPE_INTERNAL_STR(EM_ESCOPE_DELETE_CTRL_QUEUES),
412 ESCOPE_INTERNAL_STR(EM_ESCOPE_EVENT_INTERNAL_DONE),
413 ESCOPE_INTERNAL_STR(EM_ESCOPE_EVENT_INTERNAL_LFUNC_CALL),
414 ESCOPE_INTERNAL_STR(EM_ESCOPE_INTERNAL_DONE_W_NOTIF_REQ),
415 ESCOPE_INTERNAL_STR(EM_ESCOPE_INTERNAL_EVENT_RECV_FUNC),
416 ESCOPE_INTERNAL_STR(EM_ESCOPE_INTERNAL_NOTIF),
417 ESCOPE_INTERNAL_STR(EM_ESCOPE_SEND_CTRL_QUEUE),
418 /* EM ODP extensions error scope */
419 ESCOPE_INTERNAL_STR(EM_ESCOPE_ODP_EXT)
420
421#undef ESCOPE_INTERNAL_STR
422};
423
424COMPILE_TIME_ASSERT(ODPH_ARRAY_SIZE(escope_internal_name_tbl) <=
425 ESCOPE_INTERNAL_IDX(EM_ESCOPE_INTERNAL_LAST) + 1, ERR_ESCOPE_INTERNAL_TBL_SIZE);
426
427const char *err_status_str(em_status_t status)
428{
429 if (status < ODPH_ARRAY_SIZE(err_status_name_tbl) &&
430 err_status_name_tbl[status] /*avoid gaps*/)
431 return err_status_name_tbl[status];
432
433 return "Unknown ERROR";
434}
435
436const char *escope_api_str(em_escope_t escope)
437{
438 uint32_t escope_idx = ESCOPE_API_IDX(escope);
439
440 if (EM_ESCOPE_API(escope) &&
441 escope_idx < ODPH_ARRAY_SIZE(escope_api_name_tbl) &&
442 escope_api_name_tbl[escope_idx] /*avoid gaps*/)
443 return escope_api_name_tbl[escope_idx];
444
445 return "Unknown ESCOPE";
446}
447
448const char *escope_internal_str(em_escope_t escope)
449{
450 uint32_t escope_idx = ESCOPE_INTERNAL_IDX(escope);
451
452 if (EM_ESCOPE_INTERNAL(escope) &&
453 escope_idx < ODPH_ARRAY_SIZE(escope_internal_name_tbl) &&
454 escope_internal_name_tbl[escope_idx] /*avoid gaps*/)
455 return escope_internal_name_tbl[escope_idx];
456
457 return "Unknown ESCOPE";
458}
459
460const char *escope_addon_api_str(em_escope_t escope)
461{
462 if (EM_ESCOPE_ADDON_API(escope))
463 return "EM Add-on API ESCOPE";
464
465 return "Unknown ESCOPE";
466}
467
468/*
469 * Build an internal EM error message (EM_ESCOPE(escope)==true).
470 * Shared between early_error_handler() and default_error_handler() and the
471 * EM helper API em_error_format_string().
472 *
473 * Always '\0'-terminates the 'err_msg' string (if given and valid) but silently
474 * truncates messages longer than the size limit 'errmsg_sz - 1'.
475 *
476 * @return Number of chars written to 'err_msg' (excluding final '\0')
477 */
478size_t format_errmsg(em_status_t error, em_escope_t escope,
479 const char *eo_str, va_list args, bool early_mode,
480 char err_msg[/*out*/], size_t errmsg_sz)
481{
482 if (!err_msg || errmsg_sz == 0)
483 return 0;
484
485 err_msg[0] = '\0';
486
487 /*
488 * va_list contains: __FILE__, __func__, __LINE__, (user_fmt),
489 * ## __VA_ARGS__ as reported by the INTERNAL_ERROR macro
490 */
491 char *file = va_arg(args, char *);
492 const char *func = va_arg(args, const char *);
493 const int line = va_arg(args, const int);
494 const char *user_fmt = va_arg(args, const char *);
495 const char *base_file = basename(file);
496 const char *error_str = err_status_str(error);
497 const char *escope_str = "Unknown ESCOPE";
498 int n;
499
500 if (EM_ESCOPE_API(escope))
501 escope_str = escope_api_str(escope);
502 else if (EM_ESCOPE_INTERNAL(escope))
503 escope_str = escope_internal_str(escope);
504 else if (EM_ESCOPE_ADDON_API(escope))
505 escope_str = escope_addon_api_str(escope);
506
507 if (early_mode) {
508 int cpu_id = odp_cpu_id(); /* em_core_id() does not work here */
509
510 n = snprintf(err_msg, errmsg_sz,
511 "\nEM ERROR:0x%08X(%s) ESCOPE:0x%08X(%s) %s (Early Error)\n"
512 "cpu:%02d %s:%d %s()\n",
513 error, error_str, escope, escope_str, eo_str,
514 cpu_id, base_file, line, func);
515 } else {
516 const em_locm_t *locm = &em_locm;
517 const uint64_t global_err_cnt = load_global_err_cnt();
518 const uint64_t local_err_cnt = locm->error_count;
519 const int core_id = locm->core_id;
520
521 n = snprintf(err_msg, errmsg_sz,
522 "\nEM ERROR:0x%08X(%s) ESCOPE:0x%08X(%s) %s\n"
523 "core:%02d ecount:%" PRIu64 "(%" PRIu64 ") %s:%d %s()\n",
524 error, error_str, escope, escope_str, eo_str,
525 core_id, global_err_cnt, local_err_cnt, base_file, line, func);
526 }
527
528 if (unlikely(n < 0))
529 return 0;
530 else if (unlikely((size_t)n >= errmsg_sz - 1))
531 return errmsg_sz - 1; /* truncated or all used */
532
533 if (!user_fmt)
534 return (size_t)n;
535
536 /*
537 * Append error-specific message since space left
538 */
539 size_t rem_sz = errmsg_sz - n;
540
541#pragma GCC diagnostic push
542#pragma GCC diagnostic ignored "-Wformat-nonliteral"
543 int m = vsnprintf(&err_msg[n], rem_sz, user_fmt, args);
544#pragma GCC diagnostic pop
545
546 if (unlikely(m < 0))
547 return (size_t)n; /* No user message appended */
548
549 if ((size_t)m >= rem_sz - 1)
550 return errmsg_sz - 1; /* truncated or all used */
551
552 int end = n + m; /* index of '\0' */
553
554 /* Add newline if space available */
555 if ((size_t)end + 1 < errmsg_sz) {
556 err_msg[end++] = '\n';
557 err_msg[end] = '\0';
558 }
559
560 return (size_t)end;
561}
562
563static void increment_global_err_cnt(void)
564{
565 odp_atomic_inc_u64(&em_shm->error_handler.global_error_count);
566}
567
568uint64_t load_global_err_cnt(void)
569{
570 return odp_atomic_load_u64(&em_shm->error_handler.global_error_count);
571}
572
573ODP_PRINTF_FORMAT(2, 0)
574int vdefault_log(em_log_level_t level, const char *fmt, va_list args)
575{
576 int r;
577 FILE *logfd;
578
579 switch (level) {
580 case EM_LOG_DBG:
581 case EM_LOG_PRINT:
582 logfd = stdout;
583 break;
584 default:
585 /* also level=EM_LOG_ERR */
586 logfd = stderr;
587 break;
588 }
589
590 r = vfprintf(logfd, fmt, args);
591 return r;
592}
593
594ODP_PRINTF_FORMAT(2, 3)
595int default_log(em_log_level_t level, const char *fmt, ...)
596{
597 va_list args;
598 int r;
599
600 va_start(args, fmt);
601 r = vdefault_log(level, fmt, args);
602 va_end(args);
603
604 return r;
605}
606
607/**
608 * Early EM Error Handler
609 *
610 * The early error handler is used when reporting errors at startup before
611 * the default, application and EO specific error handlers have been set up.
612 *
613 * @param eo unused
614 * @param error The error code (reason), see em_status_e
615 * @param escope The error scope from within the error was reported, also
616 * tells whether the error was EM internal or application
617 * specific
618 * @param args va_list of args
619 *
620 * @return The function may not return depending on implementation / error
621 * code / error scope. If it returns, the return value is the original
622 * (or modified) error code from the caller.
623 */
624static em_status_t early_error_handler(em_eo_t eo, em_status_t error,
625 em_escope_t escope, va_list args)
626{
627 em_log_func_t log_fn = early_log.log_fn;
628
629 (void)eo;
630
631 if (EM_ESCOPE(escope)) {
632 char err_msg[1024];
633
634 format_errmsg(error, escope, "EO:n/a", args, true /*early_mode*/,
635 err_msg /*out*/, sizeof(err_msg));
636 log_fn(EM_LOG_ERR, "%s", err_msg);
637 } else {
638 /* va_list from application - don't touch. */
639 int cpu_id = odp_cpu_id(); /* em_core_id() does not work here */
640
641 log_fn(EM_LOG_ERR, "\n"
642 "APPL ERROR:0x%08X ESCOPE:0x%08X (Early Error)\n"
643 "cpu:%02d\n", error, escope, cpu_id);
644 }
645
646 if (unlikely(EM_ERROR_IS_FATAL(error))) {
647 log_fn(EM_LOG_ERR,
648 "FATAL EM ERROR:0x%08X (Early Error) - ABORT!\n",
649 error);
650 abort();
651 }
652
653 return error;
654}
655
656/**
657 * Default EM Error Handler
658 *
659 * The default error handler is called upon error if the application(s)
660 * have not registered their own global and/or EO-specific error handlers
661 *
662 * @param eo EO reporting the error (if applicable)
663 * @param error The error code (reason), see em_status_e
664 * @param escope The error scope from within the error was reported, also
665 * tells whether the error was EM internal or application
666 * specific
667 * @param args va_list of args
668 *
669 * @return The function may not return depending on implementation / error
670 * code / error scope. If it returns, the return value is the original
671 * (or modified) error code from the caller.
672 */
673em_status_t default_error_handler(em_eo_t eo, em_status_t error,
674 em_escope_t escope, va_list args)
675{
676 char eo_str[sizeof("EO:xxxxxx-abdc ") + EM_EO_NAME_LEN];
677
678 if (eo == EM_EO_UNDEF) {
679 eo_str[0] = '\0';
680 } else {
681 char eo_name[EM_EO_NAME_LEN];
682 size_t nlen;
683
684 nlen = em_eo_name(eo, eo_name, sizeof(eo_name));
685 eo_name[nlen] = '\0';
686
687 snprintf(eo_str, sizeof(eo_str),
688 "EO:%" PRI_EO "-\"%s\" ", eo, eo_name);
689 eo_str[sizeof(eo_str) - 1] = '\0';
690 }
691
692 if (EM_ESCOPE(escope)) {
693 char err_msg[1024];
694
695 format_errmsg(error, escope, eo_str, args,
696 false /*not early_mode*/,
697 err_msg /*out*/, sizeof(err_msg));
698
699 EM_LOG(EM_LOG_ERR, "%s", err_msg);
700 } else {
701 /* va_list from application - don't touch. */
702 const uint64_t local_err_cnt = em_locm.error_count;
703 const uint64_t global_err_cnt = load_global_err_cnt();
704 const int core_id = em_core_id();
705
706 EM_LOG(EM_LOG_ERR, "\n"
707 "APPL ERROR:0x%08X ESCOPE:0x%08X %s\n"
708 "core:%02d ecount:%" PRIu64 "(%" PRIu64 ")\n",
709 error, escope, eo_str, core_id,
710 global_err_cnt, local_err_cnt);
711 }
712
713 if (unlikely(EM_ERROR_IS_FATAL(error))) {
714 EM_LOG(EM_LOG_ERR, "FATAL EM ERROR:0x%08X - ABORT!\n", error);
715 abort();
716 }
717
718 return error;
719}
720
721/**
722 * Select and call an error handler.
723 *
724 * @param error Error code
725 * @param escope Error scope. Identifies the scope for interpreting
726 * the error code and variable arguments.
727 * @param args_list Variable number and type of arguments
728 *
729 * @return Returns the 'error' argument given as input if the called error
730 * handler has not changed this value.
731 */
732em_status_t select_error_handler(em_status_t error, em_escope_t escope,
733 va_list args_list)
734{
735 if (unlikely(!error_handler_initialized || !em_shm)) {
736 /*
737 * Early errors reported at startup before error handling
738 * is properly initialized.
739 */
740 error = early_error_handler(EM_EO_UNDEF, error, escope, args_list);
741 return error;
742 }
743
744 em_error_handler_t error_handler;
745 em_error_handler_t eo_handler;
746 em_log_func_t log_fn = em_shm->log_fn;
747 const eo_elem_t *const eo_elem = eo_elem_current();
748 em_eo_t eo = EM_EO_UNDEF;
749
750 /* Global error handler, default or user registered */
751 error_handler = em_shm->error_handler.em_error_handler;
752
753 if (eo_elem && eo_allocated(eo_elem)) {
754 eo_handler = eo_elem->error_handler_func;
755 eo = eo_elem->eo;
756 if (eo_handler)
757 error_handler = eo_handler;
758 }
759
760 /* fallback, should never happen */
761 if (unlikely(error_handler == NULL)) {
762 error_handler = early_error_handler;
763 log_fn = early_log.log_fn; /* for the "FATAL EM ERROR:" below */
764 }
765
766 /*
767 * Call the selected error handler and possibly change the error code.
768 */
769 error = error_handler(eo, error, escope, args_list);
770
771 if (error != EM_OK) {
772 /* Increase the error count, used in logs/printouts */
773 increment_global_err_cnt();
774 em_locm.error_count += 1;
775 }
776
777 /*
778 * An error handler cannot return a fatal EM-error and continue running.
779 */
780 if (unlikely(EM_ESCOPE(escope) && EM_ERROR_IS_FATAL(error))) {
781 log_fn(EM_LOG_ERR,
782 "FATAL EM ERROR:0x%08X ESCOPE:0x%08X - ABORT!\n"
783 "EM: an error-handler must not return a fatal EM-error!",
784 error, escope);
785 abort();
786 }
787
788 /* Return input error or value changed by error_handler */
789 return error;
790}
791
792/**
793 * Called ONLY from INTERNAL_ERROR macro - do not use for anything else!
794 * internal_error((error), (escope), __FILE__, __func__, __LINE__,
795 * (user_fmt), ## __VA_ARGS__)
796 */
797em_status_t internal_error(em_status_t error, em_escope_t escope, ...)
798{
799 /*
800 * va_list contains:
801 * __FILE__, __func__, __LINE__, (user_fmt), ## __VA_ARGS__
802 */
803 va_list args;
804
805 va_start(args, escope);
806
807 /* Select and call an error handler. Possibly modifies the error code*/
808 error = select_error_handler(error, escope, args);
809
810 va_end(args);
811
812 /* Return input error or value changed by error_handler */
813 return error;
814}
815
816/**
817 * Initialize the EM Error Handling
818 */
819void error_init(void)
820{
821 odp_ticketlock_init(&em_shm->error_handler.lock);
822
823 em_shm->error_handler.em_error_handler = default_error_handler;
824
825 odp_atomic_init_u64(&em_shm->error_handler.global_error_count, 0);
826
827 em_shm->error_handler.initialized = 1; /* For API functions */
828 error_handler_initialized = 1; /* For early error handler select */
829}
830
831em_status_t early_log_init(em_log_func_t user_log_fn, em_vlog_func_t user_vlog_fn)
832{
833 /* Check that both log fns are either set or both NULL */
834 int is_log_null = user_log_fn == NULL;
835 int is_vlog_null = user_vlog_fn == NULL;
836
837 if (is_log_null != is_vlog_null)
838 return EM_ERR_BAD_POINTER;
839
840 /* store user provided log functions */
841 if (user_log_fn != NULL) {
842 early_log.log_fn = user_log_fn;
843 early_log.vlog_fn = user_vlog_fn;
844 }
845
846 return EM_OK;
847}
848
849void log_init(void)
850{
851 em_shm->log_fn = early_log.log_fn;
852 em_shm->vlog_fn = early_log.vlog_fn;
853}
ENV_LOCAL em_locm_t em_locm
em_shm_t * em_shm
#define EM_EO_NAME_LEN
#define PRI_EO
#define EM_EO_UNDEF
int em_core_id(void)
size_t em_eo_name(em_eo_t eo, char *name, size_t maxlen)
#define EM_OK
#define EM_ESCOPE_API_MASK
uint32_t em_escope_t
em_status_t(* em_error_handler_t)(em_eo_t eo, em_status_t error, em_escope_t escope, va_list args)
#define EM_ESCOPE_ADDON_API(escope)
#define EM_ESCOPE_INTERNAL(escope)
#define EM_ERROR_IS_FATAL(error)
#define EM_ESCOPE_INTERNAL_MASK
#define EM_ESCOPE_API(escope)
#define EM_ESCOPE(escope)
#define EM_ESCOPE_ODP_EXT
uint32_t em_status_t
int(* em_log_func_t)(em_log_level_t level, const char *fmt,...) __attribute__((format(printf
int(*) typedef int(* em_vlog_func_t)(em_log_level_t level, const char *fmt, va_list args)
@ EM_ERR_TOOFAR
@ EM_ERR_BUSY
@ EM_ERR_NOT_FOUND
@ EM_ERR_OPERATION_FAILED
@ EM_ERR_TOO_LARGE
@ EM_ERR_TIMEOUT
@ EM_ERR_EVENT_STATE
@ EM_ERR_BAD_ID
@ EM_ERR_CANCELED
@ EM_ERR_NOT_CREATED
@ EM_ERR_NOT_FREE
@ EM_ERR_TOO_SMALL
@ EM_ERR_BAD_CONTEXT
@ EM_ERR_ALLOC_FAILED
@ EM_ERR_BAD_ARG
@ EM_ERR_NOT_IMPLEMENTED
@ EM_ERR_NOT_SUPPORTED
@ EM_ERR_BAD_STATE
@ EM_ERR_BAD_TYPE
@ EM_ERR_TOONEAR
@ EM_ERR_LIB_FAILED
@ EM_ERR_NOT_INITIALIZED
@ EM_ERR_BAD_POINTER
int core_id
Definition em_mem.h:239
uint64_t error_count
Definition em_mem.h:277
em_log_func_t log_fn
Definition em_mem.h:89
em_vlog_func_t vlog_fn
Definition em_mem.h:91
em_error_handler_t error_handler_func
Definition em_eo_types.h:82
em_eo_t eo
Definition em_eo_types.h:94