get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/52245/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 52245,
    "url": "http://patches.dpdk.org/api/patches/52245/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/20190403232020.12784-2-gage.eads@intel.com/",
    "project": {
        "id": 1,
        "url": "http://patches.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": "<20190403232020.12784-2-gage.eads@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20190403232020.12784-2-gage.eads@intel.com",
    "date": "2019-04-03T23:20:13",
    "name": "[v9,1/8] stack: introduce rte stack library",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "17350f466e6f1d27be55cf875cc3b3dfdc44f526",
    "submitter": {
        "id": 586,
        "url": "http://patches.dpdk.org/api/people/586/?format=api",
        "name": "Eads, Gage",
        "email": "gage.eads@intel.com"
    },
    "delegate": null,
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/20190403232020.12784-2-gage.eads@intel.com/mbox/",
    "series": [
        {
            "id": 4103,
            "url": "http://patches.dpdk.org/api/series/4103/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=4103",
            "date": "2019-04-03T23:20:12",
            "name": "Add stack library and new mempool handler",
            "version": 9,
            "mbox": "http://patches.dpdk.org/series/4103/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/52245/comments/",
    "check": "success",
    "checks": "http://patches.dpdk.org/api/patches/52245/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 AE05B6C9B;\n\tThu,  4 Apr 2019 01:21:11 +0200 (CEST)",
            "from mga12.intel.com (mga12.intel.com [192.55.52.136])\n\tby dpdk.org (Postfix) with ESMTP id 475414F98\n\tfor <dev@dpdk.org>; Thu,  4 Apr 2019 01:21:04 +0200 (CEST)",
            "from orsmga003.jf.intel.com ([10.7.209.27])\n\tby fmsmga106.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384;\n\t03 Apr 2019 16:21:03 -0700",
            "from txasoft-yocto.an.intel.com ([10.123.72.192])\n\tby orsmga003.jf.intel.com with ESMTP; 03 Apr 2019 16:21:02 -0700"
        ],
        "X-Amp-Result": "SKIPPED(no attachment in message)",
        "X-Amp-File-Uploaded": "False",
        "X-ExtLoop1": "1",
        "X-IronPort-AV": "E=Sophos;i=\"5.60,306,1549958400\"; d=\"scan'208\";a=\"139791641\"",
        "From": "Gage Eads <gage.eads@intel.com>",
        "To": "dev@dpdk.org",
        "Cc": "olivier.matz@6wind.com, arybchenko@solarflare.com,\n\tbruce.richardson@intel.com, konstantin.ananyev@intel.com,\n\tgavin.hu@arm.com, \n\tHonnappa.Nagarahalli@arm.com, nd@arm.com, thomas@monjalon.net",
        "Date": "Wed,  3 Apr 2019 18:20:13 -0500",
        "Message-Id": "<20190403232020.12784-2-gage.eads@intel.com>",
        "X-Mailer": "git-send-email 2.13.6",
        "In-Reply-To": "<20190403232020.12784-1-gage.eads@intel.com>",
        "References": "<20190403205041.4651-1-gage.eads@intel.com>\n\t<20190403232020.12784-1-gage.eads@intel.com>",
        "Subject": "[dpdk-dev] [PATCH v9 1/8] stack: introduce rte stack library",
        "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": "The rte_stack library provides an API for configuration and use of a\nbounded stack of pointers. Push and pop operations are MT-safe, allowing\nconcurrent access, and the interface supports pushing and popping multiple\npointers at a time.\n\nThe library's interface is modeled after another DPDK data structure,\nrte_ring, and its lock-based implementation is derived from the stack\nmempool handler. An upcoming commit will migrate the stack mempool handler\nto rte_stack.\n\nSigned-off-by: Gage Eads <gage.eads@intel.com>\nReviewed-by: Olivier Matz <olivier.matz@6wind.com>\nReviewed-by: Honnappa Nagarahalli <honnappa.nagarahalli@arm.com>\n---\n MAINTAINERS                            |   6 +\n config/common_base                     |   5 +\n doc/api/doxy-api-index.md              |   1 +\n doc/api/doxy-api.conf.in               |   1 +\n doc/guides/prog_guide/index.rst        |   1 +\n doc/guides/prog_guide/stack_lib.rst    |  28 +++++\n doc/guides/rel_notes/release_19_05.rst |   5 +\n lib/Makefile                           |   2 +\n lib/librte_stack/Makefile              |  25 ++++\n lib/librte_stack/meson.build           |   8 ++\n lib/librte_stack/rte_stack.c           | 182 ++++++++++++++++++++++++++++\n lib/librte_stack/rte_stack.h           | 209 +++++++++++++++++++++++++++++++++\n lib/librte_stack/rte_stack_pvt.h       |  34 ++++++\n lib/librte_stack/rte_stack_std.c       |  26 ++++\n lib/librte_stack/rte_stack_std.h       | 121 +++++++++++++++++++\n lib/librte_stack/rte_stack_version.map |   9 ++\n lib/meson.build                        |   2 +-\n mk/rte.app.mk                          |   1 +\n 18 files changed, 665 insertions(+), 1 deletion(-)\n create mode 100644 doc/guides/prog_guide/stack_lib.rst\n create mode 100644 lib/librte_stack/Makefile\n create mode 100644 lib/librte_stack/meson.build\n create mode 100644 lib/librte_stack/rte_stack.c\n create mode 100644 lib/librte_stack/rte_stack.h\n create mode 100644 lib/librte_stack/rte_stack_pvt.h\n create mode 100644 lib/librte_stack/rte_stack_std.c\n create mode 100644 lib/librte_stack/rte_stack_std.h\n create mode 100644 lib/librte_stack/rte_stack_version.map",
    "diff": "diff --git a/MAINTAINERS b/MAINTAINERS\nindex 71ac8cd4b..f30fc4aa6 100644\n--- a/MAINTAINERS\n+++ b/MAINTAINERS\n@@ -426,6 +426,12 @@ F: drivers/raw/skeleton_rawdev/\n F: app/test/test_rawdev.c\n F: doc/guides/prog_guide/rawdev.rst\n \n+Stack API - EXPERIMENTAL\n+M: Gage Eads <gage.eads@intel.com>\n+M: Olivier Matz <olivier.matz@6wind.com>\n+F: lib/librte_stack/\n+F: doc/guides/prog_guide/stack_lib.rst\n+\n \n Memory Pool Drivers\n -------------------\ndiff --git a/config/common_base b/config/common_base\nindex 6292bc4af..fc8dba69d 100644\n--- a/config/common_base\n+++ b/config/common_base\n@@ -994,3 +994,8 @@ CONFIG_RTE_APP_CRYPTO_PERF=y\n # Compile the eventdev application\n #\n CONFIG_RTE_APP_EVENTDEV=y\n+\n+#\n+# Compile librte_stack\n+#\n+CONFIG_RTE_LIBRTE_STACK=y\ndiff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md\nindex aacc66bd8..de1e215dd 100644\n--- a/doc/api/doxy-api-index.md\n+++ b/doc/api/doxy-api-index.md\n@@ -125,6 +125,7 @@ The public API headers are grouped by topics:\n   [mbuf]               (@ref rte_mbuf.h),\n   [mbuf pool ops]      (@ref rte_mbuf_pool_ops.h),\n   [ring]               (@ref rte_ring.h),\n+  [stack]              (@ref rte_stack.h),\n   [tailq]              (@ref rte_tailq.h),\n   [bitmap]             (@ref rte_bitmap.h)\n \ndiff --git a/doc/api/doxy-api.conf.in b/doc/api/doxy-api.conf.in\nindex a365e669b..7722fc3e9 100644\n--- a/doc/api/doxy-api.conf.in\n+++ b/doc/api/doxy-api.conf.in\n@@ -55,6 +55,7 @@ INPUT                   = @TOPDIR@/doc/api/doxy-api-index.md \\\n                           @TOPDIR@/lib/librte_ring \\\n                           @TOPDIR@/lib/librte_sched \\\n                           @TOPDIR@/lib/librte_security \\\n+                          @TOPDIR@/lib/librte_stack \\\n                           @TOPDIR@/lib/librte_table \\\n                           @TOPDIR@/lib/librte_telemetry \\\n                           @TOPDIR@/lib/librte_timer \\\ndiff --git a/doc/guides/prog_guide/index.rst b/doc/guides/prog_guide/index.rst\nindex 6726b1e8d..f4f60862f 100644\n--- a/doc/guides/prog_guide/index.rst\n+++ b/doc/guides/prog_guide/index.rst\n@@ -55,6 +55,7 @@ Programmer's Guide\n     metrics_lib\n     bpf_lib\n     ipsec_lib\n+    stack_lib\n     source_org\n     dev_kit_build_system\n     dev_kit_root_make_help\ndiff --git a/doc/guides/prog_guide/stack_lib.rst b/doc/guides/prog_guide/stack_lib.rst\nnew file mode 100644\nindex 000000000..25a8cc38a\n--- /dev/null\n+++ b/doc/guides/prog_guide/stack_lib.rst\n@@ -0,0 +1,28 @@\n+..  SPDX-License-Identifier: BSD-3-Clause\n+    Copyright(c) 2019 Intel Corporation.\n+\n+Stack Library\n+=============\n+\n+DPDK's stack library provides an API for configuration and use of a bounded\n+stack of pointers.\n+\n+The stack library provides the following basic operations:\n+\n+*  Create a uniquely named stack of a user-specified size and using a\n+   user-specified socket.\n+\n+*  Push and pop a burst of one or more stack objects (pointers). These function\n+   are multi-threading safe.\n+\n+*  Free a previously created stack.\n+\n+*  Lookup a pointer to a stack by its name.\n+\n+*  Query a stack's current depth and number of free entries.\n+\n+Implementation\n+~~~~~~~~~~~~~~\n+\n+The stack consists of a contiguous array of pointers, a current index, and a\n+spinlock. Accesses to the stack are made multi-thread safe by the spinlock.\ndiff --git a/doc/guides/rel_notes/release_19_05.rst b/doc/guides/rel_notes/release_19_05.rst\nindex bdad1ddbe..ebfbe36e5 100644\n--- a/doc/guides/rel_notes/release_19_05.rst\n+++ b/doc/guides/rel_notes/release_19_05.rst\n@@ -121,6 +121,11 @@ New Features\n   Improved testpmd application performance on ARM platform. For ``macswap``\n   forwarding mode, NEON intrinsics were used to do swap to save CPU cycles.\n \n+* **Added Stack API.**\n+\n+  Added a new stack API for configuration and use of a bounded stack of\n+  pointers. The API provides MT-safe push and pop operations that can operate\n+  on one or more pointers per operation.\n \n Removed Items\n -------------\ndiff --git a/lib/Makefile b/lib/Makefile\nindex a358f1c19..9f90e80ad 100644\n--- a/lib/Makefile\n+++ b/lib/Makefile\n@@ -109,6 +109,8 @@ DIRS-$(CONFIG_RTE_LIBRTE_IPSEC) += librte_ipsec\n DEPDIRS-librte_ipsec := librte_eal librte_mbuf librte_cryptodev librte_security\n DIRS-$(CONFIG_RTE_LIBRTE_TELEMETRY) += librte_telemetry\n DEPDIRS-librte_telemetry := librte_eal librte_metrics librte_ethdev\n+DIRS-$(CONFIG_RTE_LIBRTE_STACK) += librte_stack\n+DEPDIRS-librte_stack := librte_eal\n \n ifeq ($(CONFIG_RTE_EXEC_ENV_LINUX),y)\n DIRS-$(CONFIG_RTE_LIBRTE_KNI) += librte_kni\ndiff --git a/lib/librte_stack/Makefile b/lib/librte_stack/Makefile\nnew file mode 100644\nindex 000000000..6db540073\n--- /dev/null\n+++ b/lib/librte_stack/Makefile\n@@ -0,0 +1,25 @@\n+# SPDX-License-Identifier: BSD-3-Clause\n+# Copyright(c) 2019 Intel Corporation\n+\n+include $(RTE_SDK)/mk/rte.vars.mk\n+\n+# library name\n+LIB = librte_stack.a\n+\n+CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) -O3\n+CFLAGS += -DALLOW_EXPERIMENTAL_API\n+LDLIBS += -lrte_eal\n+\n+EXPORT_MAP := rte_stack_version.map\n+\n+LIBABIVER := 1\n+\n+# all source are stored in SRCS-y\n+SRCS-$(CONFIG_RTE_LIBRTE_STACK) := rte_stack.c \\\n+\t\t\t\t   rte_stack_std.c\n+\n+# install includes\n+SYMLINK-$(CONFIG_RTE_LIBRTE_STACK)-include := rte_stack.h \\\n+\t\t\t\t\t      rte_stack_std.h\n+\n+include $(RTE_SDK)/mk/rte.lib.mk\ndiff --git a/lib/librte_stack/meson.build b/lib/librte_stack/meson.build\nnew file mode 100644\nindex 000000000..d2e60ce9b\n--- /dev/null\n+++ b/lib/librte_stack/meson.build\n@@ -0,0 +1,8 @@\n+# SPDX-License-Identifier: BSD-3-Clause\n+# Copyright(c) 2019 Intel Corporation\n+\n+allow_experimental_apis = true\n+\n+version = 1\n+sources = files('rte_stack.c', 'rte_stack_std.c')\n+headers = files('rte_stack.h', 'rte_stack_std.h')\ndiff --git a/lib/librte_stack/rte_stack.c b/lib/librte_stack/rte_stack.c\nnew file mode 100644\nindex 000000000..610014b6c\n--- /dev/null\n+++ b/lib/librte_stack/rte_stack.c\n@@ -0,0 +1,182 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2019 Intel Corporation\n+ */\n+\n+#include <string.h>\n+\n+#include <rte_atomic.h>\n+#include <rte_eal.h>\n+#include <rte_eal_memconfig.h>\n+#include <rte_errno.h>\n+#include <rte_malloc.h>\n+#include <rte_memzone.h>\n+#include <rte_rwlock.h>\n+#include <rte_tailq.h>\n+\n+#include \"rte_stack.h\"\n+#include \"rte_stack_pvt.h\"\n+\n+int stack_logtype;\n+\n+TAILQ_HEAD(rte_stack_list, rte_tailq_entry);\n+\n+static struct rte_tailq_elem rte_stack_tailq = {\n+\t.name = RTE_TAILQ_STACK_NAME,\n+};\n+EAL_REGISTER_TAILQ(rte_stack_tailq)\n+\n+static void\n+rte_stack_init(struct rte_stack *s)\n+{\n+\tmemset(s, 0, sizeof(*s));\n+\n+\trte_stack_std_init(s);\n+}\n+\n+static ssize_t\n+rte_stack_get_memsize(unsigned int count)\n+{\n+\treturn rte_stack_std_get_memsize(count);\n+}\n+\n+struct rte_stack *\n+rte_stack_create(const char *name, unsigned int count, int socket_id,\n+\t\t uint32_t flags)\n+{\n+\tchar mz_name[RTE_MEMZONE_NAMESIZE];\n+\tstruct rte_stack_list *stack_list;\n+\tconst struct rte_memzone *mz;\n+\tstruct rte_tailq_entry *te;\n+\tstruct rte_stack *s;\n+\tunsigned int sz;\n+\tint ret;\n+\n+\tRTE_SET_USED(flags);\n+\n+\tsz = rte_stack_get_memsize(count);\n+\n+\tret = snprintf(mz_name, sizeof(mz_name), \"%s%s\",\n+\t\t       RTE_STACK_MZ_PREFIX, name);\n+\tif (ret < 0 || ret >= (int)sizeof(mz_name)) {\n+\t\trte_errno = ENAMETOOLONG;\n+\t\treturn NULL;\n+\t}\n+\n+\tte = rte_zmalloc(\"STACK_TAILQ_ENTRY\", sizeof(*te), 0);\n+\tif (te == NULL) {\n+\t\tSTACK_LOG_ERR(\"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+\tmz = rte_memzone_reserve_aligned(mz_name, sz, socket_id,\n+\t\t\t\t\t 0, __alignof__(*s));\n+\tif (mz == NULL) {\n+\t\tSTACK_LOG_ERR(\"Cannot reserve stack memzone!\\n\");\n+\t\trte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);\n+\t\trte_free(te);\n+\t\treturn NULL;\n+\t}\n+\n+\ts = mz->addr;\n+\n+\trte_stack_init(s);\n+\n+\t/* Store the name for later lookups */\n+\tret = snprintf(s->name, sizeof(s->name), \"%s\", name);\n+\tif (ret < 0 || ret >= (int)sizeof(s->name)) {\n+\t\trte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);\n+\n+\t\trte_errno = ENAMETOOLONG;\n+\t\trte_free(te);\n+\t\trte_memzone_free(mz);\n+\t\treturn NULL;\n+\t}\n+\n+\ts->memzone = mz;\n+\ts->capacity = count;\n+\ts->flags = flags;\n+\n+\tte->data = s;\n+\n+\tstack_list = RTE_TAILQ_CAST(rte_stack_tailq.head, rte_stack_list);\n+\n+\tTAILQ_INSERT_TAIL(stack_list, te, next);\n+\n+\trte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);\n+\n+\treturn s;\n+}\n+\n+void\n+rte_stack_free(struct rte_stack *s)\n+{\n+\tstruct rte_stack_list *stack_list;\n+\tstruct rte_tailq_entry *te;\n+\n+\tif (s == NULL)\n+\t\treturn;\n+\n+\tstack_list = RTE_TAILQ_CAST(rte_stack_tailq.head, rte_stack_list);\n+\trte_rwlock_write_lock(RTE_EAL_TAILQ_RWLOCK);\n+\n+\t/* find out tailq entry */\n+\tTAILQ_FOREACH(te, stack_list, next) {\n+\t\tif (te->data == s)\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(stack_list, te, next);\n+\n+\trte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);\n+\n+\trte_free(te);\n+\n+\trte_memzone_free(s->memzone);\n+}\n+\n+struct rte_stack *\n+rte_stack_lookup(const char *name)\n+{\n+\tstruct rte_stack_list *stack_list;\n+\tstruct rte_tailq_entry *te;\n+\tstruct rte_stack *r = NULL;\n+\n+\tif (name == NULL) {\n+\t\trte_errno = EINVAL;\n+\t\treturn NULL;\n+\t}\n+\n+\tstack_list = RTE_TAILQ_CAST(rte_stack_tailq.head, rte_stack_list);\n+\n+\trte_rwlock_read_lock(RTE_EAL_TAILQ_RWLOCK);\n+\n+\tTAILQ_FOREACH(te, stack_list, next) {\n+\t\tr = (struct rte_stack *) te->data;\n+\t\tif (strncmp(name, r->name, RTE_STACK_NAMESIZE) == 0)\n+\t\t\tbreak;\n+\t}\n+\n+\trte_rwlock_read_unlock(RTE_EAL_TAILQ_RWLOCK);\n+\n+\tif (te == NULL) {\n+\t\trte_errno = ENOENT;\n+\t\treturn NULL;\n+\t}\n+\n+\treturn r;\n+}\n+\n+RTE_INIT(librte_stack_init_log)\n+{\n+\tstack_logtype = rte_log_register(\"lib.stack\");\n+\tif (stack_logtype >= 0)\n+\t\trte_log_set_level(stack_logtype, RTE_LOG_NOTICE);\n+}\ndiff --git a/lib/librte_stack/rte_stack.h b/lib/librte_stack/rte_stack.h\nnew file mode 100644\nindex 000000000..42d042715\n--- /dev/null\n+++ b/lib/librte_stack/rte_stack.h\n@@ -0,0 +1,209 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2019 Intel Corporation\n+ */\n+\n+/**\n+ * @file rte_stack.h\n+ * @b EXPERIMENTAL: this API may change without prior notice\n+ *\n+ * RTE Stack\n+ *\n+ * librte_stack provides an API for configuration and use of a bounded stack of\n+ * pointers. Push and pop operations are MT-safe, allowing concurrent access,\n+ * and the interface supports pushing and popping multiple pointers at a time.\n+ */\n+\n+#ifndef _RTE_STACK_H_\n+#define _RTE_STACK_H_\n+\n+#ifdef __cplusplus\n+extern \"C\" {\n+#endif\n+\n+#include <rte_compat.h>\n+#include <rte_debug.h>\n+#include <rte_errno.h>\n+#include <rte_memzone.h>\n+#include <rte_spinlock.h>\n+\n+#define RTE_TAILQ_STACK_NAME \"RTE_STACK\"\n+#define RTE_STACK_MZ_PREFIX \"STK_\"\n+/** The maximum length of a stack name. */\n+#define RTE_STACK_NAMESIZE (RTE_MEMZONE_NAMESIZE - \\\n+\t\t\t   sizeof(RTE_STACK_MZ_PREFIX) + 1)\n+\n+/* Structure containing the LIFO, its current length, and a lock for mutual\n+ * exclusion.\n+ */\n+struct rte_stack_std {\n+\trte_spinlock_t lock; /**< LIFO lock */\n+\tuint32_t len; /**< LIFO len */\n+\tvoid *objs[]; /**< LIFO pointer table */\n+};\n+\n+/* The RTE stack structure contains the LIFO structure itself, plus metadata\n+ * such as its name and memzone pointer.\n+ */\n+struct rte_stack {\n+\t/** Name of the stack. */\n+\tchar name[RTE_STACK_NAMESIZE] __rte_cache_aligned;\n+\t/** Memzone containing the rte_stack structure. */\n+\tconst struct rte_memzone *memzone;\n+\tuint32_t capacity; /**< Usable size of the stack. */\n+\tuint32_t flags; /**< Flags supplied at creation. */\n+\tstruct rte_stack_std stack_std; /**< LIFO structure. */\n+} __rte_cache_aligned;\n+\n+#include \"rte_stack_std.h\"\n+\n+/**\n+ * @warning\n+ * @b EXPERIMENTAL: this API may change without prior notice\n+ *\n+ * Push several objects on the stack (MT-safe).\n+ *\n+ * @param s\n+ *   A pointer to the stack structure.\n+ * @param obj_table\n+ *   A pointer to a table of void * pointers (objects).\n+ * @param n\n+ *   The number of objects to push on the stack from the obj_table.\n+ * @return\n+ *   Actual number of objects pushed (either 0 or *n*).\n+ */\n+static __rte_always_inline unsigned int __rte_experimental\n+rte_stack_push(struct rte_stack *s, void * const *obj_table, unsigned int n)\n+{\n+\tRTE_ASSERT(s != NULL);\n+\tRTE_ASSERT(obj_table != NULL);\n+\n+\treturn __rte_stack_std_push(s, obj_table, n);\n+}\n+\n+/**\n+ * @warning\n+ * @b EXPERIMENTAL: this API may change without prior notice\n+ *\n+ * Pop several objects from the stack (MT-safe).\n+ *\n+ * @param s\n+ *   A pointer to the stack structure.\n+ * @param obj_table\n+ *   A pointer to a table of void * pointers (objects).\n+ * @param n\n+ *   The number of objects to pull from the stack.\n+ * @return\n+ *   Actual number of objects popped (either 0 or *n*).\n+ */\n+static __rte_always_inline unsigned int __rte_experimental\n+rte_stack_pop(struct rte_stack *s, void **obj_table, unsigned int n)\n+{\n+\tRTE_ASSERT(s != NULL);\n+\tRTE_ASSERT(obj_table != NULL);\n+\n+\treturn __rte_stack_std_pop(s, obj_table, n);\n+}\n+\n+/**\n+ * @warning\n+ * @b EXPERIMENTAL: this API may change without prior notice\n+ *\n+ * Return the number of used entries in a stack.\n+ *\n+ * @param s\n+ *   A pointer to the stack structure.\n+ * @return\n+ *   The number of used entries in the stack.\n+ */\n+static __rte_always_inline unsigned int __rte_experimental\n+rte_stack_count(struct rte_stack *s)\n+{\n+\tRTE_ASSERT(s != NULL);\n+\n+\treturn __rte_stack_std_count(s);\n+}\n+\n+/**\n+ * @warning\n+ * @b EXPERIMENTAL: this API may change without prior notice\n+ *\n+ * Return the number of free entries in a stack.\n+ *\n+ * @param s\n+ *   A pointer to the stack structure.\n+ * @return\n+ *   The number of free entries in the stack.\n+ */\n+static __rte_always_inline unsigned int __rte_experimental\n+rte_stack_free_count(struct rte_stack *s)\n+{\n+\tRTE_ASSERT(s != NULL);\n+\n+\treturn s->capacity - rte_stack_count(s);\n+}\n+\n+/**\n+ * @warning\n+ * @b EXPERIMENTAL: this API may change without prior notice\n+ *\n+ * Create a new stack named *name* in memory.\n+ *\n+ * This function uses ``memzone_reserve()`` to allocate memory for a stack of\n+ * size *count*. The behavior of the stack is controlled by the *flags*.\n+ *\n+ * @param name\n+ *   The name of the stack.\n+ * @param count\n+ *   The size of the stack.\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+ *   Reserved for future use.\n+ * @return\n+ *   On success, the pointer to the new allocated stack. NULL on error with\n+ *    rte_errno set appropriately. Possible errno values include:\n+ *    - ENOSPC - the maximum number of memzones has already been allocated\n+ *    - EEXIST - a stack with the same name already exists\n+ *    - ENOMEM - insufficient memory to create the stack\n+ *    - ENAMETOOLONG - name size exceeds RTE_STACK_NAMESIZE\n+ */\n+struct rte_stack *__rte_experimental\n+rte_stack_create(const char *name, unsigned int count, int socket_id,\n+\t\t uint32_t flags);\n+\n+/**\n+ * @warning\n+ * @b EXPERIMENTAL: this API may change without prior notice\n+ *\n+ * Free all memory used by the stack.\n+ *\n+ * @param s\n+ *   Stack to free\n+ */\n+void __rte_experimental\n+rte_stack_free(struct rte_stack *s);\n+\n+/**\n+ * @warning\n+ * @b EXPERIMENTAL: this API may change without prior notice\n+ *\n+ * Lookup a stack by its name.\n+ *\n+ * @param name\n+ *   The name of the stack.\n+ * @return\n+ *   The pointer to the stack matching the name, or NULL if not found,\n+ *   with rte_errno set appropriately. Possible rte_errno values include:\n+ *    - ENOENT - Stack with name *name* not found.\n+ *    - EINVAL - *name* pointer is NULL.\n+ */\n+struct rte_stack * __rte_experimental\n+rte_stack_lookup(const char *name);\n+\n+#ifdef __cplusplus\n+}\n+#endif\n+\n+#endif /* _RTE_STACK_H_ */\ndiff --git a/lib/librte_stack/rte_stack_pvt.h b/lib/librte_stack/rte_stack_pvt.h\nnew file mode 100644\nindex 000000000..4a6a7bdb3\n--- /dev/null\n+++ b/lib/librte_stack/rte_stack_pvt.h\n@@ -0,0 +1,34 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2019 Intel Corporation\n+ */\n+\n+#ifndef _RTE_STACK_PVT_H_\n+#define _RTE_STACK_PVT_H_\n+\n+#ifdef __cplusplus\n+extern \"C\" {\n+#endif\n+\n+#include <rte_log.h>\n+\n+extern int stack_logtype;\n+\n+#define STACK_LOG(level, fmt, args...) \\\n+\trte_log(RTE_LOG_ ##level, stack_logtype, \"%s(): \"fmt \"\\n\", \\\n+\t\t__func__, ##args)\n+\n+#define STACK_LOG_ERR(fmt, args...) \\\n+\tSTACK_LOG(ERR, fmt, ## args)\n+\n+#define STACK_LOG_WARN(fmt, args...) \\\n+\tSTACK_LOG(WARNING, fmt, ## args)\n+\n+#define STACK_LOG_INFO(fmt, args...) \\\n+\tSTACK_LOG(INFO, fmt, ## args)\n+\n+\n+#ifdef __cplusplus\n+}\n+#endif\n+\n+#endif /* _RTE_STACK_PVT_H_ */\ndiff --git a/lib/librte_stack/rte_stack_std.c b/lib/librte_stack/rte_stack_std.c\nnew file mode 100644\nindex 000000000..0a310d7c6\n--- /dev/null\n+++ b/lib/librte_stack/rte_stack_std.c\n@@ -0,0 +1,26 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2019 Intel Corporation\n+ */\n+\n+#include \"rte_stack.h\"\n+\n+void\n+rte_stack_std_init(struct rte_stack *s)\n+{\n+\trte_spinlock_init(&s->stack_std.lock);\n+}\n+\n+ssize_t\n+rte_stack_std_get_memsize(unsigned int count)\n+{\n+\tssize_t sz = sizeof(struct rte_stack);\n+\n+\tsz += RTE_CACHE_LINE_ROUNDUP(count * sizeof(void *));\n+\n+\t/* Add padding to avoid false sharing conflicts caused by\n+\t * next-line hardware prefetchers.\n+\t */\n+\tsz += 2 * RTE_CACHE_LINE_SIZE;\n+\n+\treturn sz;\n+}\ndiff --git a/lib/librte_stack/rte_stack_std.h b/lib/librte_stack/rte_stack_std.h\nnew file mode 100644\nindex 000000000..5dc940932\n--- /dev/null\n+++ b/lib/librte_stack/rte_stack_std.h\n@@ -0,0 +1,121 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2019 Intel Corporation\n+ */\n+\n+#ifndef _RTE_STACK_STD_H_\n+#define _RTE_STACK_STD_H_\n+\n+#include <rte_branch_prediction.h>\n+\n+/**\n+ * @internal Push several objects on the stack (MT-safe).\n+ *\n+ * @param s\n+ *   A pointer to the stack structure.\n+ * @param obj_table\n+ *   A pointer to a table of void * pointers (objects).\n+ * @param n\n+ *   The number of objects to push on the stack from the obj_table.\n+ * @return\n+ *   Actual number of objects pushed (either 0 or *n*).\n+ */\n+static __rte_always_inline unsigned int __rte_experimental\n+__rte_stack_std_push(struct rte_stack *s, void * const *obj_table,\n+\t\t     unsigned int n)\n+{\n+\tstruct rte_stack_std *stack = &s->stack_std;\n+\tunsigned int index;\n+\tvoid **cache_objs;\n+\n+\trte_spinlock_lock(&stack->lock);\n+\tcache_objs = &stack->objs[stack->len];\n+\n+\t/* Is there sufficient space in the stack? */\n+\tif ((stack->len + n) > s->capacity) {\n+\t\trte_spinlock_unlock(&stack->lock);\n+\t\treturn 0;\n+\t}\n+\n+\t/* Add elements back into the cache */\n+\tfor (index = 0; index < n; ++index, obj_table++)\n+\t\tcache_objs[index] = *obj_table;\n+\n+\tstack->len += n;\n+\n+\trte_spinlock_unlock(&stack->lock);\n+\treturn n;\n+}\n+\n+/**\n+ * @internal Pop several objects from the stack (MT-safe).\n+ *\n+ * @param s\n+ *   A pointer to the stack structure.\n+ * @param obj_table\n+ *   A pointer to a table of void * pointers (objects).\n+ * @param n\n+ *   The number of objects to pull from the stack.\n+ * @return\n+ *   Actual number of objects popped (either 0 or *n*).\n+ */\n+static __rte_always_inline unsigned int __rte_experimental\n+__rte_stack_std_pop(struct rte_stack *s, void **obj_table, unsigned int n)\n+{\n+\tstruct rte_stack_std *stack = &s->stack_std;\n+\tunsigned int index, len;\n+\tvoid **cache_objs;\n+\n+\trte_spinlock_lock(&stack->lock);\n+\n+\tif (unlikely(n > stack->len)) {\n+\t\trte_spinlock_unlock(&stack->lock);\n+\t\treturn 0;\n+\t}\n+\n+\tcache_objs = stack->objs;\n+\n+\tfor (index = 0, len = stack->len - 1; index < n;\n+\t\t\t++index, len--, obj_table++)\n+\t\t*obj_table = cache_objs[len];\n+\n+\tstack->len -= n;\n+\trte_spinlock_unlock(&stack->lock);\n+\n+\treturn n;\n+}\n+\n+/**\n+ * @internal Return the number of used entries in a stack.\n+ *\n+ * @param s\n+ *   A pointer to the stack structure.\n+ * @return\n+ *   The number of used entries in the stack.\n+ */\n+static __rte_always_inline unsigned int __rte_experimental\n+__rte_stack_std_count(struct rte_stack *s)\n+{\n+\treturn (unsigned int)s->stack_std.len;\n+}\n+\n+/**\n+ * @internal Initialize a standard stack.\n+ *\n+ * @param s\n+ *   A pointer to the stack structure.\n+ */\n+void\n+rte_stack_std_init(struct rte_stack *s);\n+\n+/**\n+ * @internal Return the memory required for a standard stack.\n+ *\n+ * @param count\n+ *   The size of the stack.\n+ * @return\n+ *   The bytes to allocate for a standard stack.\n+ */\n+ssize_t\n+rte_stack_std_get_memsize(unsigned int count);\n+\n+#endif /* _RTE_STACK_STD_H_ */\ndiff --git a/lib/librte_stack/rte_stack_version.map b/lib/librte_stack/rte_stack_version.map\nnew file mode 100644\nindex 000000000..6662679c3\n--- /dev/null\n+++ b/lib/librte_stack/rte_stack_version.map\n@@ -0,0 +1,9 @@\n+EXPERIMENTAL {\n+\tglobal:\n+\n+\trte_stack_create;\n+\trte_stack_free;\n+\trte_stack_lookup;\n+\n+\tlocal: *;\n+};\ndiff --git a/lib/meson.build b/lib/meson.build\nindex c3289f885..595314d7d 100644\n--- a/lib/meson.build\n+++ b/lib/meson.build\n@@ -22,7 +22,7 @@ libraries = [\n \t'gro', 'gso', 'ip_frag', 'jobstats',\n \t'kni', 'latencystats', 'lpm', 'member',\n \t'power', 'pdump', 'rawdev',\n-\t'reorder', 'sched', 'security', 'vhost',\n+\t'reorder', 'sched', 'security', 'stack', 'vhost',\n \t#ipsec lib depends on crypto and security\n \t'ipsec',\n \t# add pkt framework libs which use other libs from above\ndiff --git a/mk/rte.app.mk b/mk/rte.app.mk\nindex 262132fc6..7e033e78c 100644\n--- a/mk/rte.app.mk\n+++ b/mk/rte.app.mk\n@@ -87,6 +87,7 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_SECURITY)       += -lrte_security\n _LDLIBS-$(CONFIG_RTE_LIBRTE_COMPRESSDEV)    += -lrte_compressdev\n _LDLIBS-$(CONFIG_RTE_LIBRTE_EVENTDEV)       += -lrte_eventdev\n _LDLIBS-$(CONFIG_RTE_LIBRTE_RAWDEV)         += -lrte_rawdev\n+_LDLIBS-$(CONFIG_RTE_LIBRTE_STACK)          += -lrte_stack\n _LDLIBS-$(CONFIG_RTE_LIBRTE_TIMER)          += -lrte_timer\n _LDLIBS-$(CONFIG_RTE_LIBRTE_MEMPOOL)        += -lrte_mempool\n _LDLIBS-$(CONFIG_RTE_DRIVER_MEMPOOL_RING)   += -lrte_mempool_ring\n",
    "prefixes": [
        "v9",
        "1/8"
    ]
}