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