new file mode 100644
@@ -0,0 +1,122 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Arm
+ */
+
+#include <sys/queue.h>
+#include <string.h>
+
+#include <rte_tailq.h>
+#include <rte_memzone.h>
+#include <rte_rwlock.h>
+#include <rte_eal_memconfig.h>
+#include "rte_queue.h"
+
+TAILQ_HEAD(rte_queue_list, rte_tailq_entry);
+
+static struct rte_tailq_elem rte_queue_tailq = {
+ .name = RTE_TAILQ_QUEUE_NAME,
+};
+EAL_REGISTER_TAILQ(rte_queue_tailq)
+
+/* create the queue */
+struct rte_queue *
+rte_queue_create(struct rte_queue_ctx *instance, const char *name,
+ unsigned int count, int socket_id, unsigned int flags)
+{
+ struct rte_queue *q = NULL;
+ struct rte_tailq_entry *te;
+ struct rte_queue_list *queue_list = NULL;
+
+ RTE_FUNC_PTR_OR_ERR_RET(*instance->ops->queue_create, NULL);
+
+ queue_list = RTE_TAILQ_CAST(rte_queue_tailq.head, rte_queue_list);
+
+ te = rte_zmalloc("QUEUE_TAILQ_ENTRY", sizeof(*te), 0);
+ if (te == NULL) {
+ RTE_LOG(ERR, RING, "Cannot reserve memory for tailq\n");
+ rte_errno = ENOMEM;
+ return NULL;
+ }
+
+ rte_rwlock_write_lock(RTE_EAL_TAILQ_RWLOCK);
+
+ if (instance->ops->queue_create(instance->device, count, socket_id,
+ flags, &q)) {
+ rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);
+ rte_free(te);
+
+ return NULL;
+ }
+
+ te->data = q;
+ TAILQ_INSERT_TAIL(queue_list, te, next);
+ rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);
+
+ return q;
+}
+
+/* free the queue */
+void
+rte_queue_free(struct rte_queue_ctx *instance, struct rte_queue *q)
+{
+ struct rte_tailq_entry *te = NULL;
+ struct rte_queue_list *queue_list = NULL;
+
+ RTE_FUNC_PTR_OR_ERR_RET(*instance->ops->queue_free, 0);
+
+ queue_list = RTE_TAILQ_CAST(rte_queue_tailq.head, rte_queue_list);
+ rte_rwlock_write_lock(RTE_EAL_TAILQ_RWLOCK);
+
+ /* find out tailq entry */
+ TAILQ_FOREACH(te, queue_list, next) {
+ if (te->data == (void *) q)
+ break;
+ }
+
+ if (te == NULL) {
+ rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);
+ return;
+ }
+
+ TAILQ_REMOVE(queue_list, te, next);
+
+ rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);
+
+ rte_free(te);
+
+ instance->ops->queue_free(instance->device, q);
+}
+
+/* enqueue to the queue */
+unsigned int
+rte_queue_enqueue_burst(struct rte_queue_ctx *instance, struct rte_queue *q,
+ void * const *obj_table, unsigned int n,
+ unsigned int *free_space)
+{
+ return instance->ops->queue_enqueue_burst(instance->device, q,
+ obj_table, n, free_space);
+}
+
+/* dequeue from the queue */
+void
+rte_queue_dequeue_burst(struct rte_queue_ctx *instance, struct rte_queue *q,
+ void * const *obj_table, unsigned int n,
+ unsigned int *available)
+{
+ return instance->ops->queue_enqueue_burst(instance->device, q,
+ obj_table, n, available);
+}
+
+/* return size of the queue */
+void
+rte_queue_get_size(struct rte_queue_ctx *instance, struct rte_queue *q)
+{
+ return instance->ops->queue_get_size(instance->device, q);
+}
+
+/* return usable size of the queue */
+void
+rte_queue_get_capacity(struct rte_queue_ctx *instance, struct rte_queue *q)
+{
+ return instance->ops->queue_get_capacity(instance->device, q);
+}
new file mode 100644
@@ -0,0 +1,200 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Arm
+ */
+
+/**
+ * @file rte_queue.h
+ * @b EXPERIMENTAL: these APIs may change without prior notice
+ *
+ * RTE Queue
+ *
+ * This provides queue APIs for passing any data from one core to another.
+ */
+
+#ifndef _RTE_QUEUE_
+#define _RTE_QUEUE_
+
+#include <stdint.h>
+
+#include <rte_common.h>
+#include <rte_memory.h>
+#include <rte_malloc.h>
+
+#define RTE_TAILQ_QUEUE_NAME "RTE_QUEUE"
+
+/**
+ * Context for queue device
+ *
+ * Queue instance for each driver to register queue operations.
+ */
+struct rte_queue_ctx {
+ void *device;
+ /**< Queue device attached */
+ const struct rte_queue_ops *ops;
+ /**< Pointer to queue ops for the device */
+};
+
+/**
+ * Handle to the implementation specific queue
+ */
+struct rte_queue {
+ RTE_STD_C11
+ union {
+ void *private_data;
+ /**< Queue implementation specific data */
+ uintptr_t queue_handle;
+ /**< Queue handle */
+ }
+};
+
+#define RTE_QUEUE_SP_ENQ 0x0001 /**< The enqueue is "single-producer". */
+#define RTE_QUEUE_SC_DEQ 0x0002 /**< The dequeue is "single-consumer". */
+#define RTE_QUEUE_NON_BLOCK 0x0004
+/**< On the same queue, producers do not block other producers,
+ * consumers do not block other consumers.
+ */
+
+/*
+ * Create a queue
+ *
+ * This function creates a queue and returns a handle to it.
+ *
+ * @param name
+ * Name to be given to the queue
+ * @param count
+ * Minimum number of elements to be stored in the queue. If this is
+ * not a power of 2, some implementations might use extra memory.
+ * @param socket_id
+ * The *socket_id* argument is the socket identifier in case of
+ * NUMA. The value can be *SOCKET_ID_ANY* if there is no NUMA
+ * constraint for the reserved zone.
+ * @param flags
+ * An OR of the following:
+ * - RTE_QUEUE_SP_ENQ: If this flag is set, only one producer will
+ * use this queue at a time. Otherwise, multiple producers use
+ * this queue simultaneously.
+ * - RTE_QUEUE_SC_DEQ: If this flag is set, only one consumer uses
+ * this queue at a time. Otherwise, multiple consumers may use this
+ * queue simultaneously.
+ * - RTE_QUEUE_NON_BLOCK: If this flag is set, underlying queue
+ * implementation should not block threads while doing queue operations.
+ *
+ * @return
+ * On success, the pointer to the new allocated queue. NULL on error with
+ * rte_errno set appropriately. Possible errno values include:
+ * - E_RTE_NO_CONFIG - function could not get pointer to rte_config structure
+ * - E_RTE_SECONDARY - function was called from a secondary process instance
+ * - ENOSPC - the maximum number of memzones has already been allocated
+ * - EEXIST - a memzone with the same name already exists
+ * - ENOMEM - no appropriate memory area found in which to create memzone
+ */
+struct rte_queue *__rte_experimental
+rte_queue_create(struct rte_queue_ctx *instance, const char *name,
+ unsigned int count, int socket_id, unsigned int flags);
+
+/**
+ * Destroy the queue.
+ *
+ * @param q
+ * Queue to free
+ */
+void __rte_experimental
+rte_queue_free(struct rte_queue_ctx *instance, struct rte_queue *q);
+
+/**
+ * Search for a queue based on its name
+ *
+ * @param name
+ * The name of the queue.
+ * @return
+ * The pointer to the queue matching the name, or NULL if not found,
+ * with rte_errno set appropriately. Possible rte_errno values include:
+ * - ENOENT - required entry not available to return.
+ */
+struct rte_queue *
+rte_queue_lookup(const char *name);
+
+/**
+ * Enqueue a set of objects onto a queue
+ *
+ * @param q
+ * pointer to queue
+ * @param obj_table
+ * pointer to an array of void * pointers (objects, events, pkts etc)
+ * @param n
+ * number of objects to add to the queue from obj_table
+ * @return
+ * Actual number of objects enqueued.
+ */
+unsigned int __rte_experimental
+rte_queue_enqueue_burst(struct rte_queue_ctx *instance, struct rte_queue *q,
+ void * const *obj_table, unsigned int n);
+
+/**
+ * Dequeue a set of objects from a queue
+ *
+ * @param q
+ * pointer to queue
+ * @param obj_table
+ * pointer to an array of void * pointers (objects, events, pkts etc)
+ * @param n
+ * number of objects to dequeue from the queue to obj_table.
+ * obj_table is assumed to have enough space.
+ * @return
+ * Actual number of objects dequeued from queue, 0 if queue is empty
+ */
+unsigned int __rte_experimental
+rte_queue_dequeue_burst(struct rte_queue_ctx *instance, struct rte_queue *q,
+ void * const *obj_table,
+ unsigned int n);
+
+/**
+ * Returns the number of entries stored in the queue
+ *
+ * @param q
+ * pointer to the queue
+ * @return
+ * the number of elements in the queue
+ */
+unsigned int __rte_experimental
+rte_queue_get_count(struct rte_queue_ctx *instance, const struct rte_queue *q);
+
+/**
+ * Returns the number of free elements in the queue
+ *
+ * @param r
+ * pointer to the queue
+ * @return
+ * the number of free slots in the queue, i.e. the number of events that
+ * can be successfully enqueued before dequeue must be called
+ */
+unsigned int __rte_experimental
+rte_queue_get_free_count(struct rte_queue_ctx *instance,
+ const struct rte_queue *q);
+
+/**
+ * Return the size of the queue.
+ *
+ * @param q
+ * A pointer to the queue structure.
+ * @return
+ * The size of the memory used by the queue.
+ * NOTE: this is not the same as the usable space in the queue. To query that
+ * use ``rte_queue_get_capacity()``.
+ */
+unsigned int __rte_experimental
+rte_queue_get_size(struct rte_queue_ctx *instance, const struct rte_queue *q);
+
+/**
+ * Return total number of elements which can be stored in the queue.
+ *
+ * @param r
+ * A pointer to the queue structure.
+ * @return
+ * The usable size of the queue.
+ */
+unsigned int __rte_experimental
+rte_queue_get_capacity(struct rte_queue_ctx *instance,
+ const struct rte_queue *q);
+
+#endif
new file mode 100644
@@ -0,0 +1,157 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Arm
+ */
+
+/**
+ * @file rte_queue_driver.h
+ * @b EXPERIMENTAL: these APIs may change without prior notice
+ *
+ * Declarations for driver functions
+ *
+ */
+
+#ifndef _RTE_QUEUE_DRIVER_H_
+#define _RTE_QUEUE_DRIVER_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+
+#include <rte_common.h>
+#include <rte_memory.h>
+#include <rte_malloc.h>
+
+/*
+ * Create a queue
+ *
+ * This function creates a queue and returns a handle to it.
+ *
+ * @param device
+ * Queue device
+ * @param count
+ * number of elements to be stored in the queue. If this is not a
+ * power of 2, some implementations might use extra memory.
+ * @param socket_id
+ * The *socket_id* argument is the socket identifier in case of
+ * NUMA. The value can be *SOCKET_ID_ANY* if there is no NUMA
+ * constraint for the reserved zone.
+ * @param flags
+ * An OR of the following:
+ * - RTE_QUEUE_SP_ENQ: If this flag is set, only one producer uses
+ * this queue at a time. Otherwise, multiple producers use this
+ * queue simultaneously.
+ * - RTE_QUEUE_SC_DEQ: If this flag is set, only one consumer uses
+ * this queue at a time. Otherwise, multiple consumers use this
+ * queue simultaneously.
+ * @return
+ * - Returns 0 if the queue is created successfully.
+ * - Returns E_RTE_NO_CONFIG - function could not get pointer to
+ * rte_config structure
+ * - Returns E_RTE_SECONDARY - function was called from a secondary
+ * process instance
+ * - Returns ENOSPC - the maximum number of memzones has already been
+ * allocated
+ * - Returns EEXIST - a memzone with the same name already exists
+ * - Returns ENOMEM - no appropriate memory area found in which to
+ * create memzone
+ */
+
+typedef int (*queue_create_t)(void *device, unsigned int count, int socket_id,
+ unsigned int flags, struct rte_queue **queue);
+
+/**
+ * De-allocate all memory used by the queue.
+ *
+ * @param q
+ * Queue to free
+ */
+typedef int (*queue_free_t)(void *device, struct rte_queue *q);
+
+/**
+ * Enqueue a set of objects onto a queue
+ *
+ * @param q
+ * pointer to queue
+ * @param obj_table
+ * pointer to an array of void * pointers (objects, events, pkts etc)
+ * @param n
+ * number of objects to add to the queue from obj_table
+ * @param free_space
+ * if non-null, is updated to indicate the amount of free slots in the
+ * queue once the enqueue has completed.
+ * @return
+ * Actual number of objects enqueued.
+ */
+typedef unsigned int
+(*queue_enqueue_burst_t)(void *device, struct rte_queue *q,
+ void * const *obj_table,
+ unsigned int n, unsigned int *free_space);
+
+/**
+ * Dequeue a set of objects from a queue
+ *
+ * @param q
+ * pointer to queue
+ * @param obj_table
+ * pointer to an array of void * pointers (objects, events, pkts etc)
+ * @param n
+ * number of objects to dequeue from the queue to obj_table.
+ * obj_table is assumed to have enough space.
+ * @param available
+ * if non-null, is updated to indicate the number of objects remaining in
+ * the queue once the dequeue has completed
+ * @return
+ * Actual number of objects dequeued from queue, 0 if queue is empty
+ */
+typedef unsigned int
+(*queue_dequeue_burst_t)(void *device, struct rte_queue *q,
+ void * const *obj_table,
+ unsigned int n, uint16_t *available);
+
+/**
+ * Return the size of the queue.
+ *
+ * @param q
+ * A pointer to the queue structure.
+ * @return
+ * The size of the data store used by the queue.
+ * NOTE: this is not the same as the usable space in the queue. To query that
+ * use ``rte_queue_get_capacity()``.
+ */
+typedef unsigned int
+(*queue_get_size_t)(void *device, const struct rte_queue *q);
+
+/**
+ * Return the number of elements which can be stored in the queue.
+ *
+ * @param r
+ * A pointer to the queue structure.
+ * @return
+ * The usable size of the queue.
+ */
+typedef unsigned int
+(*queue_get_capacity_t)(void *device, const struct rte_queue *q);
+
+/** Queue operations function pointer table */
+struct rte_queue_ops {
+ queue_create_t create;
+ /**< Queue create. */
+ queue_free_t free;
+ /**< Destroy queue. */
+ queue_enqueue_burst_t enqueue_burst;
+ /**< Enqueue objects to the queue. */
+ queue_dequeue_burst_t dequeue_burst;
+ /**< Dequeue objects from the queue. */
+ queue_get_size_t get_size;
+ /**< Get size of the memory used by the queue */
+ queue_get_capacity_t get_capacity;
+ /**< Get total number of usable slots in the queue. */
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif