EM-ODP 4.4.0
Event Machine on ODP
Loading...
Searching...
No Matches
event_machine_hooks.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2019-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#ifndef EVENT_MACHINE_HOOKS_H_
32#define EVENT_MACHINE_HOOKS_H_
33
34#pragma GCC visibility push(default)
35
36/**
37 * @file
38 * @defgroup em_hooks API-hooks and Idle hooks
39 * Event Machine API-callback hooks and Idle hooks.
40 * @{
41 *
42 * EM API-callback hook functions can be registered for a selected set of
43 * EM APIs. The EM APIs in question are mostly fast path APIs, like em_send(),
44 * em_alloc() and em_free(). Control APIs generally do not need hook support.
45 * A registered user provided hook function will be called by EM each time the
46 * corresponding API is called.
47 * API-callback hooks enables the user to gather statistics, trace program and
48 * event flow etc. API hooks should not change the state of the events etc.
49 * they receive as arguments, nor should they call the same API from within the
50 * hook to avoid hook recursion.
51 * Hook support is only available when EM_API_HOOKS_ENABLE != 0.
52 * Multiple API-callback hook functions (up to the number 'EM_CALLBACKS_MAX')
53 * can be registered for a given EM API. The calling order of multiple
54 * registered API hook functions is the order of registration. If the same
55 * function is registered twice then it will be called twice.
56 *
57 * EM Idle callback hook functions can be registered for tracking the idle state
58 * (ACTIVE/IDLE) of EM cores. Idle hooks can be used e.g. to gather application
59 * load statistics. The idle hooks are called by the EM dispatcher depending on
60 * whether the core gets events from scheduled or local queues. A core is in the
61 * ACTIVE state when it gets events from these queues. A core is in the IDLE
62 * state when it didn't get any events from these queues.
63 * To_idle hooks are called when a core state changes from ACTIVE to IDLE.
64 * To_active hooks are called when a core state changes from IDLE to ACTIVE.
65 * While_idle hooks are called when a core is already in the IDLE state and it
66 * doesn't get any events from scheduled or local queues. While_idle hooks can
67 * be called several times when a core is in the IDLE state.
68 * The user should not make any assumptions of the current idle state of the
69 * core when registering new idle hooks.
70 * The idle hook support is only available when EM_IDLE_HOOKS_ENABLE != 0.
71 * Multiple idle hook functions (up to the number 'EM_CALLBACKS_MAX') can be
72 * registered for each idle hook type. The calling order of multiple registered
73 * idle hook functions is the order of registration. If the same function is
74 * registered twice then it will be called twice.
75 *
76 * Do not include this file from the application, event_machine.h will
77 * do it for you.
78 */
79
83
84#ifdef __cplusplus
85extern "C" {
86#endif
87
88/**
89 * API-callback hook for em_alloc(), em_alloc_multi() and em_event_clone()
90 *
91 * The hook will only be called for successful event allocations, passing also
92 * the newly allocated 'events' to the hook.
93 * The state and ownership of the events must not be changed by the hook, e.g.
94 * the events must not be freed or sent etc. Calling em_alloc/_multi() within
95 * the alloc hook leads to hook recursion and must be avoided.
96 *
97 * @note em_alloc(): hook is called with events[1] and num_act = num_req = 1.
98 * @note em_alloc_multi(): hook is called with events[num_act] and
99 * num_req >= num_act >= 1
100 *
101 * API-callback hook functions can be called concurrently from different cores.
102 *
103 * @param[in] events[] Array of newly allocated events: 'events[num_act]'.
104 * Don't change the state of the array or the events!
105 * @param num_act The actual number of events allocated and written into
106 * 'events[]' (num_act <= num_req). This is the return val
107 * of em_alloc_multi() if at least one event was allocated
108 * (the hook is not called if no events were allocated).
109 * @param num_req The requested number of events to allocate,
110 * from em_alloc/_multi('num')
111 * @param size Event size >0, from em_alloc/_multi('size')
112 * @param type Event type to allocate, from em_alloc/_multi('type')
113 * @param pool Event pool handle, from em_alloc/_multi('pool')
114 *
115 * @see em_alloc(), em_alloc_multi() and em_hooks_register_alloc()
116 */
117typedef void (*em_api_hook_alloc_t)(const em_event_t events[/*num_act*/],
118 int num_act, int num_req, uint32_t size,
119 em_event_type_t type, em_pool_t pool);
120
121/**
122 * API-callback hook for em_free() and em_free_multi().
123 *
124 * The hook will be called before freeing the actual events, after verifying
125 * that the events given are valid, thus the hook does not 'see' if the actual
126 * free-operation succeeds or fails.
127 * The state and ownership of the events must not be changed by the hook, e.g.
128 * the events must not be freed or sent etc. Calling em_free/_multi() within the
129 * free hook leads to hook recursion and must be avoided.
130 *
131 * @note em_free(): hook is called with events[1] and num = 1.
132 * @note em_free_multi(): hook is called with events[num] and num >= 1
133 *
134 * API-callback hook functions can be called concurrently from different cores.
135 *
136 * @param[in] events[] Array of events to be freed: 'events[num]'
137 * Don't change the state of the array or the events!
138 * @param num The number of events in the array 'events[]'.
139 *
140 * @see em_free(), em_free_multi() and em_hooks_register_free()
141 */
142typedef void (*em_api_hook_free_t)(const em_event_t events[], int num);
143
144/**
145 * API-callback hook for em_send(), em_send_multi(), em_send_group() and
146 * em_send_group_multi().
147 *
148 * Sending multiple events with an event group is the most generic
149 * variant and thus one callback covers all.
150 * The hook will be called just before sending the actual event(s), thus
151 * the hook does not 'see' if the actual send operation succeeds or
152 * fails.
153 * The state and ownership of the events must not be changed by the
154 * hook, e.g. the events can not be freed or sent etc.
155 * Calling em_send...() within the send hook leads to hook recursion and
156 * must be avoided.
157 *
158 * API-callback hook functions can be called concurrently from different cores.
159 *
160 * @see em_send(), em_send_multi(), em_send_group(), em_send_group_multi()
161 */
162typedef void (*em_api_hook_send_t)(const em_event_t events[], int num,
163 em_queue_t queue,
164 em_event_group_t event_group);
165
166/**
167 * To idle hook
168 *
169 * The to_idle hook will be called by the EM dispatcher when a core is entering
170 * the IDLE state i.e. when the core doesn't get any new events to be processed.
171 * The to_idle hook is called only when there previously has been events to
172 * process and the state changes from active to idle.
173 *
174 * @param to_idle_delay_ns The delay in nanoseconds that a core was waiting
175 * for scheduled events before calling to_idle hook.
176 * The value might be a coarse approximation and
177 * should not be used for precise calculations.
178 */
179typedef void (*em_idle_hook_to_idle_t)(uint64_t to_idle_delay_ns);
180
181/**
182 * To active hook
183 *
184 * The to_active hook will be called by the EM dispatcher when a core is
185 * entering the ACTIVE state i.e. when the core gets events after being idle.
186 * The to_active hook is called only when the core previously has been in the
187 * IDLE state and the state changes to active. To_active hooks are called before
188 * the EO processes the events.
189 */
190typedef void (*em_idle_hook_to_active_t)(void);
191
192/**
193 * While idle hook
194 *
195 * The while_idle hook will be called by the EM dispatcher when a core is
196 * already in the IDLE state and stays in it i.e. the core doesn't get any
197 * events. The while_idle hook can be called several times until the core state
198 * changes to active i.e. the core again gets events for processing.
199 */
200typedef void (*em_idle_hook_while_idle_t)(void);
201
202/**
203 * API-callback hooks provided by the user at start-up (init)
204 *
205 * EM API functions will call an API hook if given by the user through this
206 * struct to em_init(). E.g. em_alloc() will call api_hooks->alloc(...) if
207 * api_hooks->alloc != NULL. Not all hooks need to be provided, use NULL for
208 * unused hooks.
209 *
210 * @note Not all EM API funcs have associated hooks, only the most used
211 * functions (in the fast path) are included.
212 * Notice that extensive usage or heavy processing in the hooks might
213 * significantly impact performance since each API call (that has a hook)
214 * will execute the extra code in the user provided hook.
215 *
216 * @note Only used if EM_API_HOOKS_ENABLE != 0
217 */
218typedef struct {
219 /**
220 * API callback hook for _all_ alloc-variants:
221 * em_alloc() and em_alloc_multi()
222 * Initialize to NULL if unused.
223 */
225
226 /**
227 * API callback hook for all free-variants:
228 * em_free() and em_free_multi()
229 * Initialize to NULL if unused.
230 */
232
233 /**
234 * API callback hook used for _all_ send-variants:
235 * em_send(), em_send_multi(), em_send_group() and em_send_group_multi()
236 * Initialize to NULL if unused.
237 */
240
241/**
242 * Idle hooks given by the user via this struct to the em_init() will be called
243 * by the EM dispatcher on each core.
244 *
245 * The EM dispatcher will call:
246 * - to_idle_hook when a core doesn't get any more events from scheduled or
247 * local queues after the core has been active
248 * - to_active_hook when a core gets events after being idle
249 * - while_idle_hook when a core continues being idle
250 *
251 * Not all the idle hooks need to be provided, use NULL for unused idle hooks.
252 *
253 * @note Notice that doing heavy processing in the hooks might significantly
254 * impact performance.
255 *
256 * @note Only used if EM_IDLE_HOOKS_ENABLE != 0
257 */
258typedef struct {
259 /**
260 * Idle hook called when entering the idle state
261 * Initialize to NULL if unused.
262 */
264 /**
265 * Idle hook called when entering the active state
266 * Initialize to NULL if unused.
267 */
269 /**
270 * Idle hook called while remaining in the idle state
271 * Initialize to NULL if unused.
272 */
275
276/**
277 * Register an API-callback hook for em_alloc().
278 *
279 * A registered hook will be called at the end of em_alloc(), but only for
280 * successful allocs, passing also the newly allocated 'event' to the hook.
281 * The state and ownership of the event must not be changed by the hook, e.g.
282 * the event must not be freed or sent etc. Calling em_alloc() within the
283 * alloc hook leads to hook recursion and must be avoided.
284 *
285 * API-callback hook functions can be called concurrently from different cores.
286 *
287 * Multiple API-callback hook functions (up to the number 'EM_CALLBACKS_MAX')
288 * can be registered.
289 * The order of calling multiple registered hook functions is the order of
290 * registration. If same function is registered twice it will be called twice.
291 *
292 * @param func API-callback hook function
293 * @return EM_OK if callback hook registration succeeded
294 */
297
298/**
299 * Unregister a previously registered em_alloc() callback hook
300 *
301 * @param func API-callback hook function
302 * @return EM_OK if callback hook unregistration succeeded
303 */
306
307/**
308 * Register an API-callback hook for em_free().
309 *
310 * The hook will be called before freeing the actual event, after verifying that
311 * the event given to em_free() is valid, thus the hook does not 'see' if the
312 * actual free-operation succeeds or fails.
313 * The state and ownership of the event must not be changed by the hook, e.g.
314 * the event must not be freed or sent etc. Calling em_free() within the
315 * free hook leads to hook recursion and must be avoided.
316 *
317 * API-callback hook functions can be called concurrently from different cores.
318 *
319 * Multiple API-callback hook functions (up to the number 'EM_CALLBACKS_MAX')
320 * can be registered.
321 * The order of calling multiple registered hook functions is the order of
322 * registration. If same function is registered twice it will be called twice.
323 *
324 * @param func API-callback hook function
325 * @return EM_OK if callback hook registration succeeded
326 */
329
330/**
331 * Unregister an em_free() callback hook
332 *
333 * @param func API-callback hook function
334 * @return EM_OK if callback hook unregistration succeeded
335 */
338
339/**
340 * Register an API-callback hook for em_send(), em_send_multi(), em_send_group()
341 * and em_send_group_multi().
342 *
343 * Sending multiple events with an event group is the most generic
344 * variant and thus one callback covers all.
345 * The hook will be called just before sending the actual event(s), thus
346 * the hook does not 'see' if the actual send operation succeeds or
347 * fails.
348 * The state and ownership of the events must not be changed by the
349 * hook, e.g. the events can not be freed or sent etc.
350 * Calling em_send...() within the send hook leads to hook recursion and
351 * must be avoided.
352 *
353 * API-callback hook functions can be called concurrently from different cores.
354 *
355 * Multiple API-callback hook functions (up to the number 'EM_CALLBACKS_MAX')
356 * can be registered.
357 * The order of calling multiple registered hook functions is the order of
358 * registration. If same function is registered twice it will be called twice.
359 *
360 * @param func API-callback hook function
361 * @return EM_OK if callback hook registration succeeded
362 */
365
366/**
367 * Unregister an em_send_...() callback hook
368 *
369 * @param func API-callback hook function
370 * @return EM_OK if callback hook unregistration succeeded
371 */
374
375/**
376 * Register an idle hook that will be called when entering the idle state.
377 *
378 * To_idle hooks will be called by the EM dispatcher when a core enters the idle
379 * state, i.e. when no further events are available from scheduled or local
380 * queues for processing. The to_idle hooks will be called only if the core
381 * previously was in the active state.
382 *
383 * Multiple to_idle hook functions (up to the number 'EM_CALLBACKS_MAX') can be
384 * registered. The order of calling multiple registered hook functions is the
385 * order of registration. If the same function is registered twice it will be
386 * called twice.
387 *
388 * @param func Idle hook function
389 * @return EM_OK if idle hook registration succeeded
390 */
393
394/**
395 * Unregister a to_idle hook.
396 *
397 * @param func Idle hook function
398 * @return EM_OK if idle hook unregistration succeeded
399 */
402
403/**
404 * Register an idle hook that will be called when a core is entering the active
405 * state.
406 *
407 * To_active hooks will be called by the EM dispatcher when a core enters the
408 * active state, i.e. it received events from scheduled or local queues after
409 * being in the idle state. The to_active hooks will be called before the actual
410 * event processing is started and only if the core previously was in the idle
411 * state.
412 *
413 * Multiple to_active hook functions (up to the number 'EM_CALLBACKS_MAX') can
414 * be registered. The order of calling multiple registered hook functions is the
415 * order of registration. If the same function is registered twice it will be
416 * called twice.
417 *
418 * @param func Idle hook function
419 * @return EM_OK if idle hook registration succeeded
420 */
423
424/**
425 * Unregister a to_active hook
426 *
427 * @param func Idle hook function
428 * @return EM_OK if idle hook unregistration succeeded
429 */
432
433/**
434 * Register an idle hook that will be called while staying in the idle state.
435 *
436 * While_idle hooks will be called by the EM dispatcher while a core remains in
437 * the idle state, i.e. the core didn't get any events from scheduled or local
438 * queues for processing while already being in the idle state.
439 *
440 * Multiple while_idle hook functions (up to the number 'EM_CALLBACKS_MAX') can
441 * be registered. The order of calling multiple registered hook functions is the
442 * order of registration. If the same function is registered twice it will be
443 * called twice.
444 *
445 * @param func Idle hook function
446 * @return EM_OK if idle hook registration succeeded
447 */
450
451/**
452 * Unregister a while_idle hook
453 *
454 * @param func Idle hook function
455 * @return EM_OK if idle hook unregistration succeeded
456 */
459
460/**
461 * @}
462 */
463#ifdef __cplusplus
464}
465#endif
466
467#pragma GCC visibility pop
468#endif /* EVENT_MACHINE_HOOKS_H_ */
uint32_t em_event_type_t
uint32_t em_status_t
void(* em_idle_hook_while_idle_t)(void)
em_status_t em_hooks_register_to_active(em_idle_hook_to_active_t func)
em_status_t em_hooks_unregister_alloc(em_api_hook_alloc_t func)
void(* em_idle_hook_to_active_t)(void)
em_status_t em_hooks_unregister_to_active(em_idle_hook_to_active_t func)
em_status_t em_hooks_register_alloc(em_api_hook_alloc_t func)
void(* em_api_hook_send_t)(const em_event_t events[], int num, em_queue_t queue, em_event_group_t event_group)
em_status_t em_hooks_register_free(em_api_hook_free_t func)
void(* em_idle_hook_to_idle_t)(uint64_t to_idle_delay_ns)
void(* em_api_hook_alloc_t)(const em_event_t events[], int num_act, int num_req, uint32_t size, em_event_type_t type, em_pool_t pool)
em_status_t em_hooks_unregister_to_idle(em_idle_hook_to_idle_t func)
void(* em_api_hook_free_t)(const em_event_t events[], int num)
em_status_t em_hooks_register_to_idle(em_idle_hook_to_idle_t func)
em_status_t em_hooks_register_while_idle(em_idle_hook_while_idle_t func)
em_status_t em_hooks_unregister_free(em_api_hook_free_t func)
em_status_t em_hooks_unregister_send(em_api_hook_send_t func)
em_status_t em_hooks_register_send(em_api_hook_send_t func)
em_status_t em_hooks_unregister_while_idle(em_idle_hook_while_idle_t func)
em_api_hook_send_t send_hook
em_api_hook_alloc_t alloc_hook
em_api_hook_free_t free_hook
em_idle_hook_to_idle_t to_idle_hook
em_idle_hook_to_active_t to_active_hook
em_idle_hook_while_idle_t while_idle_hook