EM-ODP  3.8.0-1
Event Machine on ODP
em_event_group.c
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 #include "em_include.h"
32 
34 event_group_init(event_group_tbl_t *const event_group_tbl,
35  odp_stash_t *const event_group_stash)
36 {
37  uint32_t idx;
38  uint32_t val;
39  odp_stash_t stash;
40  em_status_t err_status;
41  event_group_elem_t *egrp_elem;
42  odp_stash_param_t stash_param;
43  odp_stash_capability_t stash_capa;
44 
45  if (odp_stash_capability(&stash_capa, ODP_STASH_TYPE_FIFO) != 0)
46  return EM_ERR_LIB_FAILED;
47 
48  if (stash_capa.max_num.u32 < EM_MAX_EVENT_GROUPS) {
49  EM_LOG(EM_LOG_ERR,
50  "Maximum number of event groups(%d) exceeds the maximum\n"
51  "number of object handles(%" PRIu64 ") a stash can hold.\n",
52  EM_MAX_EVENT_GROUPS, stash_capa.max_num.u32);
53  return EM_ERR_TOO_LARGE;
54  }
55 
56  memset(event_group_tbl, 0, sizeof(event_group_tbl_t));
57  env_atomic32_init(&em_shm->event_group_count);
58 
59  odp_stash_param_init(&stash_param);
60 
61  stash_param.type = ODP_STASH_TYPE_FIFO;
62  stash_param.put_mode = ODP_STASH_OP_MT;
63  stash_param.get_mode = ODP_STASH_OP_MT;
64  stash_param.num_obj = EM_MAX_EVENT_GROUPS;
65  stash_param.obj_size = sizeof(uint32_t);
66 
67  stash = odp_stash_create("event_grp", &stash_param);
68  if (stash == ODP_STASH_INVALID)
69  return EM_ERR_LIB_FAILED;
70 
71  for (idx = 0; idx < EM_MAX_EVENT_GROUPS; idx++) {
72  egrp_elem = &em_shm->event_group_tbl.egrp_elem[idx];
73 
74  egrp_elem->event_group = egrp_idx2hdl(idx); /* store handle */
75  egrp_elem->all = 0; /* set num_notif = 0, ready = 0 */
76  env_atomic64_set(&egrp_elem->post.atomic, 0);
77  env_atomic64_set(&egrp_elem->pre.atomic, 0);
78 
79  egrp_elem->in_stash = true;
80  if (odp_stash_put_u32(stash, &idx, 1) != 1) {
81  err_status = EM_ERR_LIB_FAILED;
82  egrp_elem->in_stash = false;
83  goto error_return;
84  }
85  }
86 
87  *event_group_stash = stash;
88  return EM_OK;
89 
90 error_return:
91  /* Empty the stash before destroying it */
92  for (uint32_t i = 0; i < idx; i++) {
93  odp_stash_get_u32(stash, &val, 1);
94 
95  egrp_elem = &em_shm->event_group_tbl.egrp_elem[i];
96 
97  egrp_elem->event_group = EM_EVENT_GROUP_UNDEF;
98  egrp_elem->in_stash = false;
99  }
100 
101  odp_stash_destroy(stash);
102  return err_status;
103 }
104 
105 em_status_t event_group_term(void)
106 {
107  uint32_t tmp;
108  int32_t num;
109  odp_stash_t stash = em_shm->event_group_stash;
110 
111  while (1) {
112  num = odp_stash_get_u32(stash, &tmp, 1);
113 
114  if (num == 1)
115  continue;
116 
117  if (num == 0)
118  break;
119 
120  EM_PRINT("Stash get failed: %i\n", num);
121  return EM_ERR_LIB_FAILED;
122  }
123 
124  if (odp_stash_destroy(stash))
125  return EM_ERR_LIB_FAILED;
126 
127  return EM_OK;
128 }
129 
130 em_event_group_t
131 event_group_alloc(void)
132 {
133  uint32_t idx;
134  event_group_elem_t *egrp_elem;
135 
136  if (unlikely(odp_stash_get_u32(em_shm->event_group_stash, &idx, 1) != 1))
137  return EM_EVENT_GROUP_UNDEF;
138 
140  return EM_EVENT_GROUP_UNDEF;
141 
142  egrp_elem = &em_shm->event_group_tbl.egrp_elem[idx];
143  egrp_elem->in_stash = false;
144 
145  env_atomic32_inc(&em_shm->event_group_count);
146 
147  return egrp_idx2hdl(idx);
148 }
149 
151 event_group_free(em_event_group_t event_group)
152 {
153  event_group_elem_t *egrp_elem = event_group_elem_get(event_group);
154  uint32_t idx = (uint32_t)egrp_hdl2idx(event_group);
155 
156  if (unlikely(egrp_elem == NULL))
157  return EM_ERR_BAD_ID;
158 
159  if (unlikely(egrp_elem->in_stash))
160  return EM_ERR_BAD_STATE;
161 
162  egrp_elem->in_stash = true;
163  if (unlikely(odp_stash_put_u32(em_shm->event_group_stash, &idx, 1) != 1)) {
164  egrp_elem->in_stash = false;
165  return EM_ERR_LIB_FAILED;
166  }
167 
168  env_atomic32_dec(&em_shm->event_group_count);
169  return EM_OK;
170 }
171 
172 unsigned int
173 event_group_count(void)
174 {
175  return env_atomic32_get(&em_shm->event_group_count);
176 }
177 
178 #define EGRP_INFO_HDR_FMT \
179 "Number of event groups: %d\n\n" \
180 "ID Ready Cnt(post) Gen Num-notif\n" \
181 "------------------------------------------\n%s\n"
182 
183 #define EGRP_INFO_LEN 43
184 #define EGRP_INFO_FMT "%-10" PRI_EGRP "%-7c%-11d%-5d%-9d\n" /*43 bytes*/
185 
187 {
188  unsigned int egrp_num;
189  em_event_group_t egrp;
190  const event_group_elem_t *egrp_elem;
191  egrp_counter_t egrp_count;
192  int len = 0;
193  int n_print = 0;
194 
195  egrp = em_event_group_get_first(&egrp_num);
196 
197  /*
198  * egrp_num may not match the amount of event groups actually returned
199  * by iterating with em_event_group_get_next() if event groups are added
200  * or removed in parallel by another core. Thus space for 10 extra event
201  * groups is reserved. If more than 10 event groups are added by other
202  * cores in parallel, we print only information of the (egrp_num + 10)
203  * event groups.
204  *
205  * The extra 1 byte is reserved for the terminating null byte.
206  */
207  const int egrp_info_str_len = (egrp_num + 10) * EGRP_INFO_LEN + 1;
208  char egrp_info_str[egrp_info_str_len];
209 
210  while (egrp != EM_EVENT_GROUP_UNDEF) {
211  egrp_elem = event_group_elem_get(egrp);
212 
213  if (unlikely(egrp_elem == NULL || !event_group_allocated(egrp_elem))) {
214  egrp = em_event_group_get_next();
215  continue;
216  }
217 
218  egrp_count.all = EM_ATOMIC_GET(&egrp_elem->post.atomic);
219 
220  n_print = snprintf(egrp_info_str + len,
221  egrp_info_str_len - len,
222  EGRP_INFO_FMT, egrp,
223  egrp_elem->ready ? 'Y' : 'N',
224  egrp_count.count, egrp_count.gen,
225  egrp_elem->num_notif);
226 
227  /* Not enough space to hold more event group info */
228  if (n_print >= egrp_info_str_len - len)
229  break;
230 
231  len += n_print;
232  egrp = em_event_group_get_next();
233  }
234 
235  /* No event group */
236  if (len == 0) {
237  EM_PRINT("No event group!\n");
238  return;
239  }
240 
241  /*
242  * To prevent printing incomplete information of the last event group
243  * when there is not enough space to hold all event group info.
244  */
245  egrp_info_str[len] = '\0';
246  EM_PRINT(EGRP_INFO_HDR_FMT, egrp_num, egrp_info_str);
247 }
void event_group_info_print(void)
em_shm_t * em_shm
#define EM_EVENT_GROUP_SAFE_MODE
#define EM_MAX_EVENT_GROUPS
@ EM_ERR_TOO_LARGE
@ EM_ERR_BAD_STATE
@ EM_ERR_LIB_FAILED
#define EM_OK
#define EM_EVENT_GROUP_UNDEF
uint32_t em_status_t
em_event_group_t em_event_group_get_next(void)
em_event_group_t em_event_group_get_first(unsigned int *num)
env_atomic32_t event_group_count
Definition: em_mem.h:140
em_event_group_t event_group