EM-ODP  3.8.0-1
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 /**
46  * Send an event to out of EM.
47  * This function is declared as a weak symbol in default implementation
48  * in em_chaining.c, indicating that the user can override it during
49  * linking with another implementation if event chaining is used.
50  */
51 em_status_t event_send_device(em_event_t event, em_queue_t queue);
52 
53 /**
54  * Send multiple events to out of EM.
55  * This function is declared as a weak symbol in default implementation
56  * in em_chaining.c, indicating that the user can override it during
57  * linking with another implementation if event chaining is used.
58  */
59 int event_send_device_multi(const em_event_t events[], int num, em_queue_t queue);
60 
61 #pragma GCC visibility pop
62 
63 /**
64  * Initialize event chaining during start-up.
65  */
67 
68 /**
69  * Terminate event chaining during shut-down.
70  */
71 em_status_t 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_ */
em_status_t chaining_init(event_chaining_t *event_chaining)
Definition: em_chaining.c:137
em_status_t event_send_device(em_event_t event, em_queue_t queue)
em_status_t chaining_term(const event_chaining_t *event_chaining)
Definition: em_chaining.c:196
int event_send_device_multi(const em_event_t events[], int num, em_queue_t queue)
#define INTERNAL_ERROR(error, escope, fmt,...)
Definition: em_error.h:43
#define RETURN_ERROR_IF(cond, error, escope, fmt,...)
Definition: em_error.h:50
ENV_LOCAL em_locm_t em_locm
em_shm_t * em_shm
#define EM_CHECK_LEVEL
#define EM_ESCOPE_EVENT_SEND_DEVICE
#define EM_ESCOPE_EVENT_SEND_DEVICE_MULTI
#define PRI_QUEUE
uint32_t em_status_t
em_sched_context_type_t
@ EM_SCHED_CONTEXT_TYPE_ORDERED
em_sched_context_type_t sched_context_type
Definition: em_mem.h:170
em_locm_current_t current
Definition: em_mem.h:190
int32_t egrp_gen
em_event_group_t egrp