Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/41695/?format=api
http://patchwork.dpdk.org/api/patches/41695/?format=api", "web_url": "http://patchwork.dpdk.org/project/dpdk/patch/1530115574-102162-2-git-send-email-honnappa.nagarahalli@arm.com/", "project": { "id": 1, "url": "http://patchwork.dpdk.org/api/projects/1/?format=api", "name": "DPDK", "link_name": "dpdk", "list_id": "dev.dpdk.org", "list_email": "dev@dpdk.org", "web_url": "http://core.dpdk.org", "scm_url": "git://dpdk.org/dpdk", "webscm_url": "http://git.dpdk.org/dpdk", "list_archive_url": "https://inbox.dpdk.org/dev", "list_archive_url_format": "https://inbox.dpdk.org/dev/{}", "commit_url_format": "" }, "msgid": "<1530115574-102162-2-git-send-email-honnappa.nagarahalli@arm.com>", "list_archive_url": "https://inbox.dpdk.org/dev/1530115574-102162-2-git-send-email-honnappa.nagarahalli@arm.com", "date": "2018-06-27T16:06:14", "name": "[RFC] queue: introduce queue APIs and driver framework", "commit_ref": null, "pull_url": null, "state": "rejected", "archived": true, "hash": "705a759d79ee1df29da3dd94f168047547b11422", "submitter": { "id": 1045, "url": "http://patchwork.dpdk.org/api/people/1045/?format=api", "name": "Honnappa Nagarahalli", "email": "honnappa.nagarahalli@arm.com" }, "delegate": { "id": 1, "url": "http://patchwork.dpdk.org/api/users/1/?format=api", "username": "tmonjalo", "first_name": "Thomas", "last_name": "Monjalon", "email": "thomas@monjalon.net" }, "mbox": "http://patchwork.dpdk.org/project/dpdk/patch/1530115574-102162-2-git-send-email-honnappa.nagarahalli@arm.com/mbox/", "series": [ { "id": 269, "url": "http://patchwork.dpdk.org/api/series/269/?format=api", "web_url": "http://patchwork.dpdk.org/project/dpdk/list/?series=269", "date": "2018-06-27T16:06:14", "name": "[RFC] queue: introduce queue APIs and driver framework", "version": 1, "mbox": "http://patchwork.dpdk.org/series/269/mbox/" } ], "comments": "http://patchwork.dpdk.org/api/patches/41695/comments/", "check": "warning", "checks": "http://patchwork.dpdk.org/api/patches/41695/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "<dev-bounces@dpdk.org>", "X-Original-To": "patchwork@dpdk.org", "Delivered-To": "patchwork@dpdk.org", "Received": [ "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id EF2CF1C0BE;\n\tWed, 27 Jun 2018 18:06:49 +0200 (CEST)", "from foss.arm.com (usa-sjc-mx-foss1.foss.arm.com [217.140.101.70])\n\tby dpdk.org (Postfix) with ESMTP id E91F81C0AB\n\tfor <dev@dpdk.org>; Wed, 27 Jun 2018 18:06:47 +0200 (CEST)", "from usa-sjc-imap-foss1.foss.arm.com (unknown [10.72.51.249])\n\tby usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 5B76F18A;\n\tWed, 27 Jun 2018 09:06:47 -0700 (PDT)", "from ubuntu.localdomain (u202406.usa.arm.com [10.171.18.29])\n\tby usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id\n\tEAF323F318; Wed, 27 Jun 2018 09:06:39 -0700 (PDT)" ], "From": "Honnappa Nagarahalli <honnappa.nagarahalli@arm.com>", "To": "dev@dpdk.org", "Cc": "honnappa.nagarahalli@arm.com,\n\tgavin.hu@arm.com,\n\tnd@arm.com", "Date": "Wed, 27 Jun 2018 11:06:14 -0500", "Message-Id": "<1530115574-102162-2-git-send-email-honnappa.nagarahalli@arm.com>", "X-Mailer": "git-send-email 2.7.4", "In-Reply-To": "<1530115574-102162-1-git-send-email-honnappa.nagarahalli@arm.com>", "References": "<1530115574-102162-1-git-send-email-honnappa.nagarahalli@arm.com>", "Subject": "[dpdk-dev] [RFC] queue: introduce queue APIs and driver framework", "X-BeenThere": "dev@dpdk.org", "X-Mailman-Version": "2.1.15", "Precedence": "list", "List-Id": "DPDK patches and discussions <dev.dpdk.org>", "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n\t<mailto:dev-request@dpdk.org?subject=unsubscribe>", "List-Archive": "<http://mails.dpdk.org/archives/dev/>", "List-Post": "<mailto:dev@dpdk.org>", "List-Help": "<mailto:dev-request@dpdk.org?subject=help>", "List-Subscribe": "<https://mails.dpdk.org/listinfo/dev>,\n\t<mailto:dev-request@dpdk.org?subject=subscribe>", "Errors-To": "dev-bounces@dpdk.org", "Sender": "\"dev\" <dev-bounces@dpdk.org>" }, "content": "rte_ring and rte_event_ring functions are 2 methods provided\ncurrently for core to core communication. However, these two\ndo not separate the APIs from implementation. This does not\nallow using hardware queue facilities. This change adds queue\nAPIs and driver framework.\n\nSigned-off-by: Honnappa Nagarahalli <honnappa.nagarahalli@arm.com>\nReviewed-by: Ola Liljedahl <ola.liljedahl@arm.com>\n---\n lib/librte_queue/rte_queue.c | 122 ++++++++++++++++++++++\n lib/librte_queue/rte_queue.h | 200 ++++++++++++++++++++++++++++++++++++\n lib/librte_queue/rte_queue_driver.h | 157 ++++++++++++++++++++++++++++\n 3 files changed, 479 insertions(+)\n create mode 100644 lib/librte_queue/rte_queue.c\n create mode 100644 lib/librte_queue/rte_queue.h\n create mode 100644 lib/librte_queue/rte_queue_driver.h", "diff": "diff --git a/lib/librte_queue/rte_queue.c b/lib/librte_queue/rte_queue.c\nnew file mode 100644\nindex 0000000..ddde778\n--- /dev/null\n+++ b/lib/librte_queue/rte_queue.c\n@@ -0,0 +1,122 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2018 Arm\n+ */\n+\n+#include <sys/queue.h>\n+#include <string.h>\n+\n+#include <rte_tailq.h>\n+#include <rte_memzone.h>\n+#include <rte_rwlock.h>\n+#include <rte_eal_memconfig.h>\n+#include \"rte_queue.h\"\n+\n+TAILQ_HEAD(rte_queue_list, rte_tailq_entry);\n+\n+static struct rte_tailq_elem rte_queue_tailq = {\n+\t.name = RTE_TAILQ_QUEUE_NAME,\n+};\n+EAL_REGISTER_TAILQ(rte_queue_tailq)\n+\n+/* create the queue */\n+struct rte_queue *\n+rte_queue_create(struct rte_queue_ctx *instance, const char *name,\n+\t\tunsigned int count, int socket_id, unsigned int flags)\n+{\n+\tstruct rte_queue *q = NULL;\n+\tstruct rte_tailq_entry *te;\n+\tstruct rte_queue_list *queue_list = NULL;\n+\n+\tRTE_FUNC_PTR_OR_ERR_RET(*instance->ops->queue_create, NULL);\n+\n+\tqueue_list = RTE_TAILQ_CAST(rte_queue_tailq.head, rte_queue_list);\n+\n+\tte = rte_zmalloc(\"QUEUE_TAILQ_ENTRY\", sizeof(*te), 0);\n+\tif (te == NULL) {\n+\t\tRTE_LOG(ERR, RING, \"Cannot reserve memory for tailq\\n\");\n+\t\trte_errno = ENOMEM;\n+\t\treturn NULL;\n+\t}\n+\n+\trte_rwlock_write_lock(RTE_EAL_TAILQ_RWLOCK);\n+\n+\tif (instance->ops->queue_create(instance->device, count, socket_id,\n+\t\t\t\t\tflags, &q)) {\n+\t\trte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);\n+\t\trte_free(te);\n+\n+\t\treturn NULL;\n+\t}\n+\n+\tte->data = q;\n+\tTAILQ_INSERT_TAIL(queue_list, te, next);\n+\trte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);\n+\n+\treturn q;\n+}\n+\n+/* free the queue */\n+void\n+rte_queue_free(struct rte_queue_ctx *instance, struct rte_queue *q)\n+{\n+\tstruct rte_tailq_entry *te = NULL;\n+\tstruct rte_queue_list *queue_list = NULL;\n+\n+\tRTE_FUNC_PTR_OR_ERR_RET(*instance->ops->queue_free, 0);\n+\n+\tqueue_list = RTE_TAILQ_CAST(rte_queue_tailq.head, rte_queue_list);\n+\trte_rwlock_write_lock(RTE_EAL_TAILQ_RWLOCK);\n+\n+\t/* find out tailq entry */\n+\tTAILQ_FOREACH(te, queue_list, next) {\n+\t\tif (te->data == (void *) q)\n+\t\t\tbreak;\n+\t}\n+\n+\tif (te == NULL) {\n+\t\trte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);\n+\t\treturn;\n+\t}\n+\n+\tTAILQ_REMOVE(queue_list, te, next);\n+\n+\trte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);\n+\n+\trte_free(te);\n+\n+\tinstance->ops->queue_free(instance->device, q);\n+}\n+\n+/* enqueue to the queue */\n+unsigned int\n+rte_queue_enqueue_burst(struct rte_queue_ctx *instance, struct rte_queue *q,\n+\t\tvoid * const *obj_table, unsigned int n,\n+\t\tunsigned int *free_space)\n+{\n+\treturn instance->ops->queue_enqueue_burst(instance->device, q,\n+\t\t\t\t\t\tobj_table, n, free_space);\n+}\n+\n+/* dequeue from the queue */\n+void\n+rte_queue_dequeue_burst(struct rte_queue_ctx *instance, struct rte_queue *q,\n+\t\tvoid * const *obj_table, unsigned int n,\n+\t\tunsigned int *available)\n+{\n+\treturn instance->ops->queue_enqueue_burst(instance->device, q,\n+\t\t\t\t\t\tobj_table, n, available);\n+}\n+\n+/* return size of the queue */\n+void\n+rte_queue_get_size(struct rte_queue_ctx *instance, struct rte_queue *q)\n+{\n+\treturn instance->ops->queue_get_size(instance->device, q);\n+}\n+\n+/* return usable size of the queue */\n+void\n+rte_queue_get_capacity(struct rte_queue_ctx *instance, struct rte_queue *q)\n+{\n+\treturn instance->ops->queue_get_capacity(instance->device, q);\n+}\ndiff --git a/lib/librte_queue/rte_queue.h b/lib/librte_queue/rte_queue.h\nnew file mode 100644\nindex 0000000..90dc34d\n--- /dev/null\n+++ b/lib/librte_queue/rte_queue.h\n@@ -0,0 +1,200 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2018 Arm\n+ */\n+\n+/**\n+ * @file rte_queue.h\n+ * @b EXPERIMENTAL: these APIs may change without prior notice\n+ *\n+ * RTE Queue\n+ *\n+ * This provides queue APIs for passing any data from one core to another.\n+ */\n+\n+#ifndef _RTE_QUEUE_\n+#define _RTE_QUEUE_\n+\n+#include <stdint.h>\n+\n+#include <rte_common.h>\n+#include <rte_memory.h>\n+#include <rte_malloc.h>\n+\n+#define RTE_TAILQ_QUEUE_NAME \"RTE_QUEUE\"\n+\n+/**\n+ * Context for queue device\n+ *\n+ * Queue instance for each driver to register queue operations.\n+ */\n+struct rte_queue_ctx {\n+\tvoid *device;\n+\t/**< Queue device attached */\n+\tconst struct rte_queue_ops *ops;\n+\t/**< Pointer to queue ops for the device */\n+};\n+\n+/**\n+ * Handle to the implementation specific queue\n+ */\n+struct rte_queue {\n+\tRTE_STD_C11\n+\tunion {\n+\t\tvoid *private_data;\n+\t\t/**< Queue implementation specific data */\n+\t\tuintptr_t queue_handle;\n+\t\t/**< Queue handle */\n+\t}\n+};\n+\n+#define RTE_QUEUE_SP_ENQ 0x0001 /**< The enqueue is \"single-producer\". */\n+#define RTE_QUEUE_SC_DEQ 0x0002 /**< The dequeue is \"single-consumer\". */\n+#define RTE_QUEUE_NON_BLOCK 0x0004\n+/**< On the same queue, producers do not block other producers,\n+ * consumers do not block other consumers.\n+ */\n+\n+/*\n+ * Create a queue\n+ *\n+ * This function creates a queue and returns a handle to it.\n+ *\n+ * @param name\n+ * Name to be given to the queue\n+ * @param count\n+ * Minimum number of elements to be stored in the queue. If this is\n+ * not a power of 2, some implementations might use extra memory.\n+ * @param socket_id\n+ * The *socket_id* argument is the socket identifier in case of\n+ * NUMA. The value can be *SOCKET_ID_ANY* if there is no NUMA\n+ * constraint for the reserved zone.\n+ * @param flags\n+ * An OR of the following:\n+ * - RTE_QUEUE_SP_ENQ: If this flag is set, only one producer will\n+ * use this queue at a time. Otherwise, multiple producers use\n+ * this queue simultaneously.\n+ * - RTE_QUEUE_SC_DEQ: If this flag is set, only one consumer uses\n+ * this queue at a time. Otherwise, multiple consumers may use this\n+ * queue simultaneously.\n+ * - RTE_QUEUE_NON_BLOCK: If this flag is set, underlying queue\n+ * implementation should not block threads while doing queue operations.\n+ *\n+ * @return\n+ * On success, the pointer to the new allocated queue. NULL on error with\n+ * rte_errno set appropriately. Possible errno values include:\n+ * - E_RTE_NO_CONFIG - function could not get pointer to rte_config structure\n+ * - E_RTE_SECONDARY - function was called from a secondary process instance\n+ * - ENOSPC - the maximum number of memzones has already been allocated\n+ * - EEXIST - a memzone with the same name already exists\n+ * - ENOMEM - no appropriate memory area found in which to create memzone\n+ */\n+struct rte_queue *__rte_experimental\n+rte_queue_create(struct rte_queue_ctx *instance, const char *name,\n+\t\tunsigned int count, int socket_id, unsigned int flags);\n+\n+/**\n+ * Destroy the queue.\n+ *\n+ * @param q\n+ * Queue to free\n+ */\n+void __rte_experimental\n+rte_queue_free(struct rte_queue_ctx *instance, struct rte_queue *q);\n+\n+/**\n+ * Search for a queue based on its name\n+ *\n+ * @param name\n+ * The name of the queue.\n+ * @return\n+ * The pointer to the queue matching the name, or NULL if not found,\n+ * with rte_errno set appropriately. Possible rte_errno values include:\n+ * - ENOENT - required entry not available to return.\n+ */\n+struct rte_queue *\n+rte_queue_lookup(const char *name);\n+\n+/**\n+ * Enqueue a set of objects onto a queue\n+ *\n+ * @param q\n+ * pointer to queue\n+ * @param obj_table\n+ * pointer to an array of void * pointers (objects, events, pkts etc)\n+ * @param n\n+ * number of objects to add to the queue from obj_table\n+ * @return\n+ * Actual number of objects enqueued.\n+ */\n+unsigned int __rte_experimental\n+rte_queue_enqueue_burst(struct rte_queue_ctx *instance, struct rte_queue *q,\n+\t\tvoid * const *obj_table, unsigned int n);\n+\n+/**\n+ * Dequeue a set of objects from a queue\n+ *\n+ * @param q\n+ * pointer to queue\n+ * @param obj_table\n+ * pointer to an array of void * pointers (objects, events, pkts etc)\n+ * @param n\n+ * number of objects to dequeue from the queue to obj_table.\n+ * obj_table is assumed to have enough space.\n+ * @return\n+ * Actual number of objects dequeued from queue, 0 if queue is empty\n+ */\n+unsigned int __rte_experimental\n+rte_queue_dequeue_burst(struct rte_queue_ctx *instance, struct rte_queue *q,\n+\t\tvoid * const *obj_table,\n+\t\tunsigned int n);\n+\n+/**\n+ * Returns the number of entries stored in the queue\n+ *\n+ * @param q\n+ * pointer to the queue\n+ * @return\n+ * the number of elements in the queue\n+ */\n+unsigned int __rte_experimental\n+rte_queue_get_count(struct rte_queue_ctx *instance, const struct rte_queue *q);\n+\n+/**\n+ * Returns the number of free elements in the queue\n+ *\n+ * @param r\n+ * pointer to the queue\n+ * @return\n+ * the number of free slots in the queue, i.e. the number of events that\n+ * can be successfully enqueued before dequeue must be called\n+ */\n+unsigned int __rte_experimental\n+rte_queue_get_free_count(struct rte_queue_ctx *instance,\n+\t\tconst struct rte_queue *q);\n+\n+/**\n+ * Return the size of the queue.\n+ *\n+ * @param q\n+ * A pointer to the queue structure.\n+ * @return\n+ * The size of the memory used by the queue.\n+ * NOTE: this is not the same as the usable space in the queue. To query that\n+ * use ``rte_queue_get_capacity()``.\n+ */\n+unsigned int __rte_experimental\n+rte_queue_get_size(struct rte_queue_ctx *instance, const struct rte_queue *q);\n+\n+/**\n+ * Return total number of elements which can be stored in the queue.\n+ *\n+ * @param r\n+ * A pointer to the queue structure.\n+ * @return\n+ * The usable size of the queue.\n+ */\n+unsigned int __rte_experimental\n+rte_queue_get_capacity(struct rte_queue_ctx *instance,\n+\t\tconst struct rte_queue *q);\n+\n+#endif\ndiff --git a/lib/librte_queue/rte_queue_driver.h b/lib/librte_queue/rte_queue_driver.h\nnew file mode 100644\nindex 0000000..742cb6c\n--- /dev/null\n+++ b/lib/librte_queue/rte_queue_driver.h\n@@ -0,0 +1,157 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2018 Arm\n+ */\n+\n+/**\n+ * @file rte_queue_driver.h\n+ * @b EXPERIMENTAL: these APIs may change without prior notice\n+ *\n+ * Declarations for driver functions\n+ *\n+ */\n+\n+#ifndef _RTE_QUEUE_DRIVER_H_\n+#define _RTE_QUEUE_DRIVER_H_\n+\n+#ifdef __cplusplus\n+extern \"C\" {\n+#endif\n+\n+#include <stdint.h>\n+\n+#include <rte_common.h>\n+#include <rte_memory.h>\n+#include <rte_malloc.h>\n+\n+/*\n+ * Create a queue\n+ *\n+ * This function creates a queue and returns a handle to it.\n+ *\n+ * @param device\n+ * Queue device\n+ * @param count\n+ * number of elements to be stored in the queue. If this is not a\n+ * power of 2, some implementations might use extra memory.\n+ * @param socket_id\n+ * The *socket_id* argument is the socket identifier in case of\n+ * NUMA. The value can be *SOCKET_ID_ANY* if there is no NUMA\n+ * constraint for the reserved zone.\n+ * @param flags\n+ * An OR of the following:\n+ * - RTE_QUEUE_SP_ENQ: If this flag is set, only one producer uses\n+ * this queue at a time. Otherwise, multiple producers use this\n+ * queue simultaneously.\n+ * - RTE_QUEUE_SC_DEQ: If this flag is set, only one consumer uses\n+ * this queue at a time. Otherwise, multiple consumers use this\n+ * queue simultaneously.\n+ * @return\n+ * - Returns 0 if the queue is created successfully.\n+ * - Returns E_RTE_NO_CONFIG - function could not get pointer to\n+ *\t\t\t\t rte_config structure\n+ * - Returns E_RTE_SECONDARY - function was called from a secondary\n+ *\t\t\t\t process instance\n+ * - Returns ENOSPC - the maximum number of memzones has already been\n+ *\t\t\t allocated\n+ * - Returns EEXIST - a memzone with the same name already exists\n+ * - Returns ENOMEM - no appropriate memory area found in which to\n+ *\t\t\t create memzone\n+ */\n+\n+typedef int (*queue_create_t)(void *device, unsigned int count, int socket_id,\n+\t\tunsigned int flags, struct rte_queue **queue);\n+\n+/**\n+ * De-allocate all memory used by the queue.\n+ *\n+ * @param q\n+ * Queue to free\n+ */\n+typedef int (*queue_free_t)(void *device, struct rte_queue *q);\n+\n+/**\n+ * Enqueue a set of objects onto a queue\n+ *\n+ * @param q\n+ * pointer to queue\n+ * @param obj_table\n+ * pointer to an array of void * pointers (objects, events, pkts etc)\n+ * @param n\n+ * number of objects to add to the queue from obj_table\n+ * @param free_space\n+ * if non-null, is updated to indicate the amount of free slots in the\n+ * queue once the enqueue has completed.\n+ * @return\n+ * Actual number of objects enqueued.\n+ */\n+typedef unsigned int\n+(*queue_enqueue_burst_t)(void *device, struct rte_queue *q,\n+\t\tvoid * const *obj_table,\n+\t\tunsigned int n, unsigned int *free_space);\n+\n+/**\n+ * Dequeue a set of objects from a queue\n+ *\n+ * @param q\n+ * pointer to queue\n+ * @param obj_table\n+ * pointer to an array of void * pointers (objects, events, pkts etc)\n+ * @param n\n+ * number of objects to dequeue from the queue to obj_table.\n+ * obj_table is assumed to have enough space.\n+ * @param available\n+ * if non-null, is updated to indicate the number of objects remaining in\n+ * the queue once the dequeue has completed\n+ * @return\n+ * Actual number of objects dequeued from queue, 0 if queue is empty\n+ */\n+typedef unsigned int\n+(*queue_dequeue_burst_t)(void *device, struct rte_queue *q,\n+\t\tvoid * const *obj_table,\n+\t\tunsigned int n, uint16_t *available);\n+\n+/**\n+ * Return the size of the queue.\n+ *\n+ * @param q\n+ * A pointer to the queue structure.\n+ * @return\n+ * The size of the data store used by the queue.\n+ * NOTE: this is not the same as the usable space in the queue. To query that\n+ * use ``rte_queue_get_capacity()``.\n+ */\n+typedef unsigned int\n+(*queue_get_size_t)(void *device, const struct rte_queue *q);\n+\n+/**\n+ * Return the number of elements which can be stored in the queue.\n+ *\n+ * @param r\n+ * A pointer to the queue structure.\n+ * @return\n+ * The usable size of the queue.\n+ */\n+typedef unsigned int\n+(*queue_get_capacity_t)(void *device, const struct rte_queue *q);\n+\n+/** Queue operations function pointer table */\n+struct rte_queue_ops {\n+\tqueue_create_t create;\n+\t/**< Queue create. */\n+\tqueue_free_t free;\n+\t/**< Destroy queue. */\n+\tqueue_enqueue_burst_t enqueue_burst;\n+\t/**< Enqueue objects to the queue. */\n+\tqueue_dequeue_burst_t dequeue_burst;\n+\t/**< Dequeue objects from the queue. */\n+\tqueue_get_size_t get_size;\n+\t/**< Get size of the memory used by the queue */\n+\tqueue_get_capacity_t get_capacity;\n+\t/**< Get total number of usable slots in the queue. */\n+};\n+\n+#ifdef __cplusplus\n+}\n+#endif\n+\n+#endif\n", "prefixes": [ "RFC" ] }{ "id": 41695, "url": "