EM-ODP  3.7.0
Event Machine on ODP
em_queue_inline.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  * EM internal queue functions
34  */
35 
36 #ifndef EM_QUEUE_INLINE_H_
37 #define EM_QUEUE_INLINE_H_
38 
39 #ifdef __cplusplus
40 extern "C" {
41 #endif
42 
43 #include <stdlib.h>
44 
45 #define DIFF_ABS(a, b) ((a) > (b) ? (a) - (b) : (b) - (a))
46 #define SMALLEST_NBR(a, b) ((a) > (b) ? (b) : (a))
47 
48 /** Is the queue allocated? */
49 static inline int
50 queue_allocated(const queue_elem_t *const queue_elem)
51 {
52  return !objpool_in_pool(&queue_elem->queue_pool_elem);
53 }
54 
55 /** Convert EM queue handle to queue index */
56 static inline int
57 queue_hdl2idx(em_queue_t queue)
58 {
59  internal_queue_t iq = {.queue = queue};
60  int queue_idx;
61 
62  queue_idx = iq.queue_id - EM_QUEUE_RANGE_OFFSET;
63 
64  return queue_idx;
65 }
66 
67 /** Convert queue index to EM queue handle */
68 static inline em_queue_t
69 queue_idx2hdl(int queue_idx)
70 {
71  internal_queue_t iq = {.queue = 0};
72 
73  iq.queue_id = queue_idx + EM_QUEUE_RANGE_OFFSET;
74  iq.device_id = em_shm->conf.device_id;
75 
76  return iq.queue;
77 }
78 
79 /** Convert queue ID (internal_queue_t:queue_id) to queue index */
80 static inline int
81 queue_id2idx(uint16_t queue_id)
82 {
83  return (int)queue_id - EM_QUEUE_RANGE_OFFSET;
84 }
85 
86 /** Convert queue ID (internal_queue_t:queue_id) handle to EM queue handle */
87 static inline em_queue_t
88 queue_id2hdl(uint16_t queue_id)
89 {
90  internal_queue_t iq = {.queue = 0};
91 
92  iq.queue_id = queue_id;
93  iq.device_id = em_shm->conf.device_id;
94 
95  return iq.queue;
96 }
97 
98 /**
99  * Return 'true' if the EM queue handle belongs to another EM instance.
100  *
101  * Sending to external queues will cause EM to call the user provided
102  * functions 'event_send_device' or 'event_send_device_multi'
103  */
104 static inline bool
105 queue_external(em_queue_t queue)
106 {
107  internal_queue_t iq = {.queue = queue};
108 
109  if (unlikely(queue == EM_QUEUE_UNDEF))
110  return 0;
111 
112  return iq.device_id != em_shm->conf.device_id ? true : false;
113 }
114 
115 /** Returns queue element associated with queued id 'queue' */
116 static inline queue_elem_t *
117 queue_elem_get(const em_queue_t queue)
118 {
119  int queue_idx;
120  internal_queue_t iq;
121  queue_elem_t *queue_elem;
122 
123  iq.queue = queue;
124  queue_idx = queue_id2idx(iq.queue_id);
125 
126  if (unlikely(iq.device_id != em_shm->conf.device_id ||
127  (unsigned int)queue_idx > em_shm->opt.queue.max_num - 1))
128  return NULL;
129 
130  queue_elem = &em_shm->queue_tbl.queue_elem[queue_idx];
131 
132  return queue_elem;
133 }
134 
135 static inline em_queue_t
136 queue_current(void)
137 {
138  const queue_elem_t *const q_elem = em_locm.current.q_elem;
139 
140  if (unlikely(q_elem == NULL))
141  return EM_QUEUE_UNDEF;
142 
143  return (em_queue_t)(uintptr_t)q_elem->queue;
144 }
145 
146 static inline queue_elem_t *
147 list_node_to_queue_elem(const list_node_t *const list_node)
148 {
149  queue_elem_t *const q_elem = (queue_elem_t *)((uintptr_t)list_node
150  - offsetof(queue_elem_t, queue_node));
151 
152  return likely(list_node != NULL) ? q_elem : NULL;
153 }
154 
155 static inline int
156 prio_em2odp(em_queue_prio_t em_prio, odp_schedule_prio_t *odp_prio /*out*/)
157 {
158  if (em_prio < EM_QUEUE_PRIO_NUM) {
159  *odp_prio = em_shm->queue_prio.map[em_prio];
160  return 0;
161  }
162  return -1;
163 }
164 
165 static inline int
166 scheduled_queue_type_em2odp(em_queue_type_t em_queue_type,
167  odp_schedule_sync_t *odp_schedule_sync /* out */)
168 {
169  switch (em_queue_type) {
171  *odp_schedule_sync = ODP_SCHED_SYNC_ATOMIC;
172  return 0;
174  *odp_schedule_sync = ODP_SCHED_SYNC_PARALLEL;
175  return 0;
177  *odp_schedule_sync = ODP_SCHED_SYNC_ORDERED;
178  return 0;
179  default:
180  return -1;
181  }
182 }
183 
184 static inline int
185 scheduled_queue_type_odp2em(odp_schedule_sync_t odp_schedule_sync,
186  em_queue_type_t *em_queue_type /* out */)
187 {
188  switch (odp_schedule_sync) {
189  case ODP_SCHED_SYNC_ATOMIC:
190  *em_queue_type = EM_QUEUE_TYPE_ATOMIC;
191  return 0;
192  case ODP_SCHED_SYNC_PARALLEL:
193  *em_queue_type = EM_QUEUE_TYPE_PARALLEL;
194  return 0;
195  case ODP_SCHED_SYNC_ORDERED:
196  *em_queue_type = EM_QUEUE_TYPE_PARALLEL_ORDERED;
197  return 0;
198  default:
199  *em_queue_type = EM_QUEUE_TYPE_UNDEF;
200  return 0;
201  }
202 }
203 
204 static inline em_event_t
205 queue_dequeue(const queue_elem_t *q_elem)
206 {
207  odp_queue_t odp_queue;
208  odp_event_t odp_event;
209  em_event_t em_event;
210 
211  odp_queue = q_elem->odp_queue;
212  odp_event = odp_queue_deq(odp_queue);
213  if (odp_event == ODP_EVENT_INVALID)
214  return EM_EVENT_UNDEF;
215 
216  em_event = event_odp2em(odp_event);
217 
218  if (esv_enabled()) {
219  event_hdr_t *ev_hdr = event_to_hdr(em_event);
220 
221  em_event = evstate_em2usr(em_event, ev_hdr, EVSTATE__DEQUEUE);
222  }
223 
224  return em_event;
225 }
226 
227 static inline int
228 queue_dequeue_multi(const queue_elem_t *q_elem,
229  em_event_t events[/*out*/], int num)
230 {
231  odp_queue_t odp_queue;
232  int ret;
233 
234  /* use same output-array for dequeue: odp_events[] = events[] */
235  odp_event_t *const odp_events = (odp_event_t *)events;
236 
237  odp_queue = q_elem->odp_queue;
238  ret = odp_queue_deq_multi(odp_queue, odp_events /*out*/, num);
239  if (ret <= 0)
240  return ret;
241 
242  /* now events[] = odp_events[], events[].evgen missing, set below: */
243  if (esv_enabled()) {
244  event_hdr_t *ev_hdrs[ret];
245 
246  event_to_hdr_multi(events, ev_hdrs, ret);
247  evstate_em2usr_multi(events, ev_hdrs, ret,
248  EVSTATE__DEQUEUE_MULTI);
249  }
250 
251  return ret;
252 }
253 
254 #ifdef __cplusplus
255 }
256 #endif
257 
258 #endif /* EM_QUEUE_INLINE_H_ */
EM_QUEUE_PRIO_NUM
#define EM_QUEUE_PRIO_NUM
Definition: event_machine_hw_config.h:103
em_shm_t::queue_prio
struct em_shm_t::@53 queue_prio
EM_EVENT_UNDEF
#define EM_EVENT_UNDEF
Definition: event_machine_types.h:62
EM_QUEUE_TYPE_PARALLEL
@ EM_QUEUE_TYPE_PARALLEL
Definition: event_machine_hw_types.h:117
em_locm
ENV_LOCAL em_locm_t em_locm
queue_elem_t::queue_pool_elem
objpool_elem_t queue_pool_elem
Definition: em_queue_types.h:259
em_locm_t::current
em_locm_current_t current
Definition: em_mem.h:190
EM_QUEUE_TYPE_ATOMIC
@ EM_QUEUE_TYPE_ATOMIC
Definition: event_machine_hw_types.h:112
list_node_t
Definition: list.h:42
em_queue_type_t
uint32_t em_queue_type_t
Definition: event_machine_types.h:168
event_hdr
Definition: em_event_types.h:184
EM_QUEUE_RANGE_OFFSET
#define EM_QUEUE_RANGE_OFFSET
Definition: event_machine_hw_config.h:115
EM_QUEUE_TYPE_UNDEF
@ EM_QUEUE_TYPE_UNDEF
Definition: event_machine_hw_types.h:107
em_shm_t::map
int map[EM_QUEUE_PRIO_NUM]
Definition: em_mem.h:150
queue_elem_t::odp_queue
odp_queue_t odp_queue
Definition: em_queue_types.h:228
queue_elem_t::queue
uint32_t queue
Definition: em_queue_types.h:225
ODP_PACKED::q_elem
queue_elem_t * q_elem
Definition: em_mem.h:174
evstate_em2usr
em_event_t evstate_em2usr(em_event_t event, event_hdr_t *const ev_hdr, const uint16_t api_op)
Definition: em_event_state.c:952
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_QUEUE_TYPE_PARALLEL_ORDERED
@ EM_QUEUE_TYPE_PARALLEL_ORDERED
Definition: event_machine_hw_types.h:122
evstate_em2usr_multi
void evstate_em2usr_multi(em_event_t ev_tbl[], event_hdr_t *const ev_hdr_tbl[], const int num, const uint16_t api_op)
Definition: em_event_state.c:970
em_queue_prio_t
uint32_t em_queue_prio_t
Definition: event_machine_types.h:186
internal_queue_t
Definition: em_queue_types.h:98
queue_elem_t
Definition: em_queue_types.h:180