EM-ODP  3.7.0
Event Machine on ODP
event_machine_eo.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015, 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_EO_H_
32 #define EVENT_MACHINE_EO_H_
33 
34 #pragma GCC visibility push(default)
35 
36 /**
37  * @file
38  * @defgroup em_eo Execution objects (EO)
39  *
40  * Operations on EO
41  *
42  * Execution objects (EO) are the application building blocks of EM.
43  * An EO typically implements one logical function or one stage in a pipeline,
44  * but alternatively the whole application could be implemented with one EO.
45  * EOs work as servers, queues are the service access points (inputs to the EO).
46  *
47  * An EO consists of user provided callback functions and context data.
48  * The most important function is the receive function, which gets called
49  * when an event is received from one of the queues associated with the EO.
50  * The EM scheduler selects the next event for processing on a core and the
51  * EM dispatcher on that core maps the received event and queue information to
52  * an EO receive function to call to process the event.
53  * Other EO functions are used to manage start-up and teardown of EOs. See
54  * individual EO functions for more details.
55  *
56  * em_eo_create()
57  * |
58  * v
59  * .-------------.
60  * .->.------->| CREATED | (new events discarded)
61  * | | '-------------'
62  * | | | em_eo_start(+notifs) / em_eo_start_sync()
63  * | | v
64  * | | .-------------.
65  * | | | STARTING | (new events discarded)
66  * | ' '-------------'
67  * | \ global start
68  * | \ THEN
69  * | \ local start on each core
70  * | '--- FAIL OK
71  * | | send 'start-completed' notifications
72  * | v
73  * . .-------------.
74  * | | RUNNING |
75  * | '-------------'
76  * | | em_eo_stop(+notifs) / em_eo_stop_sync()
77  * | v
78  * ' .-------------.
79  * \ | STOPPING | (new events discarded)
80  * \ '-------------'
81  * \ |
82  * \ v
83  * \ local stops on each core
84  * \ THEN
85  * \ global stops
86  * \ .
87  * \ /
88  * -------' send 'stop-completed' notifications
89  *
90  * @{
91  */
92 
93 #ifdef __cplusplus
94 extern "C" {
95 #endif
96 
100 
101 /**
102  * Execution object (EO) event receive function (single-event)
103  *
104  * An application receives events through queues and these events are passed to
105  * the application's EO receive function(s) for processing. The EO receive
106  * function implements the main part of the application logic. EM calls the
107  * receive function when it has dequeued an event from one of the EO's queues.
108  * The application then processes the event and returns immediately in a
109  * run-to-completion fashion. There is no pre-emption.
110  *
111  * On multicore systems, several events (from the same or different queue) may
112  * be dequeued in parallel and thus the same receive function may be executed
113  * concurrently on several cores. Parallel execution may be limited by queue
114  * group setup or by using queues with an atomic scheduling mode.
115  *
116  * The EO and queue context pointers are user defined. The EO context is given
117  * at EO creation and the queue context is set with em_queue_set_context().
118  * These contexts may be used in any way needed, the EM implementation will not
119  * dereference them. For example, the EO context may be used to store global
120  * EO state information, which is common to all queues and events for that EO.
121  * In addition, the queue context may be used to store queue specific state data
122  * (e.g. user data flow related data). The queue context data for an atomic
123  * queue can be freely manipulated in the receive function, since only one event
124  * at a time can be under work from that particular atomic queue. For other
125  * queue types it is up to the user to synchronize context access. The EO
126  * context is protected only if the EO has one queue and it is of type 'atomic'
127  * (applies also to several atomic queues that belong to the same atomic group).
128  *
129  * An event (handle) must be converted to an event structure pointer with
130  * em_event_pointer() before accessing any data it may contain.
131  * The event type specifies the event structure in memory, which is
132  * implementation or application specific.
133  * The queue handle specifies the queue where the event was dequeued from.
134  *
135  * The EO will not receive any events if it has not been successfully started.
136  *
137  * @param eo_ctx EO context data given to em_eo_create(),
138  * EM does not dereference.
139  * @param event Event handle
140  * @param type Event type
141  * @param queue Queue from which the event was dequeued
142  * @param q_ctx Queue context data. The context pointer is set by
143  * em_queue_set_context(), EM does not touch the data.
144  *
145  * @see em_eo_create(),
146  * em_alloc(), em_free(), em_send(),
147  * em_event_pointer(), em_queue_set_context()
148  */
149 typedef void (*em_receive_func_t)(void *eo_ctx,
150  em_event_t event, em_event_type_t type,
151  em_queue_t queue, void *q_ctx);
152 
153 /**
154  * Execution object (EO) multi-event receive function
155  *
156  * Similar to the single-event receive function (em_receive_func_t), except that
157  * multiple events can be passed with one call to the EO receive function.
158  * A multi-event receive function is taken into use during EO creation with a
159  * call to em_eo_create_multircv(...). The maximum number of events that the
160  * multi-event EO receive function is prepared to handle can be passed with the
161  * argument 'max_events' of em_eo_create_multircv(). The EM dispatcher will
162  * split event batches larger than 'max_events' into chunks of 'max_events'.
163  *
164  * Event group handling:
165  * All events passed by the EM dispatcher to the EO multi-event receive function
166  * belong to the same event group (or none) - a batch of events containing
167  * multiple event groups is split by the dispatcher into smaller chunks, each
168  * chunk belonging to the same event group (or none).
169  * The event group count is decremented by the number of events passed to the
170  * receive function when execution returns to the dispatcher.
171  *
172  * Note: Contrary to the single-event EO receive function (em_receive_func_t),
173  * no event types are passed. Use appropriate event APIs if the event types
174  * are needed.
175  *
176  * @param eo_ctx EO context data given to em_eo_create_multircv(),
177  * EM does not dereference.
178  * @param events Event handles: events[num]
179  * @param num Number of events received
180  * (0 to 'max_events' of em_eo_create_multircv())
181  * @param queue Queue from which the event was dequeued
182  * @param q_ctx Queue context data. The context pointer is set by
183  * em_queue_set_context(), EM does not touch the data.
184  *
185  * @see em_eo_create_multircv(),
186  * em_alloc(), em_free(), em_send(),
187  * em_event_pointer(), em_queue_set_context()
188  */
189 typedef void (*em_receive_multi_func_t)(void *eo_ctx,
190  em_event_t events[], int num,
191  em_queue_t queue, void *q_ctx);
192 
193 /**
194  * Execution object (EO) start function, global.
195  *
196  * This EO callback function is called once on one core by em_eo_start().
197  * The purpose of this global EO-start is to provide a placeholder for first
198  * level EO initialization, e.g. allocating memory and initializing shared data.
199  * After this global start returns, the EO core local start function (if given)
200  * is called on all cores in this EM instance. If there is no core local start,
201  * then event dispatching is enabled as this function returns, otherwise the EO
202  * is enabled only when all core local starts have completed successfully on all
203  * the cores. If this function does not return EM_OK, the system will not call
204  * the core local init and will not enable event dispatching for this EO.
205  *
206  * Note that events sent to scheduled queues from a start function are
207  * buffered. The buffered events will be sent into the queues when the EO start
208  * functions have returned - otherwise it would not be possible to send events
209  * to the EO's own queues as the EO is not yet in a started state. No buffering
210  * is done when sending to queues that are not scheduled.
211  *
212  * The last argument is an optional startup configuration passed directly
213  * from em_eo_start(). If local start functions need the configuration data,
214  * it must be saved during the global start.
215  *
216  * This function should never be directly called from the application,
217  * it will be called by em_eo_start(), which maintains state information.
218  *
219  * @param eo_ctx Execution object internal state/instance data
220  * @param eo Execution object handle
221  * @param conf Optional startup configuration, NULL ok.
222  *
223  * @return EM_OK if successful, other values abort EO start
224  *
225  * @see em_eo_start(), em_eo_create()
226  */
227 typedef em_status_t (*em_start_func_t)(void *eo_ctx, em_eo_t eo,
228  const em_eo_conf_t *conf);
229 
230 /**
231  * Execution object (EO) start function, core local.
232  *
233  * This is similar to the global start above, but this one is called after the
234  * global start has completed and is run on all cores of the EM instance
235  * potentially in parallel.
236  *
237  * The purpose of this optional local start is to work as a placeholder for
238  * core local initialization, e.g. allocating core local memory.
239  *
240  * Note that events sent to scheduled queues from local start functions are
241  * buffered. The buffered events will be sent into the queues when the EO start
242  * functions have returned - otherwise it would not be possible to send events
243  * to the EO's own queues as the EO is not yet in a started state. No buffering
244  * is done when sending to queues that are not scheduled.
245  *
246  * This function should never be directly called from the application,
247  * it will be called by em_eo_start(), which maintains state information.
248  *
249  * Event dispatching is not enabled if this function doesn't return EM_OK on
250  * all cores.
251  *
252  * @param eo_ctx Execution object internal state/instance data
253  * @param eo Execution object handle
254  *
255  * @return EM_OK if successful, other values prevent EO start
256  *
257  * @see em_eo_start(), em_eo_create()
258  */
259 typedef em_status_t (*em_start_local_func_t)(void *eo_ctx, em_eo_t eo);
260 
261 /**
262  * Execution object (EO) stop function, core local.
263  *
264  * This function is called once on each core of the EM instance before the
265  * global stop (reverse order of start). The system disables event dispatching
266  * before calling these and also makes sure this does not get called before
267  * the core has been notified of the stop condition for this EO (won't dispatch
268  * any new events).
269  *
270  * This function should never be directly called from the application,
271  * it will be called by em_eo_stop(), which maintains state information.
272  *
273  * @param eo_ctx Execution object internal state data
274  * @param eo Execution object handle
275  *
276  * @return EM_OK if successful.
277  *
278  * @see em_eo_stop(), em_eo_create()
279  */
280 typedef em_status_t (*em_stop_local_func_t)(void *eo_ctx, em_eo_t eo);
281 
282 /**
283  * Execution object (EO) stop function, global.
284  *
285  * The EO global stop function is called once on one core after the optional
286  * core local stop functions return on all cores. The system disables event
287  * dispatching before calling this function and also makes sure it does not get
288  * called before all cores have been notified of the stop condition for this EO
289  * (don't dispatch new events).
290  *
291  * This function should never be directly called from the application,
292  * it will be called by em_eo_stop(), which maintains state information.
293  *
294  * @param eo_ctx Execution object internal state data
295  * @param eo Execution object handle
296  *
297  * @return EM_OK if successful.
298  *
299  * @see em_eo_stop(), em_eo_create()
300  */
301 typedef em_status_t (*em_stop_func_t)(void *eo_ctx, em_eo_t eo);
302 
303 /**
304  * Create an Execution Object (EO).
305  *
306  * Allocate an EO handle and initialize internal data for the new EO.
307  * The EO is left in a non-active state, i.e. no events are dispatched before
308  * em_eo_start() has been called. Start, stop and receive callback functions
309  * are mandatory arguments.
310  *
311  * The EO name is copied into EO internal data. The maximum length stored is
312  * EM_EO_NAME_LEN. Duplicate names are allowed, but find will only match one of
313  * them.
314  *
315  * @param name Name of the EO (optional, NULL ok)
316  * @param start Start function
317  * @param local_start Core local start function (NULL if no local start)
318  * @param stop Stop function
319  * @param local_stop Core local stop function (NULL if no local stop)
320  * @param receive Receive function
321  * @param eo_ctx User defined EO context data, EM passes the value
322  * (NULL if no context)
323  *
324  * @return New EO handle if successful, otherwise EM_EO_UNDEF.
325  *
326  * @see em_eo_start(), em_eo_delete(), em_queue_create(), em_eo_add_queue()
327  * @see em_start_func_t, em_stop_func_t, em_receive_func_t
328  */
329 em_eo_t
330 em_eo_create(const char *name,
331  em_start_func_t start, em_start_local_func_t local_start,
332  em_stop_func_t stop, em_stop_local_func_t local_stop,
333  em_receive_func_t receive, const void *eo_ctx);
334 
335 /**
336  * EO parameters for em_eo_create_multircv(...)
337  */
338 typedef struct {
339  /**
340  * EO start function, mandatory.
341  * Called once on one core, triggered by em_eo_start/_start_sync().
342  * First EO-function to be called.
343  */
345  /**
346  * EO core-local start function, optional (set NULL if not used).
347  * Called on all EM-cores after 'start' has completed.
348  */
350  /**
351  * EO stop function, mandatory.
352  * Called once on one core, triggered by em_eo_stop/_stop_sync().
353  * Last EO-function to be called.
354  */
356  /**
357  * EO core-local stop function, optional (set NULL if not used).
358  * Called and completed on all EM-cores before 'stop'.
359  */
361  /**
362  * EO receive function for multiple events, mandatory.
363  */
365  /**
366  * Maximum number of events passed to the receive function.
367  * EM will dispatch 1 to 'max-events' at a time to the EO's multi-event
368  * receive function.
369  * Use '0' for an EM default value (=EM_EO_MULTIRCV_MAX_EVENTS).
370  * The user provided 'receive_multi' function must be able to handle
371  * 'max_events' events at a time.
372  */
374  /**
375  * User defined EO context data, optional (NULL if no context).
376  * EM only passes the value.
377  */
378  const void *eo_ctx;
379 
380  /**
381  * Internal check - don't touch!
382  *
383  * EM will verify that em_eo_multircv_param_init(param) has been called
384  * before creating an EO with em_eo_create_multircv(..., param)
385  */
388 
389 /**
390  * Initialize parameters for the multi-event receive-function EO.
391  *
392  * Initialize em_eo_multircv_param_t to default values for all fields.
393  * After initialization, the user further needs to set the mandatory fields of
394  * 'em_eo_multircv_param_t' before calling em_eo_create_multircv().
395  * Always initialize 'param' first with em_eo_multircv_param_init(&param) to
396  * ensure backwards compatibility with potentially added new options.
397  *
398  * @param param Address of the em_eo_multircv_param_t to be initialized
399  *
400  * @see em_eo_create_multircv()
401  */
403 
404 /**
405  * Create an Execution Object (EO) with a multi-event receive function.
406  *
407  * Similar to em_eo_create(), except that an EO multi-event receive function is
408  * taken into use for the created EO, see em_receive_multi_func_t (passed via
409  * em_eo_multircv_param_t param).
410  *
411  * Always initialize 'param' first with em_eo_multircv_param_init(&param) to
412  * ensure backwards compatibility before setting your own params and calling
413  * em_eo_create_multircv():
414  * @code
415  * em_eo_multircv_param_t param;
416  * em_eo_t eo;
417  *
418  * em_eo_multircv_param_init(&param);
419  * param.start = my_start_fn;
420  * param.stop = my_stop_fn;
421  * param.receive_multi = my_receive_multi_fn;
422  * param.max_events = MY_MAX_EVENTS; // or use default=0
423  * ...
424  * eo = em_eo_create_multircv("my-eo", &param);
425  * if (unlikely(eo == EM_EO_UNDEF))
426  * report_error();
427  * @endcode
428  *
429  * @param name Name of the EO (optional, NULL ok)
430  * @param param EO parameters
431  *
432  * @return New EO handle if successful, otherwise EM_EO_UNDEF.
433  *
434  * @see em_eo_multircv_param_init()
435  * @see em_eo_start(), em_eo_start_sync(), em_eo_stop(), em_eo_stop_sync()
436  * @see em_start_func_t, em_stop_func_t, em_receive_multi_func_t
437  */
438 em_eo_t
439 em_eo_create_multircv(const char *name, const em_eo_multircv_param_t *param);
440 
441 /**
442  * Delete Execution Object (EO).
443  *
444  * Immediately delete the given EO and free the identifier.
445  *
446  * NOTE, that an EO can only be deleted after it has been stopped using
447  * em_eo_stop(), otherwise another core might still access the EO data.
448  * All associated queues must be removed before deleting an EO.
449  *
450  * A sequence of
451  * @code
452  * em_eo_stop_sync(eo);
453  * em_eo_remove_queue_all_sync(eo, EM_TRUE);
454  * em_eo_delete(eo);
455  * @endcode
456  * will cleanly delete an EO from the EM point of view (not including user
457  * allocated data).
458  *
459  * @param eo EO handle to delete
460  *
461  * @return EM_OK if successful.
462  *
463  * @see em_eo_stop(), em_eo_remove_queue()
464  */
466 em_eo_delete(em_eo_t eo);
467 
468 /**
469  * Returns the name given to the EO when it was created.
470  *
471  * A copy of the name string (up to 'maxlen' characters) is
472  * written to the user buffer 'name'.
473  * The string is always null terminated - even if the given buffer length
474  * is less than the name length.
475  *
476  * The function returns 0 and writes an empty string if the EO has no name.
477  *
478  * @param eo EO handle
479  * @param[out] name Destination buffer
480  * @param maxlen Maximum length (including the terminating '0')
481  *
482  * @return Number of characters written (excludes the terminating '0').
483  *
484  * @see em_eo_create()
485  */
486 size_t
487 em_eo_get_name(em_eo_t eo, char *name, size_t maxlen);
488 
489 /**
490  * Find EO by name.
491  *
492  * Finds an EO by the given name (exact match). An empty string will not match
493  * anything. The search is case sensitive. This function will return the first
494  * match only if there are duplicate names.
495  *
496  * @param name the name to look for
497  *
498  * @return EO handle or EM_EO_UNDEF if not found
499  *
500  * @see em_eo_create()
501  */
502 em_eo_t
503 em_eo_find(const char *name);
504 
505 /**
506  * Add a queue to an EO, asynchronous (non-blocking)
507  *
508  * Add the given queue to the EO and enable scheduling for it. The function
509  * returns immediately, but the operation can be asynchronous and only fully
510  * complete later. The given notification events are sent when the operation has
511  * completed and the queue is ready to receive events.
512  * Note, that the completion notification(s) guarantee that the queue itself is
513  * operational, but if the target EO is not yet started then events sent into
514  * the queue will still be dropped by dispatcher.
515  *
516  * @param eo EO handle
517  * @param queue Queue handle
518  * @param num_notif Number of notification events, 0 for no notification
519  * @param notif_tbl Array of pairs of event and queue identifiers
520  * (+ optional event groups to send the events with)
521  *
522  * @return EM_OK if successful.
523  *
524  * @see em_queue_create(), em_eo_create(), em_eo_remove_queue(),
525  * em_eo_add_queue_sync()
526  */
528 em_eo_add_queue(em_eo_t eo, em_queue_t queue,
529  int num_notif, const em_notif_t notif_tbl[]);
530 
531 /**
532  * Add a queue to an EO, synchronous (blocking)
533  *
534  * As em_eo_add_queue(), but does not return until the queue is ready to
535  * receive events.
536  *
537  * Note that the function is blocking and will not return until the operation
538  * has completed across all concerned EM cores.
539  * Sync-API calls can block the core for a long (indefinite) time, thus they
540  * should not be used to make runtime changes on real time EM cores - consider
541  * the async variants of the APIs in these cases instead.
542  * While one core is calling a sync-API function, the others must be running the
543  * EM dispatch loop to be able to receive and handle the sync-API request events
544  * sent internally.
545  * Use the sync-APIs mainly to simplify application start-up or teardown.
546  *
547  * @param eo EO handle
548  * @param queue Queue handle
549  *
550  * @return EM_OK if successful.
551  *
552  * @see em_queue_create(), em_eo_create(), em_eo_remove_queue()
553  * @see em_eo_add_queue() for an asynchronous version of the API
554  */
556 em_eo_add_queue_sync(em_eo_t eo, em_queue_t queue);
557 
558 /**
559  * Removes a queue from an EO, asynchronous (non-blocking)
560  *
561  * Disables queue scheduling and removes the queue from the EO. The function
562  * returns immediately, but the operation can be asynchronous and only fully
563  * complete later. The given notification events are sent when the operation has
564  * completed across all cores and no event from this queue is being dispatched
565  * anymore. Use notifications to know when the operation has fully completed
566  * and the queue can safely be deleted.
567  *
568  * @param eo EO handle
569  * @param queue Queue handle to remove
570  * @param num_notif Number of notification events, 0 for no notification
571  * @param notif_tbl Array of pairs of event and queue identifiers
572  * (+ optional event groups to send the events with)
573  *
574  * @return EM_OK if successful.
575  *
576  * @see em_eo_add_queue(), em_eo_remove_queue_sync()
577  */
579 em_eo_remove_queue(em_eo_t eo, em_queue_t queue,
580  int num_notif, const em_notif_t notif_tbl[]);
581 
582 /**
583  * Removes a queue from an EO, synchronous (blocking)
584  *
585  * As em_eo_remove_queue(), but will not return until the queue has been
586  * disabled, removed from the EO and no more events are being processed from
587  * the queue.
588  *
589  * Note that the function is blocking and will not return until the operation
590  * has completed across all concerned EM cores.
591  * Sync-API calls can block the core for a long (indefinite) time, thus they
592  * should not be used to make runtime changes on real time EM cores - consider
593  * the async variants of the APIs in these cases instead.
594  * While one core is calling a sync-API function, the others must be running the
595  * EM dispatch loop to be able to receive and handle the sync-API request events
596  * sent internally.
597  * Use the sync-APIs mainly to simplify application start-up or teardown.
598  *
599  * @param eo EO handle
600  * @param queue Queue handle to remove
601  *
602  * @return EM_OK if successful.
603  *
604  * @see em_eo_remove_queue() for an asynchronous version of the API
605  */
607 em_eo_remove_queue_sync(em_eo_t eo, em_queue_t queue);
608 
609 /**
610  * Removes all queues from an EO, asynchronous (non-blocking)
611  *
612  * Like em_eo_remove_queue(), but removes all queues currently associated with
613  * the EO.
614  * The argument 'delete_queues' can be used to automatically also delete all
615  * queues by setting it to EM_TRUE (EM_FALSE otherwise).
616  * Note: any allocated queue contexts will still need to be handled elsewhere.
617  *
618  * @param eo EO handle
619  * @param delete_queues delete the EO's queues if set to EM_TRUE
620  * @param num_notif Number of notification events, 0 for no notification
621  * @param notif_tbl Array of pairs of event and queue identifiers
622  * (+ optional event groups to send the events with)
623  *
624  * @return EM_OK if successful.
625  *
626  * @see em_eo_add_queue(), em_eo_remove_queue_sync(),
627  * em_eo_remove_queue_all_sync()
628  */
630 em_eo_remove_queue_all(em_eo_t eo, int delete_queues,
631  int num_notif, const em_notif_t notif_tbl[]);
632 
633 /**
634  * Removes all queues from an EO, synchronous (blocking).
635  *
636  * As em_eo_remove_queue_all(), but does not return until all queues have
637  * been removed.
638  *
639  * Note that the function is blocking and will not return until the operation
640  * has completed across all concerned EM cores.
641  * Sync-API calls can block the core for a long (indefinite) time, thus they
642  * should not be used to make runtime changes on real time EM cores - consider
643  * the async variants of the APIs in these cases instead.
644  * While one core is calling a sync-API function, the others must be running the
645  * EM dispatch loop to be able to receive and handle the sync-API request events
646  * sent internally.
647  * Use the sync-APIs mainly to simplify application start-up or teardown.
648  *
649  * @param eo EO handle
650  * @param delete_queues delete the EO's queues if set to EM_TRUE
651  *
652  * @return EM_OK if successful.
653  *
654  *
655  * @see em_eo_remove_queue_all() for an asynchronous version of the API
656  */
658 em_eo_remove_queue_all_sync(em_eo_t eo, int delete_queues);
659 
660 /**
661  * Register an EO specific error handler.
662  *
663  * The EO specific error handler is called if an error occurs or em_error() is
664  * called in the context of the running EO.
665  * Note, the provided function will override any previously registered
666  * error handler for the EO in question.
667  * The global error handler is called if no EO specific error handler is
668  * registered.
669  *
670  * @param eo EO handle
671  * @param handler New error handler
672  *
673  * @return EM_OK if successful.
674  *
675  * @see em_register_error_handler(), em_error_handler_t()
676  */
679 
680 /**
681  * Unregister an EO specific error handler.
682  *
683  * Removes a previously registered EO specific error handler and restores the
684  * global error handler into use for the EO.
685  *
686  * @param eo EO handle
687  *
688  * @return EM_OK if successful.
689  */
692 
693 /**
694  * Start an Execution Object (EO), asynchronous (non-blocking)
695  *
696  * Start and enable a previously created EO.
697  * The em_eo_start() function will first call the user provided global EO start
698  * function. If that global start function returns EM_OK then events to trigger
699  * the (optional) user provided local start function are sent to all cores.
700  * The em_eo_start() function returns immediately after the global start
701  * returns, which means that the action only fully completes later.
702  * Notifications should be used if the caller needs to know when the EO start
703  * has fully completed. The given notification event(s) will be sent to the
704  * given queue(s) when the start is completed on all cores.
705  *
706  * Local start is not called and event dispatching is not enabled for this EO if
707  * the global start function does not return EM_OK.
708  *
709  * The notification(s) are sent when the global start function returns if a
710  * local start function hasn't been provided.
711  * Use '0' as 'num_notif' if notifications are not needed. Be aware of,
712  * is this case, that the EO may not immediately be ready to handle events.
713  *
714  * Note that events sent to scheduled queues from a user provided EO global or
715  * local start function are buffered. The buffered events will be sent into the
716  * queues when the EO start functions have all returned - otherwise it would not
717  * be possible to send events to the EO's own queues as the EO is not yet in a
718  * started state. No buffering is done when sending to queues that are
719  * not scheduled.
720  *
721  * The optional conf-argument can be used to pass applification specific
722  * information (e.g. configuration data) to the EO.
723  *
724  * @param eo EO handle
725  * @param[out] result Optional pointer to em_status_t, which gets updated to
726  * the return value of the actual user provided EO global
727  * start function.
728  * @param conf Optional startup configuration, NULL ok.
729  * @param num_notif If not 0, defines the number of notification events to
730  * send when all cores have returned from the start
731  * function(s).
732  * @param notif_tbl Array of em_notif_t, the optional notification events
733  * (array data is copied)
734  *
735  * @return EM_OK if successful.
736  *
737  * @see em_start_func_t(), em_start_local_func_t(), em_eo_stop(),
738  * em_eo_start_sync()
739  */
741 em_eo_start(em_eo_t eo, em_status_t *result, const em_eo_conf_t *conf,
742  int num_notif, const em_notif_t notif_tbl[]);
743 
744 /**
745  * Start Execution Object (EO), synchronous (blocking)
746  *
747  * As em_eo_start(), but will not return until the operation is complete.
748  *
749  * Note that the function is blocking and will not return until the operation
750  * has completed across all concerned EM cores.
751  * Sync-API calls can block the core for a long (indefinite) time, thus they
752  * should not be used to make runtime changes on real time EM cores - consider
753  * the async variants of the APIs in these cases instead.
754  * While one core is calling a sync-API function, the others must be running the
755  * EM dispatch loop to be able to receive and handle the sync-API request events
756  * sent internally.
757  * Use the sync-APIs mainly to simplify application start-up or teardown.
758  *
759  * @param eo EO handle
760  * @param[out] result Optional pointer to em_status_t, which gets updated to
761  * the return value of the actual user provided EO global
762  * start function.
763  * @param conf Optional startup configuration, NULL ok.
764  *
765  * @return EM_OK if successful.
766  *
767  * @see em_start_func_t(), em_start_local_func_t(), em_eo_stop()
768  * @see em_eo_start() for an asynchronous version of the API
769  */
771 em_eo_start_sync(em_eo_t eo, em_status_t *result, const em_eo_conf_t *conf);
772 
773 /**
774  * Stop Execution Object (EO), asynchronous (non-blocking)
775  *
776  * Disables event dispatch from all related queues, calls core local stop
777  * on all cores and finally calls the global stop function of the EO when all
778  * cores have returned from the (optional) core local stop.
779  * The call to the global EO stop is asynchronous and only done when all cores
780  * have completed processing of the receive function and/or core local stop.
781  * This guarantees no other core is accessing EO data during the EO global stop
782  * function.
783  *
784  * This function returns immediately, but may only fully complete later. If the
785  * caller needs to know when the EO stop has actually completed, the num_notif
786  * and notif_tbl should be used. The given notification event(s) will be sent to
787  * given queue(s) when the stop operation actually completes.
788  * If such notifications are not needed, use '0' as 'num_notif'.
789  *
790  * When the EO has stopped it can be started again with em_eo_start().
791  *
792  * @param eo EO handle
793  * @param num_notif Number of notification events, 0 for no notification
794  * @param notif_tbl Array of pairs of event and queue identifiers
795  * (+ optional event groups to send the events with)
796  *
797  * @return EM_OK if successful.
798  *
799  * @see em_stop_func_t(), em_stop_local_func_t(), em_eo_start(),
800  * em_eo_stop_sync()
801  */
803 em_eo_stop(em_eo_t eo, int num_notif, const em_notif_t notif_tbl[]);
804 
805 /**
806  * Stop Execution Object (EO), synchronous (blocking)
807  *
808  * As em_eo_stop(), but will not return until the operation is complete.
809  *
810  * Note that the function is blocking and will not return until the operation
811  * has completed across all concerned EM cores.
812  * Sync-API calls can block the core for a long (indefinite) time, thus they
813  * should not be used to make runtime changes on real time EM cores - consider
814  * the async variants of the APIs in these cases instead.
815  * While one core is calling a sync-API function, the others must be running the
816  * EM dispatch loop to be able to receive and handle the sync-API request events
817  * sent internally.
818  * Use the sync-APIs mainly to simplify application start-up or teardown.
819  *
820  * @param eo EO handle
821  *
822  * @return EM_OK if successful.
823  *
824  * @see em_stop_func_t(), em_stop_local_func_t(), em_eo_start()
825  * @see em_eo_stop() for an asynchronous version of the API
826  */
828 em_eo_stop_sync(em_eo_t eo);
829 
830 /**
831  * Return the currently active EO
832  *
833  * Returns the EO handle associated with the currently running EO function.
834  * Only valid if called within an EO-context, will return EM_EO_UNDEF otherwise.
835  * Can be called from the EO-receive or EO-start/stop functions (or subfunctions
836  * thereof).
837  * Note that calling em_eo_current() from e.g. an EO-start function that was
838  * launched from within another EO's receive will return the EO handle of the
839  * EO being started - i.e. always returns the 'latest' current EO.
840  *
841  * @return The current EO or EM_EO_UNDEF if no current EO (or error)
842  */
843 em_eo_t
844 em_eo_current(void);
845 
846 /**
847  * Get EO specific (application) context.
848  *
849  * Returns the EO context pointer that the application has earlier provided via
850  * em_eo_create().
851  *
852  * @param eo EO for which the context is requested
853  *
854  * @return EO specific context pointer or NULL if no context (or error)
855  */
856 void *
857 em_eo_get_context(em_eo_t eo);
858 
859 /**
860  * Return the EO state.
861  *
862  * Returns the current state of the given EO.
863  *
864  * @return The current EO state or EM_EO_STATE_UNDEF if never created.
865  */
867 em_eo_get_state(em_eo_t eo);
868 
869 /**
870  * Initialize EO iteration and return the first EO handle.
871  *
872  * Can be used to initialize the iteration to retrieve all created EOs for
873  * debugging or management purposes. Use em_eo_get_next() after this call until
874  * it returns EM_EO_UNDEF. A new call to em_eo_get_first() resets the iteration,
875  * which is maintained per core (thread). The operation should be completed in
876  * one go before returning from the EO's event receive function (or start/stop).
877  *
878  * The number of EOs (output arg 'num') may not match the amount of EOs actually
879  * returned by iterating using em_eo_get_next() if EOs are added or removed in
880  * parallel by another core. The order of the returned EO handles is undefined.
881  *
882  * @code
883  * unsigned int num;
884  * em_eo_t eo = em_eo_get_first(&num);
885  * while (eo != EM_EO_UNDEF) {
886  * eo = em_eo_get_next();
887  * }
888  * @endcode
889  *
890  * @param[out] num Pointer to an unsigned int to store the amount of EOs into
891  * @return The first EO handle or EM_EO_UNDEF if none exist
892  *
893  * @see em_eo_get_next()
894  */
895 em_eo_t
896 em_eo_get_first(unsigned int *num);
897 
898 /**
899  * Return the next EO handle.
900  *
901  * Continues the EO iteration started by em_eo_get_first() and returns the next
902  * EO handle.
903  *
904  * @return The next EO handle or EM_EO_UNDEF if the EO iteration is completed
905  * (i.e. no more EO's available).
906  *
907  * @see em_eo_get_first()
908  */
909 em_eo_t
910 em_eo_get_next(void);
911 
912 /**
913  * Initialize iteration of an EO's queues and return the first queue handle.
914  *
915  * Can be used to initialize the iteration to retrieve all queues associated
916  * with the given EO for debugging or management purposes.
917  * Use em_eo_queue_get_next() after this call until it returns EM_QUEUE_UNDEF.
918  * A new call to em_eo_queue_get_first() resets the iteration, which is
919  * maintained per core (thread). The operation should be started and completed
920  * in one go before returning from the EO's event receive function (or
921  * start/stop).
922  *
923  * The number of queues owned by the EO (output arg 'num') may not match the
924  * amount of queues actually returned by iterating using em_eo_queue_get_next()
925  * if queues are added or removed in parallel by another core. The order of
926  * the returned queue handles is undefined.
927  *
928  * Simplified example:
929  * @code
930  * unsigned int num;
931  * em_queue_t q = em_eo_queue_get_first(&num, eo);
932  * while (q != EM_QUEUE_UNDEF) {
933  * q = em_eo_queue_get_next();
934  * }
935  * @endcode
936  *
937  * @param[out] num Output the current amount of queues associated with the EO
938  * @param eo EO handle
939  *
940  * @return The first queue handle or EM_QUEUE_UNDEF if none exist or the EO
941  * is invalid.
942  *
943  * @see em_eo_queue_get_next()
944  **/
945 em_queue_t
946 em_eo_queue_get_first(unsigned int *num, em_eo_t eo);
947 
948 /**
949  * Return the EO's next queue handle.
950  *
951  * Continues the queue iteration started by em_eo_queue_get_first() and returns
952  * the next queue handle owned by the EO.
953  *
954  * @return The next queue handle or EM_QUEUE_UNDEF if the queue iteration is
955  * completed (i.e. no more queues available for this EO).
956  *
957  * @see em_eo_queue_get_first()
958  **/
959 em_queue_t
961 
962 /**
963  * Convert an EO handle to an unsigned integer
964  *
965  * @param eo EO handle to be converted
966  * @return uint64_t value that can be used to print/display the handle
967  *
968  * @note This routine is intended to be used for diagnostic purposes
969  * to enable applications to e.g. generate a printable value that represents
970  * an em_eo_t handle.
971  */
972 uint64_t em_eo_to_u64(em_eo_t eo);
973 
974 /**
975  * @}
976  */
977 #ifdef __cplusplus
978 }
979 #endif
980 
981 #pragma GCC visibility pop
982 #endif /* EVENT_MACHINE_EO_H_ */
em_eo_remove_queue_sync
em_status_t em_eo_remove_queue_sync(em_eo_t eo, em_queue_t queue)
Definition: event_machine_eo.c:409
em_eo_start
em_status_t em_eo_start(em_eo_t eo, em_status_t *result, const em_eo_conf_t *conf, int num_notif, const em_notif_t notif_tbl[])
Definition: event_machine_eo.c:604
em_eo_multircv_param_t
Definition: event_machine_eo.h:338
em_eo_multircv_param_t::local_stop
em_stop_local_func_t local_stop
Definition: event_machine_eo.h:360
em_eo_remove_queue
em_status_t em_eo_remove_queue(em_eo_t eo, em_queue_t queue, int num_notif, const em_notif_t notif_tbl[])
Definition: event_machine_eo.c:352
em_eo_get_name
size_t em_eo_get_name(em_eo_t eo, char *name, size_t maxlen)
Definition: event_machine_eo.c:236
em_stop_func_t
em_status_t(* em_stop_func_t)(void *eo_ctx, em_eo_t eo)
Definition: event_machine_eo.h:301
em_eo_get_context
void * em_eo_get_context(em_eo_t eo)
Definition: event_machine_eo.c:1002
em_eo_add_queue_sync
em_status_t em_eo_add_queue_sync(em_eo_t eo, em_queue_t queue)
Definition: event_machine_eo.c:344
em_eo_unregister_error_handler
em_status_t em_eo_unregister_error_handler(em_eo_t eo)
Definition: event_machine_eo.c:585
em_eo_multircv_param_t::local_start
em_start_local_func_t local_start
Definition: event_machine_eo.h:349
em_eo_current
em_eo_t em_eo_current(void)
Definition: event_machine_eo.c:996
em_eo_remove_queue_all_sync
em_status_t em_eo_remove_queue_all_sync(em_eo_t eo, int delete_queues)
Definition: event_machine_eo.c:517
em_eo_get_next
em_eo_t em_eo_get_next(void)
Definition: event_machine_eo.c:1075
em_eo_multircv_param_t::start
em_start_func_t start
Definition: event_machine_eo.h:344
em_start_func_t
em_status_t(* em_start_func_t)(void *eo_ctx, em_eo_t eo, const em_eo_conf_t *conf)
Definition: event_machine_eo.h:227
em_eo_delete
em_status_t em_eo_delete(em_eo_t eo)
Definition: event_machine_eo.c:205
em_eo_multircv_param_t::max_events
int max_events
Definition: event_machine_eo.h:373
event_machine_error.h
em_eo_register_error_handler
em_status_t em_eo_register_error_handler(em_eo_t eo, em_error_handler_t handler)
Definition: event_machine_eo.c:566
em_start_local_func_t
em_status_t(* em_start_local_func_t)(void *eo_ctx, em_eo_t eo)
Definition: event_machine_eo.h:259
em_eo_start_sync
em_status_t em_eo_start_sync(em_eo_t eo, em_status_t *result, const em_eo_conf_t *conf)
Definition: event_machine_eo.c:725
em_status_t
uint32_t em_status_t
Definition: event_machine_types.h:321
em_error_handler_t
em_status_t(* em_error_handler_t)(em_eo_t eo, em_status_t error, em_escope_t escope, va_list args)
Definition: event_machine_error.h:94
em_eo_stop
em_status_t em_eo_stop(em_eo_t eo, int num_notif, const em_notif_t notif_tbl[])
Definition: event_machine_eo.c:854
event_machine_hw_types.h
em_event_type_t
uint32_t em_event_type_t
Definition: event_machine_types.h:85
em_receive_multi_func_t
void(* em_receive_multi_func_t)(void *eo_ctx, em_event_t events[], int num, em_queue_t queue, void *q_ctx)
Definition: event_machine_eo.h:189
em_eo_multircv_param_t::receive_multi
em_receive_multi_func_t receive_multi
Definition: event_machine_eo.h:364
em_eo_multircv_param_t::eo_ctx
const void * eo_ctx
Definition: event_machine_eo.h:378
em_stop_local_func_t
em_status_t(* em_stop_local_func_t)(void *eo_ctx, em_eo_t eo)
Definition: event_machine_eo.h:280
em_eo_multircv_param_t::stop
em_stop_func_t stop
Definition: event_machine_eo.h:355
em_notif_t
Definition: event_machine_types.h:268
em_receive_func_t
void(* em_receive_func_t)(void *eo_ctx, em_event_t event, em_event_type_t type, em_queue_t queue, void *q_ctx)
Definition: event_machine_eo.h:149
em_eo_to_u64
uint64_t em_eo_to_u64(em_eo_t eo)
Definition: event_machine_eo.c:1162
em_eo_create
em_eo_t em_eo_create(const char *name, em_start_func_t start, em_start_local_func_t local_start, em_stop_func_t stop, em_stop_local_func_t local_stop, em_receive_func_t receive, const void *eo_ctx)
Definition: event_machine_eo.c:40
em_eo_multircv_param_init
void em_eo_multircv_param_init(em_eo_multircv_param_t *param)
Definition: event_machine_eo.c:108
em_eo_queue_get_first
em_queue_t em_eo_queue_get_first(unsigned int *num, em_eo_t eo)
Definition: event_machine_eo.c:1093
em_eo_queue_get_next
em_queue_t em_eo_queue_get_next(void)
Definition: event_machine_eo.c:1140
em_eo_stop_sync
em_status_t em_eo_stop_sync(em_eo_t eo)
Definition: event_machine_eo.c:897
event_machine_types.h
em_eo_add_queue
em_status_t em_eo_add_queue(em_eo_t eo, em_queue_t queue, int num_notif, const em_notif_t notif_tbl[])
Definition: event_machine_eo.c:336
em_eo_multircv_param_t::__internal_check
uint32_t __internal_check
Definition: event_machine_eo.h:386
em_eo_state_t
em_eo_state_t
Definition: event_machine_types.h:295
em_eo_conf_t
Definition: event_machine_types.h:242
em_eo_get_state
em_eo_state_t em_eo_get_state(em_eo_t eo)
Definition: event_machine_eo.c:1031
em_eo_get_first
em_eo_t em_eo_get_first(unsigned int *num)
Definition: event_machine_eo.c:1051
em_eo_find
em_eo_t em_eo_find(const char *name)
Definition: event_machine_eo.c:265
em_eo_remove_queue_all
em_status_t em_eo_remove_queue_all(em_eo_t eo, int delete_queues, int num_notif, const em_notif_t notif_tbl[])
Definition: event_machine_eo.c:486
em_eo_create_multircv
em_eo_t em_eo_create_multircv(const char *name, const em_eo_multircv_param_t *param)
Definition: event_machine_eo.c:122