diff options
author | Konstantin Ananyev <konstantin.ananyev@intel.com> | 2016-06-03 16:43:13 +0100 |
---|---|---|
committer | Konstantin Ananyev <konstantin.ananyev@intel.com> | 2016-06-07 14:17:17 +0100 |
commit | 3395610ea65d66fb96ab98d6915a7ffbd584c34e (patch) | |
tree | 1e4b4ad406679913ee8c490a2f9be6e3d610dbf3 /lib/libtle_udp/tle_event.h | |
parent | b0a4a8b51228d049e8472757349569a6d53c27c5 (diff) |
Initial commit of tldk code.
Change-Id: Ib96fdd2c57bae0a51ed420137c35eb8e2ee58473
Signed-off-by: Konstantin Ananyev <konstantin.ananyev@intel.com>
Signed-off-by: Ed Warnicke <eaw@cisco.com>
Diffstat (limited to 'lib/libtle_udp/tle_event.h')
-rw-r--r-- | lib/libtle_udp/tle_event.h | 257 |
1 files changed, 257 insertions, 0 deletions
diff --git a/lib/libtle_udp/tle_event.h b/lib/libtle_udp/tle_event.h new file mode 100644 index 0000000..1a5c436 --- /dev/null +++ b/lib/libtle_udp/tle_event.h @@ -0,0 +1,257 @@ +/* + * Copyright (c) 2016 Intel Corporation. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _SEV_IMPL_H_ +#define _SEV_IMPL_H_ + +#include <rte_common.h> +#include <rte_spinlock.h> +#include <rte_atomic.h> +#include <sys/queue.h> + +#ifdef __cplusplus +extern "C" { +#endif + +struct tle_evq; + +/** + * Possible states of the event. + */ +enum tle_ev_state { + TLE_SEV_IDLE, + TLE_SEV_DOWN, + TLE_SEV_UP, + TLE_SEV_NUM +}; + +struct tle_event { + TAILQ_ENTRY(tle_event) ql; + struct tle_evq *head; + const void *data; + enum tle_ev_state state; +} __rte_cache_aligned; + +struct tle_evq { + rte_spinlock_t lock; + uint32_t nb_events; + uint32_t nb_armed; + uint32_t nb_free; + TAILQ_HEAD(, tle_event) armed; + TAILQ_HEAD(, tle_event) free; + struct tle_event events[0]; +}; + +/** + * event queue creation parameters. + */ +struct tle_evq_param { + int32_t socket_id; /**< socket ID to allocate memory from. */ + uint32_t max_events; /**< max number of events in queue. */ +}; + +/** + * create event queue. + * @param prm + * Parameters used to create and initialise the queue. + * @return + * Pointer to new event queue structure, + * or NULL on error, with error code set in rte_errno. + * Possible rte_errno errors include: + * - EINVAL - invalid parameter passed to function + * - ENOMEM - out of memory + */ +struct tle_evq *tle_evq_create(const struct tle_evq_param *prm); + +/** + * Destroy given event queue. + * + * @param evq + * event queue to destroy + */ +void tle_evq_destroy(struct tle_evq *evq); + +/** + * allocate a new event within given event queue. + * @param evq + * event queue to allocate a new stream within. + * @param data + * User data to be associated with that event. + * @return + * Pointer to event structure that can be used in future tle_event API calls, + * or NULL on error, with error code set in rte_errno. + * Possible rte_errno errors include: + * - EINVAL - invalid parameter passed to function + * - ENOMEM - max limit of allocated events reached for that context + */ +struct tle_event *tle_event_alloc(struct tle_evq *evq, const void *data); + +/** + * free an allocated event. + * @param ev + * Pointer to the event to free. + */ +void tle_event_free(struct tle_event *ev); + + +/** + * move event from DOWN to UP state. + * @param ev + * Pointer to the event. + */ +static inline void +tle_event_raise(struct tle_event *ev) +{ + struct tle_evq *q; + + if (ev->state != TLE_SEV_DOWN) + return; + + q = ev->head; + rte_compiler_barrier(); + + rte_spinlock_lock(&q->lock); + if (ev->state == TLE_SEV_DOWN) { + ev->state = TLE_SEV_UP; + TAILQ_INSERT_TAIL(&q->armed, ev, ql); + q->nb_armed++; + } + rte_spinlock_unlock(&q->lock); +} + +/** + * move event from UP to DOWN state. + * @param ev + * Pointer to the event. + */ +static inline void +tle_event_down(struct tle_event *ev) +{ + struct tle_evq *q; + + if (ev->state != TLE_SEV_UP) + return; + + q = ev->head; + rte_compiler_barrier(); + + rte_spinlock_lock(&q->lock); + if (ev->state == TLE_SEV_UP) { + ev->state = TLE_SEV_DOWN; + TAILQ_REMOVE(&q->armed, ev, ql); + q->nb_armed--; + } + rte_spinlock_unlock(&q->lock); +} + +/** + * move from IDLE to DOWN/UP state. + * @param ev + * Pointer to the event. + * @param st + * new state for the event. + */ +static inline void +tle_event_active(struct tle_event *ev, enum tle_ev_state st) +{ + struct tle_evq *q; + + if (st == ev->state) + return; + + q = ev->head; + rte_compiler_barrier(); + + rte_spinlock_lock(&q->lock); + if (st > ev->state) { + if (st == TLE_SEV_UP) { + TAILQ_INSERT_TAIL(&q->armed, ev, ql); + q->nb_armed++; + } + ev->state = st; + } + rte_spinlock_unlock(&q->lock); +} + +/** + * move event IDLE state. + * @param ev + * Pointer to the event. + */ +static inline void +tle_event_idle(struct tle_event *ev) +{ + struct tle_evq *q; + + if (ev->state == TLE_SEV_IDLE) + return; + + q = ev->head; + rte_compiler_barrier(); + + rte_spinlock_lock(&q->lock); + if (ev->state == TLE_SEV_UP) { + TAILQ_REMOVE(&q->armed, ev, ql); + q->nb_armed--; + } + ev->state = TLE_SEV_IDLE; + rte_spinlock_unlock(&q->lock); +} + + +/* + * return up to *num* user data pointers associated with + * the events that were in the UP state. + * Each retrieved event is automatically moved into the DOWN state. + * @param evq + * event queue to retrieve events from. + * @param evd + * An array of user data pointers associated with the events retrieved. + * It must be large enough to store up to *num* pointers in it. + * @param num + * Number of elements in the *evd* array. + * @return + * number of of entries filled inside *evd* array. + */ +static inline int32_t +tle_evq_get(struct tle_evq *evq, const void *evd[], uint32_t num) +{ + uint32_t i, n; + struct tle_event *ev; + + if (evq->nb_armed == 0) + return 0; + + rte_compiler_barrier(); + + rte_spinlock_lock(&evq->lock); + n = RTE_MIN(num, evq->nb_armed); + for (i = 0; i != n; i++) { + ev = TAILQ_FIRST(&evq->armed); + ev->state = TLE_SEV_DOWN; + TAILQ_REMOVE(&evq->armed, ev, ql); + evd[i] = ev->data; + } + evq->nb_armed -= n; + rte_spinlock_unlock(&evq->lock); + return n; +} + + +#ifdef __cplusplus +} +#endif + +#endif /* _SEV_IMPL_H_ */ |