EM-ODP  3.8.0-1
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() with notifications or em_eo_stop_sync(), otherwise another core
448  * might still access the EO data.
449  * All associated queues must be removed before deleting an EO.
450  *
451  * A sequence of
452  * @code
453  * em_eo_stop_sync(eo);
454  * em_eo_remove_queue_all_sync(eo, EM_TRUE);
455  * em_eo_delete(eo);
456  * @endcode
457  * will cleanly delete an EO from the EM point of view (not including user
458  * allocated data).
459  *
460  * @param eo EO handle to delete
461  *
462  * @return EM_OK if successful.
463  *
464  * @see em_eo_stop(), em_eo_remove_queue()
465  */
467 em_eo_delete(em_eo_t eo);
468 
469 /**
470  * Returns the name given to the EO when it was created.
471  *
472  * A copy of the name string (up to 'maxlen' characters) is
473  * written to the user buffer 'name'.
474  * The string is always null terminated - even if the given buffer length
475  * is less than the name length.
476  *
477  * The function returns 0 and writes an empty string if the EO has no name.
478  *
479  * @param eo EO handle
480  * @param[out] name Destination buffer
481  * @param maxlen Maximum length (including the terminating '0')
482  *
483  * @return Number of characters written (excludes the terminating '0').
484  *
485  * @see em_eo_create()
486  */
487 size_t
488 em_eo_get_name(em_eo_t eo, char *name, size_t maxlen);
489 
490 /**
491  * Find EO by name.
492  *
493  * Finds an EO by the given name (exact match). An empty string will not match
494  * anything. The search is case sensitive. This function will return the first
495  * match only if there are duplicate names.
496  *
497  * @param name the name to look for
498  *
499  * @return EO handle or EM_EO_UNDEF if not found
500  *
501  * @see em_eo_create()
502  */
503 em_eo_t
504 em_eo_find(const char *name);
505 
506 /**
507  * Add a queue to an EO, asynchronous (non-blocking)
508  *
509  * Add the given queue to the EO and enable scheduling for it. The function
510  * returns immediately, but the operation can be asynchronous and only fully
511  * complete later. The given notification events are sent when the operation has
512  * completed and the queue is ready to receive events.
513  * Note, that the completion notification(s) guarantee that the queue itself is
514  * operational, but if the target EO is not yet started then events sent into
515  * the queue will still be dropped by dispatcher.
516  *
517  * @param eo EO handle
518  * @param queue Queue handle
519  * @param num_notif Number of notification events, 0 for no notification
520  * @param notif_tbl Array of pairs of event and queue identifiers
521  * (+ optional event groups to send the events with)
522  *
523  * @return EM_OK if successful.
524  *
525  * @see em_queue_create(), em_eo_create(), em_eo_remove_queue(),
526  * em_eo_add_queue_sync()
527  */
529 em_eo_add_queue(em_eo_t eo, em_queue_t queue,
530  int num_notif, const em_notif_t notif_tbl[]);
531 
532 /**
533  * Add a queue to an EO, synchronous (blocking)
534  *
535  * As em_eo_add_queue(), but does not return until the queue is ready to
536  * receive events.
537  *
538  * Note that the function is blocking and will not return until the operation
539  * has completed across all concerned EM cores.
540  * Sync-API calls can block the core for a long (indefinite) time, thus they
541  * should not be used to make runtime changes on real time EM cores - consider
542  * the async variants of the APIs in these cases instead.
543  * While one core is calling a sync-API function, the others must be running the
544  * EM dispatch loop to be able to receive and handle the sync-API request events
545  * sent internally.
546  * Use the sync-APIs mainly to simplify application start-up or teardown.
547  *
548  * @param eo EO handle
549  * @param queue Queue handle
550  *
551  * @return EM_OK if successful.
552  *
553  * @see em_queue_create(), em_eo_create(), em_eo_remove_queue()
554  * @see em_eo_add_queue() for an asynchronous version of the API
555  */
557 em_eo_add_queue_sync(em_eo_t eo, em_queue_t queue);
558 
559 /**
560  * Removes a queue from an EO, asynchronous (non-blocking)
561  *
562  * Disables queue scheduling and removes the queue from the EO. The function
563  * returns immediately, but the operation can be asynchronous and only fully
564  * complete later. The given notification events are sent when the operation has
565  * completed across all cores and no event from this queue is being dispatched
566  * anymore. Use notifications to know when the operation has fully completed
567  * and the queue can safely be deleted.
568  *
569  * @param eo EO handle
570  * @param queue Queue handle to remove
571  * @param num_notif Number of notification events, 0 for no notification
572  * @param notif_tbl Array of pairs of event and queue identifiers
573  * (+ optional event groups to send the events with)
574  *
575  * @return EM_OK if successful.
576  *
577  * @see em_eo_add_queue(), em_eo_remove_queue_sync()
578  */
580 em_eo_remove_queue(em_eo_t eo, em_queue_t queue,
581  int num_notif, const em_notif_t notif_tbl[]);
582 
583 /**
584  * Removes a queue from an EO, synchronous (blocking)
585  *
586  * As em_eo_remove_queue(), but will not return until the queue has been
587  * disabled, removed from the EO and no more events are being processed from
588  * the queue.
589  *
590  * Note that the function is blocking and will not return until the operation
591  * has completed across all concerned EM cores.
592  * Sync-API calls can block the core for a long (indefinite) time, thus they
593  * should not be used to make runtime changes on real time EM cores - consider
594  * the async variants of the APIs in these cases instead.
595  * While one core is calling a sync-API function, the others must be running the
596  * EM dispatch loop to be able to receive and handle the sync-API request events
597  * sent internally.
598  * Use the sync-APIs mainly to simplify application start-up or teardown.
599  *
600  * @param eo EO handle
601  * @param queue Queue handle to remove
602  *
603  * @return EM_OK if successful.
604  *
605  * @see em_eo_remove_queue() for an asynchronous version of the API
606  */
608 em_eo_remove_queue_sync(em_eo_t eo, em_queue_t queue);
609 
610 /**
611  * Removes all queues from an EO, asynchronous (non-blocking)
612  *
613  * Like em_eo_remove_queue(), but removes all queues currently associated with
614  * the EO.
615  * The argument 'delete_queues' can be used to automatically also delete all
616  * queues by setting it to EM_TRUE (EM_FALSE otherwise).
617  * Note: any allocated queue contexts will still need to be handled elsewhere.
618  *
619  * @param eo EO handle
620  * @param delete_queues delete the EO's queues if set to EM_TRUE
621  * @param num_notif Number of notification events, 0 for no notification
622  * @param notif_tbl Array of pairs of event and queue identifiers
623  * (+ optional event groups to send the events with)
624  *
625  * @return EM_OK if successful.
626  *
627  * @see em_eo_add_queue(), em_eo_remove_queue_sync(),
628  * em_eo_remove_queue_all_sync()
629  */
631 em_eo_remove_queue_all(em_eo_t eo, int delete_queues,
632  int num_notif, const em_notif_t notif_tbl[]);
633 
634 /**
635  * Removes all queues from an EO, synchronous (blocking).
636  *
637  * As em_eo_remove_queue_all(), but does not return until all queues have
638  * been removed.
639  *
640  * Note that the function is blocking and will not return until the operation
641  * has completed across all concerned EM cores.
642  * Sync-API calls can block the core for a long (indefinite) time, thus they
643  * should not be used to make runtime changes on real time EM cores - consider
644  * the async variants of the APIs in these cases instead.
645  * While one core is calling a sync-API function, the others must be running the
646  * EM dispatch loop to be able to receive and handle the sync-API request events
647  * sent internally.
648  * Use the sync-APIs mainly to simplify application start-up or teardown.
649  *
650  * @param eo EO handle
651  * @param delete_queues delete the EO's queues if set to EM_TRUE
652  *
653  * @return EM_OK if successful.
654  *
655  *
656  * @see em_eo_remove_queue_all() for an asynchronous version of the API
657  */
659 em_eo_remove_queue_all_sync(em_eo_t eo, int delete_queues);
660 
661 /**
662  * Register an EO specific error handler.
663  *
664  * The EO specific error handler is called if an error occurs or em_error() is
665  * called in the context of the running EO.
666  * Note, the provided function will override any previously registered
667  * error handler for the EO in question.
668  * The global error handler is called if no EO specific error handler is
669  * registered.
670  *
671  * @param eo EO handle
672  * @param handler New error handler
673  *
674  * @return EM_OK if successful.
675  *
676  * @see em_register_error_handler(), em_error_handler_t()
677  */
680 
681 /**
682  * Unregister an EO specific error handler.
683  *
684  * Removes a previously registered EO specific error handler and restores the
685  * global error handler into use for the EO.
686  *
687  * @param eo EO handle
688  *
689  * @return EM_OK if successful.
690  */
693 
694 /**
695  * Start an Execution Object (EO), asynchronous (non-blocking)
696  *
697  * Start and enable a previously created EO.
698  * The em_eo_start() function will first call the user provided global EO start
699  * function. If that global start function returns EM_OK then events to trigger
700  * the (optional) user provided local start function are sent to all cores.
701  * The em_eo_start() function returns immediately after the global start
702  * returns, which means that the action only fully completes later.
703  * Notifications should be used if the caller needs to know when the EO start
704  * has fully completed. The given notification event(s) will be sent to the
705  * given queue(s) when the start is completed on all cores.
706  *
707  * Local start is not called and event dispatching is not enabled for this EO if
708  * the global start function does not return EM_OK.
709  *
710  * The notification(s) are sent when the global start function returns if a
711  * local start function hasn't been provided.
712  * Use '0' as 'num_notif' if notifications are not needed. Be aware of,
713  * is this case, that the EO may not immediately be ready to handle events.
714  *
715  * Note that events sent to scheduled queues from a user provided EO global or
716  * local start function are buffered. The buffered events will be sent into the
717  * queues when the EO start functions have all returned - otherwise it would not
718  * be possible to send events to the EO's own queues as the EO is not yet in a
719  * started state. No buffering is done when sending to queues that are
720  * not scheduled.
721  *
722  * The optional conf-argument can be used to pass applification specific
723  * information (e.g. configuration data) to the EO.
724  *
725  * @param eo EO handle
726  * @param[out] result Optional pointer to em_status_t, which gets updated to
727  * the return value of the actual user provided EO global
728  * start function.
729  * @param conf Optional startup configuration, NULL ok.
730  * @param num_notif If not 0, defines the number of notification events to
731  * send when all cores have returned from the start
732  * function(s).
733  * @param notif_tbl Array of em_notif_t, the optional notification events
734  * (array data is copied)
735  *
736  * @return EM_OK if successful.
737  *
738  * @see em_start_func_t(), em_start_local_func_t(), em_eo_stop(),
739  * em_eo_start_sync()
740  */
742 em_eo_start(em_eo_t eo, em_status_t *result, const em_eo_conf_t *conf,
743  int num_notif, const em_notif_t notif_tbl[]);
744 
745 /**
746  * Start Execution Object (EO), synchronous (blocking)
747  *
748  * As em_eo_start(), but will not return until the operation is complete.
749  *
750  * Note that the function is blocking and will not return until the operation
751  * has completed across all concerned EM cores.
752  * Sync-API calls can block the core for a long (indefinite) time, thus they
753  * should not be used to make runtime changes on real time EM cores - consider
754  * the async variants of the APIs in these cases instead.
755  * While one core is calling a sync-API function, the others must be running the
756  * EM dispatch loop to be able to receive and handle the sync-API request events
757  * sent internally.
758  * Use the sync-APIs mainly to simplify application start-up or teardown.
759  *
760  * @param eo EO handle
761  * @param[out] result Optional pointer to em_status_t, which gets updated to
762  * the return value of the actual user provided EO global
763  * start function.
764  * @param conf Optional startup configuration, NULL ok.
765  *
766  * @return EM_OK if successful.
767  *
768  * @see em_start_func_t(), em_start_local_func_t(), em_eo_stop()
769  * @see em_eo_start() for an asynchronous version of the API
770  */
772 em_eo_start_sync(em_eo_t eo, em_status_t *result, const em_eo_conf_t *conf);
773 
774 /**
775  * Stop Execution Object (EO), asynchronous (non-blocking)
776  *
777  * Disables event dispatch from all related queues, calls core local stop
778  * on all cores and finally calls the global stop function of the EO when all
779  * cores have returned from the (optional) core local stop.
780  * The call to the global EO stop is asynchronous and only done when all cores
781  * have completed processing of the receive function and/or core local stop.
782  * This guarantees no other core is accessing EO data during the EO global stop
783  * function.
784  *
785  * This function returns immediately, but may only fully complete later. If the
786  * caller needs to know when the EO stop has actually completed, the num_notif
787  * and notif_tbl should be used. The given notification event(s) will be sent to
788  * given queue(s) when the stop operation actually completes.
789  * If such notifications are not needed, use '0' as 'num_notif'.
790  *
791  * When the EO has stopped it can be started again with em_eo_start().
792  *
793  * @param eo EO handle
794  * @param num_notif Number of notification events, 0 for no notification
795  * @param notif_tbl Array of pairs of event and queue identifiers
796  * (+ optional event groups to send the events with)
797  *
798  * @return EM_OK if successful.
799  *
800  * @see em_stop_func_t(), em_stop_local_func_t(), em_eo_start(),
801  * em_eo_stop_sync()
802  */
804 em_eo_stop(em_eo_t eo, int num_notif, const em_notif_t notif_tbl[]);
805 
806 /**
807  * Stop Execution Object (EO), synchronous (blocking)
808  *
809  * As em_eo_stop(), but will not return until the operation is complete.
810  *
811  * Note that the function is blocking and will not return until the operation
812  * has completed across all concerned EM cores.
813  * Sync-API calls can block the core for a long (indefinite) time, thus they
814  * should not be used to make runtime changes on real time EM cores - consider
815  * the async variants of the APIs in these cases instead.
816  * While one core is calling a sync-API function, the others must be running the
817  * EM dispatch loop to be able to receive and handle the sync-API request events
818  * sent internally.
819  * Use the sync-APIs mainly to simplify application start-up or teardown.
820  *
821  * @param eo EO handle
822  *
823  * @return EM_OK if successful.
824  *
825  * @see em_stop_func_t(), em_stop_local_func_t(), em_eo_start()
826  * @see em_eo_stop() for an asynchronous version of the API
827  */
829 em_eo_stop_sync(em_eo_t eo);
830 
831 /**
832  * Return the currently active EO
833  *
834  * Returns the EO handle associated with the currently running EO function.
835  * Only valid if called within an EO-context, will return EM_EO_UNDEF otherwise.
836  * Can be called from the EO-receive or EO-start/stop functions (or subfunctions
837  * thereof).
838  * Note that calling em_eo_current() from e.g. an EO-start function that was
839  * launched from within another EO's receive will return the EO handle of the
840  * EO being started - i.e. always returns the 'latest' current EO.
841  *
842  * @return The current EO or EM_EO_UNDEF if no current EO (or error)
843  */
844 em_eo_t
845 em_eo_current(void);
846 
847 /**
848  * Get EO specific (application) context.
849  *
850  * Returns the EO context pointer that the application has earlier provided via
851  * em_eo_create().
852  *
853  * @param eo EO for which the context is requested
854  *
855  * @return EO specific context pointer or NULL if no context (or error)
856  */
857 void *
858 em_eo_get_context(em_eo_t eo);
859 
860 /**
861  * Return the EO state.
862  *
863  * Returns the current state of the given EO.
864  *
865  * @return The current EO state or EM_EO_STATE_UNDEF if never created.
866  */
868 em_eo_get_state(em_eo_t eo);
869 
870 /**
871  * Initialize EO iteration and return the first EO handle.
872  *
873  * Can be used to initialize the iteration to retrieve all created EOs for
874  * debugging or management purposes. Use em_eo_get_next() after this call until
875  * it returns EM_EO_UNDEF. A new call to em_eo_get_first() resets the iteration,
876  * which is maintained per core (thread). The operation should be completed in
877  * one go before returning from the EO's event receive function (or start/stop).
878  *
879  * The number of EOs (output arg 'num') may not match the amount of EOs actually
880  * returned by iterating using em_eo_get_next() if EOs are added or removed in
881  * parallel by another core. The order of the returned EO handles is undefined.
882  *
883  * @code
884  * unsigned int num;
885  * em_eo_t eo = em_eo_get_first(&num);
886  * while (eo != EM_EO_UNDEF) {
887  * eo = em_eo_get_next();
888  * }
889  * @endcode
890  *
891  * @param[out] num Pointer to an unsigned int to store the amount of EOs into
892  * @return The first EO handle or EM_EO_UNDEF if none exist
893  *
894  * @see em_eo_get_next()
895  */
896 em_eo_t
897 em_eo_get_first(unsigned int *num);
898 
899 /**
900  * Return the next EO handle.
901  *
902  * Continues the EO iteration started by em_eo_get_first() and returns the next
903  * EO handle.
904  *
905  * @return The next EO handle or EM_EO_UNDEF if the EO iteration is completed
906  * (i.e. no more EO's available).
907  *
908  * @see em_eo_get_first()
909  */
910 em_eo_t
911 em_eo_get_next(void);
912 
913 /**
914  * Initialize iteration of an EO's queues and return the first queue handle.
915  *
916  * Can be used to initialize the iteration to retrieve all queues associated
917  * with the given EO for debugging or management purposes.
918  * Use em_eo_queue_get_next() after this call until it returns EM_QUEUE_UNDEF.
919  * A new call to em_eo_queue_get_first() resets the iteration, which is
920  * maintained per core (thread). The operation should be started and completed
921  * in one go before returning from the EO's event receive function (or
922  * start/stop).
923  *
924  * The number of queues owned by the EO (output arg 'num') may not match the
925  * amount of queues actually returned by iterating using em_eo_queue_get_next()
926  * if queues are added or removed in parallel by another core. The order of
927  * the returned queue handles is undefined.
928  *
929  * Simplified example:
930  * @code
931  * unsigned int num;
932  * em_queue_t q = em_eo_queue_get_first(&num, eo);
933  * while (q != EM_QUEUE_UNDEF) {
934  * q = em_eo_queue_get_next();
935  * }
936  * @endcode
937  *
938  * @param[out] num Output the current amount of queues associated with the EO
939  * @param eo EO handle
940  *
941  * @return The first queue handle or EM_QUEUE_UNDEF if none exist or the EO
942  * is invalid.
943  *
944  * @see em_eo_queue_get_next()
945  **/
946 em_queue_t
947 em_eo_queue_get_first(unsigned int *num, em_eo_t eo);
948 
949 /**
950  * Return the EO's next queue handle.
951  *
952  * Continues the queue iteration started by em_eo_queue_get_first() and returns
953  * the next queue handle owned by the EO.
954  *
955  * @return The next queue handle or EM_QUEUE_UNDEF if the queue iteration is
956  * completed (i.e. no more queues available for this EO).
957  *
958  * @see em_eo_queue_get_first()
959  **/
960 em_queue_t
962 
963 /**
964  * Convert an EO handle to an unsigned integer
965  *
966  * @param eo EO handle to be converted
967  * @return uint64_t value that can be used to print/display the handle
968  *
969  * @note This routine is intended to be used for diagnostic purposes
970  * to enable applications to e.g. generate a printable value that represents
971  * an em_eo_t handle.
972  */
973 uint64_t em_eo_to_u64(em_eo_t eo);
974 
975 /**
976  * @}
977  */
978 #ifdef __cplusplus
979 }
980 #endif
981 
982 #pragma GCC visibility pop
983 #endif /* EVENT_MACHINE_EO_H_ */
uint32_t em_event_type_t
uint32_t em_status_t
em_queue_t em_eo_queue_get_first(unsigned int *num, em_eo_t eo)
em_status_t em_eo_register_error_handler(em_eo_t eo, em_error_handler_t handler)
em_status_t em_eo_remove_queue_all_sync(em_eo_t eo, int delete_queues)
void * em_eo_get_context(em_eo_t eo)
em_eo_t em_eo_current(void)
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)
em_status_t em_eo_remove_queue_all(em_eo_t eo, int delete_queues, int num_notif, const em_notif_t notif_tbl[])
em_status_t em_eo_remove_queue(em_eo_t eo, em_queue_t queue, int num_notif, const em_notif_t notif_tbl[])
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[])
em_status_t em_eo_stop(em_eo_t eo, int num_notif, const em_notif_t notif_tbl[])
em_eo_t em_eo_get_next(void)
em_status_t(* em_start_local_func_t)(void *eo_ctx, em_eo_t eo)
void(* em_receive_func_t)(void *eo_ctx, em_event_t event, em_event_type_t type, em_queue_t queue, void *q_ctx)
em_status_t(* em_stop_func_t)(void *eo_ctx, em_eo_t eo)
em_status_t(* em_stop_local_func_t)(void *eo_ctx, em_eo_t eo)
em_eo_state_t em_eo_get_state(em_eo_t eo)
em_eo_t em_eo_find(const char *name)
em_status_t em_eo_start_sync(em_eo_t eo, em_status_t *result, const em_eo_conf_t *conf)
em_status_t em_eo_unregister_error_handler(em_eo_t eo)
em_status_t em_eo_add_queue(em_eo_t eo, em_queue_t queue, int num_notif, const em_notif_t notif_tbl[])
em_eo_t em_eo_get_first(unsigned int *num)
void em_eo_multircv_param_init(em_eo_multircv_param_t *param)
em_status_t em_eo_add_queue_sync(em_eo_t eo, em_queue_t queue)
em_queue_t em_eo_queue_get_next(void)
em_status_t(* em_start_func_t)(void *eo_ctx, em_eo_t eo, const em_eo_conf_t *conf)
em_status_t em_eo_stop_sync(em_eo_t eo)
size_t em_eo_get_name(em_eo_t eo, char *name, size_t maxlen)
uint64_t em_eo_to_u64(em_eo_t eo)
em_status_t em_eo_delete(em_eo_t eo)
em_status_t em_eo_remove_queue_sync(em_eo_t eo, em_queue_t queue)
em_eo_t em_eo_create_multircv(const char *name, const em_eo_multircv_param_t *param)
void(* em_receive_multi_func_t)(void *eo_ctx, em_event_t events[], int num, em_queue_t queue, void *q_ctx)
em_status_t(* em_error_handler_t)(em_eo_t eo, em_status_t error, em_escope_t escope, va_list args)
em_start_local_func_t local_start
em_receive_multi_func_t receive_multi
em_stop_local_func_t local_stop