EM-ODP 4.4.0
Event Machine on ODP
Loading...
Searching...
No Matches
event_machine_core.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2015-2026, Nokia Solutions and Networks
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * * Neither the name of the copyright holder nor the names of its
15 * contributors may be used to endorse or promote products derived
16 * from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31#ifndef EVENT_MACHINE_CORE_H_
32#define EVENT_MACHINE_CORE_H_
33
34#pragma GCC visibility push(default)
35
36/**
37 * @file
38 * @defgroup em_core EM-core related
39 * core (thread) specific APIs.
40 * @{
41 * An EM-core is a thread/process initialized through EM init APIs with the
42 * core type EM_CORE_TYPE_WORKER or EM_CORE_TYPE_CONTROL and is running the
43 * EM dispatch loop.
44 *
45 * The Event Machine enumerates EM-cores within an EM instance as integers
46 * starting from 0. When adding an EM-core by calling em_init_local() on a
47 * new thread, the next lowest available integer (>=0) will be assigned to the
48 * EM-core as an id. Removing an EM-core from the instance frees the id and can
49 * leave a potential gap in the id range. This means that the core id range
50 * might not be coutiguous after a removal/termination of an EM-core.
51 * The next EM-core added will again acquire the first available core id and
52 * potentially fill a gap in the EM-core id range.
53 */
54
56
57#ifdef __cplusplus
58extern "C" {
59#endif
60
61/**
62 * EM core type
63 */
64typedef enum {
65 /** Undef EM-core type */
67
68 /**
69 * Worker EM-core, has an EM-core ID and must call em_dispatch...().
70 * An EM worker core is pinned to a single CPU by the user before
71 * calling em_init_local() and it runs the EM dispatch loop with
72 * no interrupts.
73 * Meant for real-time processing of events ("RT-core(s)").
74 */
76
77 /**
78 * Control EM-core, has an EM-core ID and calls dispatch (at least
79 * occasionally).
80 * An EM control core can e.g. function as a non-realtime EM-core that
81 * can participate in dispatching of events, but usually via carefully
82 * selected queues and queue groups to avoid disturbing the EM worker
83 * cores that can have real time workloads.
84 * An EM control core need not be pinned to single CPU, but still
85 * runs the dispatch loop.
86 * Meant for non-real-time processing ("NRT-core(s)").
87 */
89
90 /**
91 * External EM thread/process, no EM-core ID, no dispatching allowed.
92 *
93 * An EM external thread is not allowed to participate in event
94 * dispatching (i.e. it must not call any em_dispatch...() functions).
95 * An EM external thread can create/delete EM resources, send events and
96 * poll unscheduled queues etc. but is not considered an EM-core
97 * (hence no bit in an EM coremask) and cannot receive events via
98 * scheduled queues since dispatching is forbidden.
99 * Meant for external control or monitoring of EM.
100 */
102
103 /** Last, for bounds checking only */
106
107/**
108 * Get the EM-core id of the current EM thread/process.
109 *
110 * Returns the EM-core id (logical id) of the calling thread/process.
111 * The Event Machine enumerates EM-cores (i.e. threads/processes of type
112 * EM_CORE_TYPE_WORKER or EM_CORE_TYPE_CONTROL running the EM dispatch loop)
113 * within an EM instance as integers starting from 0. The core id range can
114 * contain gaps if EM-cores have been terminated/removed. Note that external
115 * threads/processes of type EM_CORE_TYPE_EXTERNAL do not have an EM-core id and
116 * this function will return -1 for those instead.
117 * The thread/process must have been initialized as an EM-core with
118 * em_init_local() (or the older em_init_core()) to have a valid EM-core id.
119 *
120 * @note The core id returned for an EM external thread/process of type
121 * EM_CORE_TYPE_EXTERNAL is -1 (i.e. no EM-core id available).
122 *
123 * @return Current logical EM core id.
124 * @retval 0 to EM_MAX_CORES-1 for EM_CORE_TYPE_WORKER or EM_CORE_TYPE_CONTROL
125 * @retval -1 for EM_CORE_TYPE_EXTERNAL
126 * @retval undefined for threads/processes not initialized as EM-cores
127 */
128int em_core_id(void);
129
130/**
131 * The number of EM-cores currently running within the EM instance.
132 *
133 * Adding an EM-core with em_init_local() increases the core count by one (1).
134 * Removing an EM-core with em_term_local() decreases the core count by one (1).
135 *
136 * Only EM-cores of the type EM_CORE_TYPE_WORKER and EM_CORE_TYPE_CONTROL are
137 * included in the count.
138 *
139 * Note that the EM-core count is not constant, instead it varies as EM-cores
140 * are added or removed.
141 * The current EM-core count is limited by em_conf_t::core_count that sets the
142 * maximum count for the EM instance.
143 *
144 * @return The number of currently running EM-cores.
145 */
146uint32_t em_core_count(void);
147
148/**
149 * Maximum number of concurrently running EM-cores allowed for this EM instance.
150 *
151 * The maximum number of EM-cores is a constant value set at startup and cannot
152 * be changed afterwards. The value is the same as the em_conf_t::core_count set
153 * by the user and passed to em_init() (if accepted by EM).
154 * The user provided maximum EM-core count value is within the range
155 * [1, EM_MAX_CORES].
156 * @see em_conf_t::core_count
157 *
158 * The max number of EM-cores is concerned with concurrently running
159 * EM-cores of the type EM_CORE_TYPE_CONTROL or EM_CORE_TYPE_WORKER.
160 * Additionally the user may create threads/processes of type
161 * EM_CORE_TYPE_EXTERNAL that are not included in this max count,
162 * see em_core_type_t.
163 *
164 * @return Maximum number of EM-cores supported by this EM instance.
165 */
166uint32_t em_core_count_max(void);
167
168/**
169 * The number of EM-cores of the specified type currently running within the
170 * EM instance.
171 *
172 * Similar to em_core_count(), but only counts EM-cores of the specified type.
173 *
174 * @param core_type The type of the EM-cores to include in the count.
175 * The core type can be one of the following:
176 * - EM_CORE_TYPE_WORKER: only include worker EM-cores
177 * - EM_CORE_TYPE_CONTROL: only include control EM-cores
178 * - EM_CORE_TYPE_UNDEF: include both worker and control EM-cores
179 * (special usage for the '_UNDEF' type here)
180 * - EM_CORE_TYPE_EXTERNAL: only include EM external
181 * threads/processes (EM external threads/processes are not
182 * considered EM-cores since they do not have an EM-core id)
183 *
184 * Note that the EM-core count is not constant, instead it varies as EM-cores
185 * are added or removed.
186 *
187 * @return The number of currently running EM-cores.
188 */
189uint32_t em_core_type_count(em_core_type_t core_type);
190
191/**
192 * Initialize EM-core id iteration and get the first EM-core id.
193 *
194 * Start a new iteration over EM-core ids and get the EM-core id of the first
195 * (=lowest id) EM-core available at the time of the call.
196 * Optionally outputs the current number of EM-cores via the 'num' output
197 * parameter.
198 * The iteration can be continued with em_core_id_next() until all EM-core
199 * ids have been returned. The iteration stops when either of the functions
200 * return -1.
201 *
202 * Only EM-cores of the type EM_CORE_TYPE_WORKER and/or EM_CORE_TYPE_CONTROL are
203 * included in the iteration, as set by the 'core_type' parameter.
204 *
205 * The EM-core id range may not be contiguous if EM-cores have been removed
206 * after startup. The iteration will return the available EM-core ids in
207 * ascending order. The iteration functions always represent a snapshot of the
208 * available core-ids at a certain time - if EM-cores are added or removed just
209 * after any of the calls then the returned ids might be not be up-to-date.
210 *
211 * Example usage:
212 * @code
213 * uint32_t num;
214 * int core_id = em_core_id_first(EM_CORE_TYPE_WORKER, &num);
215 * while (core_id >= 0) {
216 * ...
217 * core_id = em_core_id_next();
218 * }
219 * @endcode
220 *
221 * @param core_type EM-core type to include in the iteration.
222 * The core type can be one of the following:
223 * - EM_CORE_TYPE_WORKER: only include worker EM-cores
224 * - EM_CORE_TYPE_CONTROL: only include control EM-cores
225 * - EM_CORE_TYPE_UNDEF: include both worker and control EM-cores
226 * (special usage for the '_UNDEF' type here)
227 * @param[out] num Optional output parameter to store the current
228 * number of EM-cores.
229 *
230 * @note the 'num' output parameter only represent the number of EM-cores at the
231 * time of the call and thus the number of iterations with
232 * em_core_id_next() until no more EM-cores are available may differ.
233 *
234 * @return the first available EM-core id or -1 if no EM-cores exist
235 * @retval -1 if no EM-cores exist (of type worker or control)
236 *
237 * @see em_core_id_next()
238 */
239int em_core_id_first(em_core_type_t core_type, uint32_t *num /*out*/);
240
241/**
242 * Continue iteration over EM-core ids and get the next EM-core id available.
243 *
244 * Continue the EM-core iteration started by em_core_id_first() and get the
245 * next EM-core id available at the time of the call. The iteration can be
246 * continued with successive calls to em_core_id_next() until all EM-core
247 * ids have been returned. The iteration stops when the function returns -1.
248 *
249 * Only EM-cores of the type EM_CORE_TYPE_WORKER and/or EM_CORE_TYPE_CONTROL are
250 * included in the iteration, as set by the 'core_type' parameter in the
251 * em_core_id_first() call.
252 *
253 * @note This API function must only be used after first successfully calling
254 * em_core_id_first() to initialize the iteration.
255 *
256 * @return the next available EM-core id or -1 if no more EM-cores exist
257 *
258 * @see em_core_id_first()
259 */
260int em_core_id_next(void);
261
262/**
263 * Retrieve the core mask for all available EM-cores of the specified core type.
264 *
265 * This function populates the provided core mask with the currently running
266 * EM-cores that match the specified core type and returns the number of
267 * EM-cores of the given type set in the mask.
268 *
269 * @param core_type The type of the EM-cores to include in the mask.
270 * The core type can be one of the following:
271 * - EM_CORE_TYPE_WORKER: only include worker EM-cores
272 * - EM_CORE_TYPE_CONTROL: only include control EM-cores
273 * - EM_CORE_TYPE_UNDEF: include both worker and control EM-cores
274 * (special usage for the '_UNDEF' type here)
275 * @param core_mask Pointer to the core mask to be populated.
276 * The core mask is cleared before the EM-cores are set, thus
277 * also in error cases the mask will be zeroed (e.g. when an
278 * invalid 'core_type' is given).
279 *
280 * @return the number of EM-cores of the specified type set in the mask
281 * @retval 0 if no EM-cores of the given type available
282 */
283uint32_t em_core_ids_available(em_core_type_t core_type,
284 em_core_mask_t *core_mask /*out*/);
285
286/**
287 * EM-core type of the calling EM thread/process.
288 *
289 * Return the EM-core type of the calling thread/process.
290 * The thread/process must have been initialized as an EM-core with
291 * em_init_local() (or the older em_init_core()) to have a valid EM-core type.
292 *
293 * @return EM-core type.
294 * @retval undefined for threads/processes not initialized as EM-cores
295 */
297
298/**
299 * @}
300 */
301#ifdef __cplusplus
302}
303#endif
304
305#pragma GCC visibility pop
306#endif /* EVENT_MACHINE_CORE_H_ */
int em_core_id_next(void)
int em_core_id(void)
uint32_t em_core_ids_available(em_core_type_t core_type, em_core_mask_t *core_mask)
em_core_type_t
int em_core_id_first(em_core_type_t core_type, uint32_t *num)
em_core_type_t em_core_type(void)
uint32_t em_core_count(void)
uint32_t em_core_count_max(void)
uint32_t em_core_type_count(em_core_type_t core_type)
@ EM_CORE_TYPE_CONTROL
@ EM_CORE_TYPE_LAST
@ EM_CORE_TYPE_EXTERNAL
@ EM_CORE_TYPE_UNDEF
@ EM_CORE_TYPE_WORKER