EM-ODP 4.4.0
Event Machine on ODP
Loading...
Searching...
No Matches
em_dispatcher.c
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 _GNU_SOURCE
32#define _GNU_SOURCE
33#endif
34
35#ifdef HAVE_CONFIG_H
36#include "config.h"
37#endif
38
39#include <stdbool.h>
40#include <stdint.h>
41
42#include <odp_api.h>
43
44#include <event_machine.h>
45
46#include "em_dispatcher.h"
48#include "em_dispatcher_types.h"
49#include "em_error.h"
50#include "em_libconfig.h"
51#include "em_mem.h"
52
53static int read_config_file(void)
54{
55 const char *conf_str;
56 int val = 0;
57 int64_t val64 = 0;
58 bool val_bool = false;
59 int ret;
60
61 EM_PRINT("EM dispatch config:\n");
62
63 /*
64 * Option: dispatch.poll_ctrl_interval
65 */
66 conf_str = "dispatch.poll_ctrl_interval";
67 ret = em_libconfig_lookup_int(&em_shm->libconfig, conf_str, &val);
68 if (unlikely(!ret)) {
69 EM_LOG(EM_LOG_ERR, "Config option '%s' not found.\n", conf_str);
70 return -1;
71 }
72
73 if (val < 0) {
74 EM_LOG(EM_LOG_ERR, "Bad config value '%s = %d'\n",
75 conf_str, val);
76 return -1;
77 }
78 /* store & print the value */
79 em_shm->opt.dispatch.poll_ctrl_interval = val;
80 EM_PRINT(" %s: %d\n", conf_str, val);
81
82 /*
83 * Option: dispatch.poll_ctrl_interval_ns
84 */
85 conf_str = "dispatch.poll_ctrl_interval_ns";
86 ret = em_libconfig_lookup_int64(&em_shm->libconfig, conf_str, &val64);
87 if (unlikely(!ret)) {
88 EM_LOG(EM_LOG_ERR, "Config option '%s' not found.\n", conf_str);
89 return -1;
90 }
91
92 if (val64 < 0) {
93 EM_LOG(EM_LOG_ERR, "Bad config value '%s = %" PRId64 "'\n",
94 conf_str, val64);
95 return -1;
96 }
97 /* store & print the value */
98 em_shm->opt.dispatch.poll_ctrl_interval_ns = val64;
99 long double sec = (long double)val64 / 1000000000.0;
100
101 EM_PRINT(" %s: %" PRId64 "ns (%Lfs)\n", conf_str, val64, sec);
102
103 /*
104 * Option: dispatch.poll_drain_interval
105 */
106 conf_str = "dispatch.poll_drain_interval";
107 ret = em_libconfig_lookup_int(&em_shm->libconfig, conf_str, &val);
108 if (unlikely(!ret)) {
109 EM_LOG(EM_LOG_ERR, "Config option '%s' not found.\n", conf_str);
110 return -1;
111 }
112
113 if (val < 0) {
114 EM_LOG(EM_LOG_ERR, "Bad config value '%s = %d'\n",
115 conf_str, val);
116 return -1;
117 }
118 /* store & print the value */
119 em_shm->opt.dispatch.poll_drain_interval = val;
120 EM_PRINT(" %s: %d\n", conf_str, val);
121
122 /*
123 * Option: dispatch.poll_drain_interval_ns
124 */
125 conf_str = "dispatch.poll_drain_interval_ns";
126 ret = em_libconfig_lookup_int64(&em_shm->libconfig, conf_str, &val64);
127 if (unlikely(!ret)) {
128 EM_LOG(EM_LOG_ERR, "Config option '%s' not found.\n", conf_str);
129 return -1;
130 }
131
132 if (val64 < 0) {
133 EM_LOG(EM_LOG_ERR, "Bad config value '%s = %" PRId64 "'\n",
134 conf_str, val64);
135 return -1;
136 }
137 /* store & print the value */
138 em_shm->opt.dispatch.poll_drain_interval_ns = val64;
139 sec = (long double)val64 / 1000000000.0;
140
141 EM_PRINT(" %s: %" PRId64 "ns (%Lfs)\n", conf_str, val64, sec);
142
143 /*
144 * Option: dispatch.sched_wait_ns
145 */
146 conf_str = "dispatch.sched_wait_ns";
148 ret = em_libconfig_lookup_int64(&em_shm->libconfig, conf_str, &val64);
149 if (unlikely(!ret)) {
150 EM_LOG(EM_LOG_ERR, "Config option '%s' not found.\n", conf_str);
151 return -1;
152 }
153
154 if (val64 < -1) {
155 EM_LOG(EM_LOG_ERR, "Bad config value '%s = %" PRId64 "'\n",
156 conf_str, val64);
157 return -1;
158 }
159
160 /* store & print the value */
161 em_shm->opt.dispatch.sched_wait_ns = val64;
162
163 /* Store ns value as odp sched-wait-time */
164 if (val64 == 0) {
165 em_shm->opt_cache.dispatch.sched_wait = ODP_SCHED_NO_WAIT;
166 EM_PRINT(" %s: no-wait (0 ns)\n", conf_str);
167 } else if (val64 == -1) {
168 em_shm->opt_cache.dispatch.sched_wait = ODP_SCHED_WAIT;
169 EM_PRINT(" %s: wait indefinitely (inf. ns)\n", conf_str);
170 } else {
171 em_shm->opt_cache.dispatch.sched_wait = odp_schedule_wait_time(val64);
172 sec = (long double)val64 / 1000000000.0;
173 EM_PRINT(" %s: wait %" PRId64 "ns (%Lfs)\n", conf_str, val64, sec);
174 }
175 } else {
176 em_shm->opt.dispatch.sched_wait_ns = 0;
177 em_shm->opt_cache.dispatch.sched_wait = ODP_SCHED_NO_WAIT;
178 EM_PRINT(" %s: DISABLED (build time), using no-wait (0 ns)\n", conf_str);
179 }
180
181 /*
182 * Option: dispatch.sched_pause
183 */
184 conf_str = "dispatch.sched_pause";
185 ret = em_libconfig_lookup_bool(&em_shm->libconfig, conf_str, &val_bool);
186 if (unlikely(!ret)) {
187 EM_LOG(EM_LOG_ERR, "Config option '%s' not found\n", conf_str);
188 return -1;
189 }
190 /* store & print the value */
191 em_shm->opt.dispatch.sched_pause = val_bool;
192 EM_PRINT(" %s: %s(%d)\n", conf_str, val_bool ? "true" : "false",
193 val_bool);
194
195 return 0;
196}
197
198em_status_t dispatch_init(void)
199{
200 if (read_config_file())
201 return EM_ERR_LIB_FAILED;
202
203 return EM_OK;
204}
205
206em_status_t dispatch_init_local(void)
207{
208 em_locm_t *const locm = &em_locm;
209
210 /*
211 * Convert the poll intervals from ns to odp_time_t here, on this core,
212 * using the CPU-local time source. Per the ODP time spec, local time is
213 * specific to the calling thread/CPU and values from different cores
214 * must not be mixed; the conversion rate (odp_time_local_res()) is not
215 * guaranteed identical across cores. Each core therefore does its own
216 * conversion into core-local memory so the interval shares the same
217 * local time source as the odp_time_local() stamps compared against it.
218 */
220 odp_time_local_from_ns(em_shm->opt.dispatch.poll_ctrl_interval_ns);
222 odp_time_local_from_ns(em_shm->opt.dispatch.poll_drain_interval_ns);
223
224 odp_time_t poll_period = locm->poll_ctrl_interval_time;
225 odp_time_t now = odp_time_local();
226
227 /*
228 * Initialize values so that the _first_ call to em_dispatch() on each
229 * core will trigger a poll of the unscheduled ctrl queues.
230 */
231 locm->dispatch_cnt = 1;
232 locm->dispatch_last_run = odp_time_diff(now, poll_period); /* wrap OK */
233
234 /*
235 * Sanity check:
236 * Perform the same calculation as in dispatch_poll_ctrl_queue()
237 * to verify that ctrl queue polling is triggered by the first dispatch.
238 */
239 odp_time_t period = odp_time_diff(now, locm->dispatch_last_run);
240
241 if (odp_time_cmp(period, poll_period) != 0) /* 0: periods equal */
242 return EM_ERR_TOONEAR;
243
244 locm->poll_drain_dispatch_cnt = em_shm->opt.dispatch.poll_drain_interval;
246
248
249 return EM_OK;
250}
@ IDLE_STATE_ACTIVE
ENV_LOCAL em_locm_t em_locm
em_shm_t * em_shm
#define EM_SCHED_WAIT_ENABLE
#define EM_OK
uint32_t em_status_t
@ EM_ERR_TOONEAR
@ EM_ERR_LIB_FAILED
unsigned int dispatch_cnt
Definition em_mem.h:233
unsigned int poll_drain_dispatch_cnt
Definition em_mem.h:235
odp_time_t poll_ctrl_interval_time
Definition em_mem.h:265
odp_time_t dispatch_last_run
Definition em_mem.h:263
idle_state_t idle_state
Definition em_mem.h:231
odp_time_t poll_drain_dispatch_last_run
Definition em_mem.h:267
odp_time_t poll_drain_interval_time
Definition em_mem.h:269
cfgfile_opt_cache_t opt_cache
Definition em_mem.h:97
em_cfgfile_opts_t opt
Definition em_mem.h:99