EM-ODP  3.7.0
Event Machine on ODP
em_chaining.h
Go to the documentation of this file.
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  /**
32  * @file
33  * EM event chaining support
34  */
35 
36 #ifndef EM_CHAINING_H_
37 #define EM_CHAINING_H_
38 
39 #ifdef __cplusplus
40 extern "C" {
41 #endif
42 
43 #pragma GCC visibility push(default)
44 /**
45  * This function is declared as a weak symbol, indicating that the user should
46  * override it during linking with another implementation if event chaining is
47  * used.
48  */
49 __attribute__((weak))
50 em_status_t event_send_device(em_event_t event, em_queue_t queue);
51 /**
52  * This function is declared as a weak symbol, indicating that the user should
53  * override it during linking with another implementation if event chaining is
54  * used.
55  */
56 __attribute__((weak))
57 int event_send_device_multi(const em_event_t events[], int num,
58  em_queue_t queue);
59 #pragma GCC visibility pop
60 
61 /**
62  * Initialize event chaining during start-up
63  */
65 chaining_init(event_chaining_t *event_chaining);
66 
67 /**
68  * Terminate event chaining during shut-down
69  */
71 chaining_term(const event_chaining_t *event_chaining);
72 
73 /**
74  * Send an event to out of EM (e.g. to another device) via event-chaining and a
75  * user-provided function 'event_send_device()'.
76  * @see event_send_device()
77  */
78 static inline em_status_t
79 send_chaining(em_event_t event, em_queue_t chaining_queue)
80 {
81  const unsigned int num_outq = em_shm->event_chaining.num_output_queues;
82  const em_sched_context_type_t sched_ctx_type =
84 
85  if (num_outq == 0 || sched_ctx_type != EM_SCHED_CONTEXT_TYPE_ORDERED)
86  return event_send_device(event, chaining_queue);
87 
88  /* always use the same output queue for each chaining queue */
89  const internal_queue_t iq = {.queue = chaining_queue};
90  em_queue_t output_queue;
91  queue_elem_t *output_q_elem;
92  uint32_t idx;
93 
94  idx = ((uint32_t)iq.device_id + (uint32_t)iq.queue_id) % num_outq;
95  output_queue = em_shm->event_chaining.output_queues[idx];
96  output_q_elem = queue_elem_get(output_queue);
97 
98  RETURN_ERROR_IF(EM_CHECK_LEVEL >= 3 && !output_q_elem,
100  "Invalid output queue:%" PRI_QUEUE "", output_queue);
101 
102  return send_output(event, output_q_elem);
103 }
104 
105 /**
106  * Send 'num' events out of EM (e.g. to another device) via event-chaining and a
107  * user-provided function 'event_send_device_multi()'.
108  * @see event_send_device_multi()
109  */
110 static inline int
111 send_chaining_multi(const em_event_t events[], const int num,
112  em_queue_t chaining_queue)
113 {
114  const unsigned int num_outq = em_shm->event_chaining.num_output_queues;
115  const em_sched_context_type_t sched_ctx_type =
117 
118  if (num_outq == 0 || sched_ctx_type != EM_SCHED_CONTEXT_TYPE_ORDERED)
119  return event_send_device_multi(events, num, chaining_queue);
120 
121  /* always use the same output queue for each chaining queue */
122  const internal_queue_t iq = {.queue = chaining_queue};
123  em_queue_t output_queue;
124  queue_elem_t *output_q_elem;
125  uint32_t idx;
126 
127  idx = ((uint32_t)iq.device_id + (uint32_t)iq.queue_id) % num_outq;
128  output_queue = em_shm->event_chaining.output_queues[idx];
129  output_q_elem = queue_elem_get(output_queue);
130 
131  if (unlikely(EM_CHECK_LEVEL >= 3 && !output_q_elem)) {
133  "Invalid output queue:%" PRI_QUEUE "", output_queue);
134  return 0;
135  }
136 
137  return send_output_multi(events, num, output_q_elem);
138 }
139 
140 /**
141  * Send an event tagged with an event group out of EM (e.g. to another device)
142  * via event-chaining and a user-provided function 'event_send_device()'.
143  * @see event_send_device()
144  */
145 static inline em_status_t
146 send_chaining_egrp(em_event_t event, event_hdr_t *const ev_hdr,
147  em_queue_t chaining_queue,
148  const event_group_elem_t *egrp_elem)
149 {
150  if (!egrp_elem)
151  return send_chaining(event, chaining_queue);
152 
153  em_event_group_t save_egrp;
154  event_group_elem_t *save_egrp_elem;
155  int32_t save_egrp_gen;
156 
157  /* Send to another DEVICE with an event group */
158  save_current_evgrp(&save_egrp, &save_egrp_elem, &save_egrp_gen);
159  /*
160  * "Simulate" a dispatch round from evgrp perspective,
161  * send-device() instead of EO-receive()
162  */
163  event_group_set_local(ev_hdr->egrp, ev_hdr->egrp_gen, 1);
164 
165  em_status_t stat = send_chaining(event, chaining_queue);
166 
167  event_group_count_decrement(1);
168  restore_current_evgrp(save_egrp, save_egrp_elem, save_egrp_gen);
169 
170  return stat;
171 }
172 
173 /**
174  * Send 'num' events tagged with an event group out of EM (e.g. to another device)
175  * via event-chaining and a user-provided function 'event_send_device_multi()'.
176  * @see event_send_device_multi()
177  */
178 static inline int
179 send_chaining_egrp_multi(const em_event_t events[], event_hdr_t *const ev_hdrs[],
180  const int num, em_queue_t chaining_queue,
181  const event_group_elem_t *egrp_elem)
182 {
183  if (!egrp_elem)
184  return send_chaining_multi(events, num, chaining_queue);
185 
186  em_event_group_t save_egrp;
187  event_group_elem_t *save_egrp_elem;
188  int32_t save_egrp_gen;
189 
190  /* Send to another DEVICE with an event group */
191  save_current_evgrp(&save_egrp, &save_egrp_elem, &save_egrp_gen);
192  /*
193  * "Simulate" dispatch rounds from evgrp perspective,
194  * send-device() instead of EO-receive().
195  * Decrement evgrp-count by 'num' instead of by '1'.
196  * Note: event_group_set_local() called only once for
197  * all events.
198  */
199  event_group_set_local(ev_hdrs[0]->egrp, ev_hdrs[0]->egrp_gen, num);
200 
201  int num_sent = send_chaining_multi(events, num, chaining_queue);
202 
203  event_group_count_decrement(num);
204  restore_current_evgrp(save_egrp, save_egrp_elem, save_egrp_gen);
205 
206  return num_sent;
207 }
208 
209 #ifdef __cplusplus
210 }
211 #endif
212 
213 #endif /* EM_CHAINING_H_ */
ODP_PACKED::sched_context_type
em_sched_context_type_t sched_context_type
Definition: em_mem.h:170
chaining_term
em_status_t chaining_term(const event_chaining_t *event_chaining)
Definition: em_chaining.c:194
event_hdr::egrp_gen
int32_t egrp_gen
Definition: em_event_types.h:260
em_locm
ENV_LOCAL em_locm_t em_locm
em_locm_t::current
em_locm_current_t current
Definition: em_mem.h:190
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
event_hdr
Definition: em_event_types.h:184
RETURN_ERROR_IF
#define RETURN_ERROR_IF(cond, error, escope, fmt,...)
Definition: em_error.h:50
EM_ERR_BAD_ID
@ EM_ERR_BAD_ID
Definition: event_machine_hw_types.h:265
INTERNAL_ERROR
#define INTERNAL_ERROR(error, escope, fmt,...)
Definition: em_error.h:43
EM_ESCOPE_EVENT_SEND_DEVICE_MULTI
#define EM_ESCOPE_EVENT_SEND_DEVICE_MULTI
Definition: event_machine_hw_types.h:626
__attribute__
__attribute__((weak)) em_status_t event_send_device(em_event_t event
em_status_t
uint32_t em_status_t
Definition: event_machine_types.h:321
PRI_QUEUE
#define PRI_QUEUE
Definition: event_machine_types.h:109
EM_SCHED_CONTEXT_TYPE_ORDERED
@ EM_SCHED_CONTEXT_TYPE_ORDERED
Definition: event_machine_types.h:289
EM_CHECK_LEVEL
#define EM_CHECK_LEVEL
Definition: event_machine_config.h:253
event_hdr::egrp
em_event_group_t egrp
Definition: em_event_types.h:265
em_shm
em_shm_t * em_shm
Definition: event_machine_init.c:41
event_group_elem_t
Definition: em_event_group_types.h:64
event_chaining_t
Definition: em_chaining_types.h:45
internal_queue_t
Definition: em_queue_types.h:98
queue_elem_t
Definition: em_queue_types.h:180
em_sched_context_type_t
em_sched_context_type_t
Definition: event_machine_types.h:277