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