EM-ODP  3.7.0
Event Machine on ODP
em_event_group.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015, 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  *
34  * EM internal event group functions
35  *
36  */
37 
38 #ifndef EM_EVENT_GROUP_H_
39 #define EM_EVENT_GROUP_H_
40 
41 #ifdef __cplusplus
42 extern "C" {
43 #endif
44 
45 #define invalid_egrp(event_group) \
46  ((unsigned int)egrp_hdl2idx((event_group)) >= EM_MAX_EVENT_GROUPS)
47 
49 event_group_init(event_group_tbl_t *const event_group_tbl,
50  event_group_pool_t *const event_group_pool);
51 
52 em_event_group_t
53 event_group_alloc(void);
54 
56 event_group_free(em_event_group_t event_group);
57 
58 static inline int
59 event_group_allocated(const event_group_elem_t *egrp_elem)
60 {
61  return !objpool_in_pool(&egrp_elem->event_group_pool_elem);
62 }
63 
64 static inline int
65 egrp_hdl2idx(const em_event_group_t event_group)
66 {
67  return (int)((uintptr_t)event_group - 1);
68 }
69 
70 static inline em_event_group_t
71 egrp_idx2hdl(const int event_group_idx)
72 {
73  return (em_event_group_t)(uintptr_t)(event_group_idx + 1);
74 }
75 
76 static inline event_group_elem_t *
77 event_group_elem_get(const em_event_group_t event_group)
78 {
79  const int egrp_idx = egrp_hdl2idx(event_group);
80  event_group_elem_t *egrp_elem;
81 
82  if (unlikely((unsigned int)egrp_idx > EM_MAX_EVENT_GROUPS - 1))
83  return NULL;
84 
85  egrp_elem = &em_shm->event_group_tbl.egrp_elem[egrp_idx];
86 
87  return egrp_elem;
88 }
89 
90 static inline uint64_t
91 event_group_gen_get(const event_group_elem_t *egrp_elem)
92 {
93  egrp_counter_t egrp_count;
94 
95  egrp_count.all = EM_ATOMIC_GET(&egrp_elem->post.atomic);
96 
97  return egrp_count.gen;
98 }
99 
100 /**
101  * Verifies event group state and updates pre count before setting core local
102  * event group. Sets group to undefined for excess and expired group events.
103  */
104 static inline void
105 set_local_safe(const em_event_group_t egrp, const int32_t egrp_gen,
106  const unsigned int decr)
107 {
108  em_locm_t *const locm = &em_locm;
109  uint64_t current_count;
110  egrp_counter_t new_count;
111  event_group_elem_t *const egrp_elem = event_group_elem_get(egrp);
112 
113  do {
114  current_count = EM_ATOMIC_GET(&egrp_elem->pre.atomic);
115  new_count.all = current_count;
116  new_count.count -= decr;
117  /* Check for excess and expired group events */
118  if (unlikely(new_count.count < 0 ||
119  new_count.gen != egrp_gen)) {
122  "Expired event group event received!");
124  return;
125  }
126  } while (!EM_ATOMIC_CMPSET(&egrp_elem->pre.atomic,
127  current_count, new_count.all));
128 
129  locm->current.egrp_gen = egrp_gen;
130  locm->current.egrp = egrp;
131  locm->current.egrp_elem = egrp_elem;
132 }
133 
134 /**
135  * Set core local event group.
136  *
137  * Validates event group if EM_EVENT_GROUP_SAFE_MODE is enabled.
138  *
139  * Only called by the EM-dispatcher before receive function.
140  */
141 static inline void
142 event_group_set_local(const em_event_group_t egrp, const int32_t egrp_gen,
143  const unsigned int decr)
144 {
145  if (egrp == EM_EVENT_GROUP_UNDEF)
146  return;
147 
148  /* event group is set: */
150  /* Group is validated before setting */
151  set_local_safe(egrp, egrp_gen, decr);
152  } else {
153  em_locm_t *const locm = &em_locm;
154 
155  locm->current.egrp_elem = event_group_elem_get(egrp);
156  locm->current.egrp = egrp;
157  }
158 }
159 
160 /**
161  * Updates event group counter safely. Generation and count must be valid.
162  */
163 static inline int64_t
164 count_decrement_safe(event_group_elem_t *const egrp_elem,
165  const unsigned int decr)
166 {
167  uint64_t current_count;
168  egrp_counter_t new_count;
169 
170  do {
171  current_count = EM_ATOMIC_GET(&egrp_elem->post.atomic);
172  new_count.all = current_count;
173  new_count.count -= decr;
174  /* Validate group state and generation before changing count */
175  if (unlikely(new_count.count < 0 ||
176  new_count.gen != em_locm.current.egrp_gen)) {
177  /* Suppress error if group is aborted */
178  if (!egrp_elem->ready)
181  "Expired grp event in post cnt!"
182  );
183  return -1;
184  }
185  } while (!EM_ATOMIC_CMPSET(&egrp_elem->post.atomic, current_count,
186  new_count.all));
187  return new_count.count;
188 }
189 
190 /**
191  * Decrements the event group count and sends notif events when group is done
192  *
193  * Only called by the EM-dispatcher after receive function.
194  */
195 static inline void
196 event_group_count_decrement(const unsigned int decr)
197 {
198  int64_t count;
199  event_group_elem_t *const egrp_elem = em_locm.current.egrp_elem;
200 
202  /* Validates group before updating counters */
203  count = count_decrement_safe(egrp_elem, decr);
204  } else {
205  count = EM_ATOMIC_SUB_RETURN(&egrp_elem->post.atomic, decr);
206 
207  if (unlikely(count < 0)) {
208  if (egrp_elem->ready) {
209  /* Counter should stay zero if aborted */
210  egrp_elem->post.all = 0;
211  return;
212  }
213 
214  INTERNAL_ERROR(EM_FATAL(EM_ERR_BAD_ID),
216  "Group count already 0!");
217  }
218  }
219 
220  if (count == 0) { /* Last event in the group */
221  /* Setting pre_count here does nothing as both counters should
222  * be zero. Only due to incorrect usage pre_count is other than
223  * zero when notif events are about to be sent.
224  */
226  egrp_elem->pre.count = 0;
227 
228  const int num_notif = egrp_elem->num_notif;
229  em_status_t ret;
230 
231  /* Copy notifications to local memory */
233 
234  for (int i = 0; i < num_notif; i++) {
235  notif_tbl[i].event = egrp_elem->notif_tbl[i].event;
236  notif_tbl[i].queue = egrp_elem->notif_tbl[i].queue;
237  notif_tbl[i].egroup = egrp_elem->notif_tbl[i].egroup;
238  }
239 
240  egrp_elem->ready = true; /* ready for 'apply' */
241  ret = send_notifs(num_notif, notif_tbl);
242  if (unlikely(ret != EM_OK))
244  "send notifs failed");
245  }
246 }
247 
248 static inline void
249 save_current_evgrp(em_event_group_t *save_egrp /*out*/,
250  event_group_elem_t **save_egrp_elem /*out*/,
251  int32_t *save_egrp_gen /*out*/)
252 {
253  const em_locm_t *locm = &em_locm;
254 
255  *save_egrp_elem = locm->current.egrp_elem;
256  *save_egrp = locm->current.egrp;
257  *save_egrp_gen = locm->current.egrp_gen;
258 }
259 
260 static inline void
261 restore_current_evgrp(const em_event_group_t saved_egrp,
262  event_group_elem_t *const saved_egrp_elem,
263  const int32_t saved_egrp_gen)
264 {
265  em_locm_t *const locm = &em_locm;
266 
267  locm->current.egrp_elem = saved_egrp_elem;
268  locm->current.egrp = saved_egrp;
269  locm->current.egrp_gen = saved_egrp_gen;
270 }
271 
272 unsigned int
273 event_group_count(void);
274 
275 /** Print information about all event groups */
276 void event_group_info_print(void);
277 
278 #ifdef __cplusplus
279 }
280 #endif
281 
282 #endif /* EM_EVENT_GROUP_H_ */
EM_OK
#define EM_OK
Definition: event_machine_types.h:329
em_notif_t::queue
em_queue_t queue
Definition: event_machine_types.h:270
event_group_pool_t
Definition: em_event_group_types.h:111
em_locm
ENV_LOCAL em_locm_t em_locm
event_group_info_print
void event_group_info_print(void)
Definition: em_event_group.c:126
em_locm_t::current
em_locm_current_t current
Definition: em_mem.h:190
EM_EVENT_GROUP_SAFE_MODE
#define EM_EVENT_GROUP_SAFE_MODE
Definition: event_machine_config.h:303
ODP_PACKED::egrp_elem
event_group_elem_t * egrp_elem
Definition: em_mem.h:180
EM_MAX_EVENT_GROUPS
#define EM_MAX_EVENT_GROUPS
Definition: event_machine_config.h:161
event_group_elem_t::num_notif
int num_notif
Definition: em_event_group_types.h:83
egrp_counter_t::gen
int32_t gen
Definition: em_event_group_types.h:52
EM_ERR_BAD_ID
@ EM_ERR_BAD_ID
Definition: event_machine_hw_types.h:265
ODP_PACKED::egrp
em_event_group_t egrp
Definition: em_mem.h:178
INTERNAL_ERROR
#define INTERNAL_ERROR(error, escope, fmt,...)
Definition: em_error.h:43
em_status_t
uint32_t em_status_t
Definition: event_machine_types.h:321
event_group_elem_t::all
uint64_t all
Definition: em_event_group_types.h:88
em_shm
em_shm_t * em_shm
Definition: event_machine_init.c:41
ODP_PACKED::egrp_gen
int32_t egrp_gen
Definition: em_mem.h:182
egrp_counter_t
Definition: em_event_group_types.h:47
EM_ESCOPE_EVENT_GROUP_UPDATE
#define EM_ESCOPE_EVENT_GROUP_UPDATE
Definition: event_machine_hw_types.h:632
event_group_tbl_t
Definition: em_event_group_types.h:103
event_group_elem_t::ready
bool ready
Definition: em_event_group_types.h:85
send_notifs
em_status_t send_notifs(const int num_notif, const em_notif_t notif_tbl[])
Helper func to send notifications events.
Definition: em_internal_event.c:423
em_notif_t
Definition: event_machine_types.h:268
event_group_elem_t::event_group_pool_elem
objpool_elem_t event_group_pool_elem
Definition: em_event_group_types.h:94
EM_EVENT_GROUP_MAX_NOTIF
#define EM_EVENT_GROUP_MAX_NOTIF
Definition: event_machine_config.h:167
event_group_elem_t
Definition: em_event_group_types.h:64
em_locm_t
Definition: em_mem.h:188
EM_EVENT_GROUP_UNDEF
#define EM_EVENT_GROUP_UNDEF
Definition: event_machine_types.h:141
em_notif_t::egroup
em_event_group_t egroup
Definition: event_machine_types.h:271
em_notif_t::event
em_event_t event
Definition: event_machine_types.h:269
egrp_counter_t::count
int32_t count
Definition: em_event_group_types.h:50