Revert "l4p/tcp: introduce tle_tcp_stream_establish() API"
[tldk.git] / lib / libtle_l4p / tle_event.h
1 /*
2  * Copyright (c) 2016  Intel Corporation.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15
16 #ifndef _SEV_IMPL_H_
17 #define _SEV_IMPL_H_
18
19 #include <rte_common.h>
20 #include <rte_memory.h>
21 #include <rte_spinlock.h>
22 #include <rte_atomic.h>
23 #include <sys/queue.h>
24
25 #ifdef __cplusplus
26 extern "C" {
27 #endif
28
29 struct tle_evq;
30
31 /**
32  * Possible states of the event.
33  */
34 enum tle_ev_state {
35         TLE_SEV_IDLE,
36         TLE_SEV_DOWN,
37         TLE_SEV_UP,
38         TLE_SEV_NUM
39 };
40
41 struct tle_event {
42         TAILQ_ENTRY(tle_event) ql;
43         struct tle_evq *head;
44         const void *data;
45         enum tle_ev_state state;
46 } __rte_cache_aligned;
47
48 struct tle_evq {
49         rte_spinlock_t lock;
50         uint32_t nb_events;
51         uint32_t nb_armed;
52         uint32_t nb_free;
53         TAILQ_HEAD(, tle_event) armed;
54         TAILQ_HEAD(, tle_event) free;
55         struct tle_event events[0];
56 };
57
58 /**
59  * event queue creation parameters.
60  */
61 struct tle_evq_param {
62         int32_t socket_id;    /**< socket ID to allocate memory from. */
63         uint32_t max_events;  /**< max number of events in queue. */
64 };
65
66 /**
67  * create event queue.
68  * @param prm
69  *   Parameters used to create and initialise the queue.
70  * @return
71  *   Pointer to new event queue structure,
72  *   or NULL on error, with error code set in rte_errno.
73  *   Possible rte_errno errors include:
74  *   - EINVAL - invalid parameter passed to function
75  *   - ENOMEM - out of memory
76  */
77 struct tle_evq *tle_evq_create(const struct tle_evq_param *prm);
78
79 /**
80  * Destroy given event queue.
81  *
82  * @param evq
83  *   event queue to destroy
84  */
85 void tle_evq_destroy(struct tle_evq *evq);
86
87 /**
88  * allocate a new event within given event queue.
89  * @param evq
90  *    event queue to allocate a new stream within.
91  * @param data
92  *   User data to be associated with that event.
93  * @return
94  *   Pointer to event structure that can be used in future tle_event API calls,
95  *   or NULL on error, with error code set in rte_errno.
96  *   Possible rte_errno errors include:
97  *   - EINVAL - invalid parameter passed to function
98  *   - ENOMEM - max limit of allocated events reached for that context
99  */
100 struct tle_event *tle_event_alloc(struct tle_evq *evq, const void *data);
101
102 /**
103  * free an allocated event.
104  * @param ev
105  *   Pointer to the event to free.
106  */
107 void tle_event_free(struct tle_event *ev);
108
109 static inline enum tle_ev_state
110 tle_event_state(const struct tle_event *ev)
111 {
112         return ev->state;
113 }
114
115 /**
116  * move event from DOWN to UP state.
117  * @param ev
118  *   Pointer to the event.
119  */
120 static inline void
121 tle_event_raise(struct tle_event *ev)
122 {
123         struct tle_evq *q;
124
125         if (ev->state != TLE_SEV_DOWN)
126                 return;
127
128         q = ev->head;
129         rte_compiler_barrier();
130
131         rte_spinlock_lock(&q->lock);
132         if (ev->state == TLE_SEV_DOWN) {
133                 ev->state = TLE_SEV_UP;
134                 TAILQ_INSERT_TAIL(&q->armed, ev, ql);
135                 q->nb_armed++;
136         }
137         rte_spinlock_unlock(&q->lock);
138 }
139
140 /**
141  * move event from UP to DOWN state.
142  * @param ev
143  *   Pointer to the event.
144  */
145 static inline void
146 tle_event_down(struct tle_event *ev)
147 {
148         struct tle_evq *q;
149
150         if (ev->state != TLE_SEV_UP)
151                 return;
152
153         q = ev->head;
154         rte_compiler_barrier();
155
156         rte_spinlock_lock(&q->lock);
157         if (ev->state == TLE_SEV_UP) {
158                 ev->state = TLE_SEV_DOWN;
159                 TAILQ_REMOVE(&q->armed, ev, ql);
160                 q->nb_armed--;
161         }
162         rte_spinlock_unlock(&q->lock);
163 }
164
165 /**
166  * move from IDLE to DOWN/UP state.
167  * @param ev
168  *   Pointer to the event.
169  * @param st
170  *   new state for the event.
171  */
172 static inline void
173 tle_event_active(struct tle_event *ev, enum tle_ev_state st)
174 {
175         struct tle_evq *q;
176
177         if (ev->state != TLE_SEV_IDLE)
178                 return;
179
180         q = ev->head;
181         rte_compiler_barrier();
182
183         rte_spinlock_lock(&q->lock);
184         if (st > ev->state) {
185                 if (st == TLE_SEV_UP) {
186                         TAILQ_INSERT_TAIL(&q->armed, ev, ql);
187                         q->nb_armed++;
188                 }
189                 ev->state = st;
190         }
191         rte_spinlock_unlock(&q->lock);
192 }
193
194 /**
195  * move event IDLE state.
196  * @param ev
197  *   Pointer to the event.
198  */
199 static inline void
200 tle_event_idle(struct tle_event *ev)
201 {
202         struct tle_evq *q;
203
204         if (ev->state == TLE_SEV_IDLE)
205                 return;
206
207         q = ev->head;
208         rte_compiler_barrier();
209
210         rte_spinlock_lock(&q->lock);
211         if (ev->state == TLE_SEV_UP) {
212                 TAILQ_REMOVE(&q->armed, ev, ql);
213                 q->nb_armed--;
214         }
215         ev->state = TLE_SEV_IDLE;
216         rte_spinlock_unlock(&q->lock);
217 }
218
219 static inline void
220 tle_evq_idle(struct tle_evq *evq, struct tle_event *ev[], uint32_t num)
221 {
222         uint32_t i, n;
223
224         rte_spinlock_lock(&evq->lock);
225
226         n = 0;
227         for (i = 0; i != num; i++) {
228                 if (ev[i]->state == TLE_SEV_UP) {
229                         TAILQ_REMOVE(&evq->armed, ev[i], ql);
230                         n++;
231                 }
232                 ev[i]->state = TLE_SEV_IDLE;
233         }
234
235         evq->nb_armed -= n;
236         rte_spinlock_unlock(&evq->lock);
237 }
238
239
240 /*
241  * return up to *num* user data pointers associated with
242  * the events that were in the UP state.
243  * Each retrieved event is automatically moved into the DOWN state.
244  * @param evq
245  *   event queue to retrieve events from.
246  * @param evd
247  *   An array of user data pointers associated with the events retrieved.
248  *   It must be large enough to store up to *num* pointers in it.
249  * @param num
250  *   Number of elements in the *evd* array.
251  * @return
252  *   number of of entries filled inside *evd* array.
253  */
254 static inline int32_t
255 tle_evq_get(struct tle_evq *evq, const void *evd[], uint32_t num)
256 {
257         uint32_t i, n;
258         struct tle_event *ev;
259
260         if (evq->nb_armed == 0)
261                 return 0;
262
263         rte_compiler_barrier();
264
265         rte_spinlock_lock(&evq->lock);
266         n = RTE_MIN(num, evq->nb_armed);
267         for (i = 0; i != n; i++) {
268                 ev = TAILQ_FIRST(&evq->armed);
269                 ev->state = TLE_SEV_DOWN;
270                 TAILQ_REMOVE(&evq->armed, ev, ql);
271                 evd[i] = ev->data;
272         }
273         evq->nb_armed -= n;
274         rte_spinlock_unlock(&evq->lock);
275         return n;
276 }
277
278
279 #ifdef __cplusplus
280 }
281 #endif
282
283 #endif /* _SEV_IMPL_H_ */