EM-ODP 4.4.0
Event Machine on ODP
Loading...
Searching...
No Matches
em_chaining.c
1/*
2 * Copyright (c) 2020-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 _GNU_SOURCE
32#define _GNU_SOURCE
33#endif
34
35#ifdef HAVE_CONFIG_H
36#include "config.h"
37#endif
38
39#include <stdint.h>
40#include <stdio.h>
41
42#include <odp_api.h>
43
44#include <event_machine.h>
46
47#include "em_chaining.h"
48#include "em_chaining_types.h"
49#include "em_error.h"
50#include "em_event.h"
51#include "em_event_inline.h"
52#include "em_event_state.h"
53#include "em_event_types.h"
54#include "em_libconfig.h"
55#include "em_mem.h"
56#include "em_queue.h"
57#include "em_queue_inline.h"
58#include "em_queue_types.h"
59
60/* em_output_func_t for event-chaining output*/
61int chaining_output(const em_event_t events[], const unsigned int num,
62 const em_queue_t output_queue, void *output_fn_args);
63
64/*
65 * The weak default implementations of the event-chaining output hooks
66 * event_send_device() / event_send_device_multi() live in their own
67 * translation unit (em_chaining_default.c), built without LTO, so that an
68 * application's strong override resolves reliably under static + LTO builds.
69 */
70
71static int
72read_config_file(void)
73{
74 const char *conf_str;
75 int val = 0;
76 bool val_bool = false;
77 int ret;
78
79 /* Zero all options first */
80 memset(&em_shm->opt.event_chaining, 0, sizeof(em_shm->opt.event_chaining));
81
82 EM_PRINT("EM event-chaining config:\n");
83 /*
84 * Option: event_chaining.order_keep - runtime enable/disable
85 */
86 conf_str = "event_chaining.order_keep";
87 ret = em_libconfig_lookup_bool(&em_shm->libconfig, conf_str, &val_bool);
88 if (unlikely(!ret)) {
89 EM_LOG(EM_LOG_ERR, "Config option '%s' not found\n", conf_str);
90 return -1;
91 }
92 /* store & print the value */
93 em_shm->opt.event_chaining.order_keep = val_bool;
94 EM_PRINT(" %s: %s(%d)\n", conf_str, val_bool ? "true" : "false",
95 val_bool);
96
97 /* Read no more options if ordering is disabled */
98 if (!em_shm->opt.event_chaining.order_keep)
99 return 0; /* Note! */
100
101 /* Temporary: Event chaining re-ordering not yet supported */
102 if (unlikely(em_shm->opt.event_chaining.order_keep)) {
103 EM_LOG(EM_LOG_ERR,
104 "Config option %s: %s(%d) currently not supported\n",
105 conf_str, val_bool ? "true" : "false", val_bool);
106 return -1;
107 }
108
109 /*
110 * Option: event_chaining.num_order_queues
111 * (only read if .order_keep == true above)
112 */
113 conf_str = "event_chaining.num_order_queues";
114 ret = em_libconfig_lookup_int(&em_shm->libconfig, conf_str, &val);
115 if (unlikely(!ret)) {
116 EM_LOG(EM_LOG_ERR, "Config option '%s' not found.\n", conf_str);
117 return -1;
118 }
119 if (val < 0 || val > MAX_CHAINING_OUTPUT_QUEUES) {
120 EM_LOG(EM_LOG_ERR, "Bad config value '%s = %d' (max: %d)\n",
121 conf_str, val, MAX_CHAINING_OUTPUT_QUEUES);
122 return -1;
123 }
124 /* store & print the value */
125 em_shm->opt.event_chaining.num_order_queues = val;
126 EM_PRINT(" %s: %d (max: %d)\n", conf_str, val,
127 MAX_CHAINING_OUTPUT_QUEUES);
128
129 return 0;
130}
131
133chaining_init(event_chaining_t *event_chaining)
134{
135 if (read_config_file())
136 return EM_ERR_LIB_FAILED;
137
138 /* Remains '0' if 'event_chaining.order_keep = false' in config file */
139 event_chaining->num_output_queues = 0;
140
141 for (unsigned int i = 0; i < MAX_CHAINING_OUTPUT_QUEUES; i++)
142 event_chaining->output_queues[i] = EM_QUEUE_UNDEF;
143
144 if (!em_shm->opt.event_chaining.order_keep)
145 return EM_OK; /* don't create output queues for event chaining */
146
147 /*
148 * Create EM output queues for event chaining, needed to maintain event
149 * order during an ordered context
150 */
151 em_queue_conf_t queue_conf;
152 em_output_queue_conf_t output_conf;
153
154 memset(&queue_conf, 0, sizeof(queue_conf));
155 memset(&output_conf, 0, sizeof(output_conf));
156
157 queue_conf.flags = EM_QUEUE_FLAG_DEFAULT;
158 queue_conf.min_events = 0; /* system default */
159 queue_conf.conf_len = sizeof(output_conf);
160 queue_conf.conf = &output_conf;
161 /* Set output-queue callback function, no args needed */
162 output_conf.output_fn = chaining_output;
163 output_conf.output_fn_args = NULL;
164 output_conf.args_len = 0;
165
166 const unsigned int num = em_shm->opt.event_chaining.num_order_queues;
167 unsigned char idx = 0;
168
169 for (unsigned int i = 0; i < num; i++) {
170 char name[EM_QUEUE_NAME_LEN];
171
172 snprintf(name, sizeof(name), "Event-Chaining-Output-%02u", idx);
173 idx++;
174 name[sizeof(name) - 1] = '\0';
175
176 em_queue_t output_queue = em_queue_create(name,
180 &queue_conf);
181 if (unlikely(output_queue == EM_QUEUE_UNDEF))
182 return EM_ERR_ALLOC_FAILED;
183
184 event_chaining->num_output_queues++;
185 event_chaining->output_queues[i] = output_queue;
186 }
187
188 return EM_OK;
189}
190
192chaining_term(const event_chaining_t *event_chaining)
193{
194 /* num = 0 if 'event_chaining.order_keep = false' in config file */
195 const unsigned int num = event_chaining->num_output_queues;
196
197 for (unsigned int i = 0; i < num; i++) {
198 em_queue_t output_queue = event_chaining->output_queues[i];
199 /* delete the output queues associated with event chaining */
200 em_status_t stat = em_queue_delete(output_queue);
201
202 if (unlikely(stat != EM_OK))
203 return stat;
204 }
205
206 return EM_OK;
207}
208
209/**
210 * Output-queue callback function of type 'em_output_func_t' for Event-Chaining.
211 * Only needed when sending during an ordered-context when the EM config file
212 * option is set to 'event_chaining.order_keep = true'.
213 */
214int
215chaining_output(const em_event_t events[], const unsigned int num,
216 const em_queue_t output_queue, void *output_fn_args)
217{
218 /*
219 * NOTE!
220 * Temporary: Not supporting the EM config file option
221 * 'event_chaining.order_keep = true' at the moment, checked during
222 * chaining_init() -> read_config_file().
223 * This function will thus not be called until support added.
224 */
225 em_queue_t chaining_queue = EM_QUEUE_UNDEF;
226
227 (void)output_queue;
228 (void)output_fn_args;
229
230 if (unlikely(num <= 0))
231 return 0;
232
233 if (num == 1) {
234 em_status_t stat = event_send_device(events[0], chaining_queue);
235
236 if (unlikely(stat != EM_OK))
237 return 0;
238 return 1;
239 }
240
241 /*
242 * num > 1:
243 */
244 int ret = event_send_device_multi(events, num, chaining_queue);
245
246 if (unlikely((unsigned int)ret != num)) {
247 if (ret < 0)
248 return 0;
249 else
250 return ret;
251 }
252
253 return num;
254}
em_status_t event_send_device(em_event_t event, em_queue_t queue)
int event_send_device_multi(const em_event_t events[], int num, em_queue_t queue)
em_shm_t * em_shm
#define EM_QUEUE_NAME_LEN
#define EM_QUEUE_GROUP_UNDEF
#define EM_QUEUE_UNDEF
#define EM_OK
uint32_t em_status_t
@ EM_ERR_ALLOC_FAILED
@ EM_ERR_LIB_FAILED
em_status_t em_queue_delete(em_queue_t queue)
#define EM_QUEUE_PRIO_UNDEF
#define EM_QUEUE_FLAG_DEFAULT
em_queue_t em_queue_create(const char *name, em_queue_type_t type, em_queue_prio_t prio, em_queue_group_t group, const em_queue_conf_t *conf)
@ EM_QUEUE_TYPE_OUTPUT
em_queue_flag_t flags
em_cfgfile_opts_t opt
Definition em_mem.h:99