DPDK patches and discussions
 help / color / mirror / Atom feed
From: Zhigang Lu <zlu@ezchip.com>
To: <dev@dpdk.org>
Cc: Cyril Chemparathy <cchemparathy@ezchip.com>
Subject: [dpdk-dev] [PATCH 12/15] eal/tile: add mPIPE buffer stack mempool provider
Date: Mon, 8 Dec 2014 16:59:35 +0800	[thread overview]
Message-ID: <1418029178-25162-13-git-send-email-zlu@ezchip.com> (raw)
In-Reply-To: <1418029178-25162-1-git-send-email-zlu@ezchip.com>

TileGX: Modified mempool to allow for variable metadata.
Signed-off-by: Zhigang Lu <zlu@ezchip.com>
Signed-off-by: Cyril Chemparathy <cchemparathy@ezchip.com>
---
 app/test-pmd/mempool_anon.c           |   2 +-
 app/test/Makefile                     |   6 +-
 app/test/test_mempool_tile.c          | 217 ++++++++++++
 lib/Makefile                          |   5 +
 lib/librte_eal/linuxapp/eal/Makefile  |   4 +
 lib/librte_mempool_tile/Makefile      |  48 +++
 lib/librte_mempool_tile/rte_mempool.c | 381 ++++++++++++++++++++
 lib/librte_mempool_tile/rte_mempool.h | 634 ++++++++++++++++++++++++++++++++++
 8 files changed, 1295 insertions(+), 2 deletions(-)
 create mode 100644 app/test/test_mempool_tile.c
 create mode 100644 lib/librte_mempool_tile/Makefile
 create mode 100644 lib/librte_mempool_tile/rte_mempool.c
 create mode 100644 lib/librte_mempool_tile/rte_mempool.h

diff --git a/app/test-pmd/mempool_anon.c b/app/test-pmd/mempool_anon.c
index 559a625..05b4c77 100644
--- a/app/test-pmd/mempool_anon.c
+++ b/app/test-pmd/mempool_anon.c
@@ -36,7 +36,7 @@
 #include "mempool_osdep.h"
 #include <rte_errno.h>
 
-#ifdef RTE_EXEC_ENV_LINUXAPP
+#if defined(RTE_EXEC_ENV_LINUXAPP) && !defined(RTE_ARCH_TILE)
 
 #include <fcntl.h>
 #include <unistd.h>
diff --git a/app/test/Makefile b/app/test/Makefile
index 4311f96..40ad971 100644
--- a/app/test/Makefile
+++ b/app/test/Makefile
@@ -72,10 +72,14 @@ SRCS-y += test_rwlock.c
 SRCS-$(CONFIG_RTE_LIBRTE_TIMER) += test_timer.c
 SRCS-$(CONFIG_RTE_LIBRTE_TIMER) += test_timer_perf.c
 
+ifeq ($(CONFIG_RTE_ARCH),"tile")
+SRCS-y += test_mempool_tile.c
+else
 SRCS-y += test_mempool.c
 SRCS-y += test_mempool_perf.c
-
 SRCS-y += test_mbuf.c
+endif
+
 SRCS-y += test_logs.c
 
 SRCS-y += test_memcpy.c
diff --git a/app/test/test_mempool_tile.c b/app/test/test_mempool_tile.c
new file mode 100644
index 0000000..41a375d
--- /dev/null
+++ b/app/test/test_mempool_tile.c
@@ -0,0 +1,217 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of Intel Corporation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <sys/queue.h>
+
+#include <rte_common.h>
+#include <rte_log.h>
+#include <rte_debug.h>
+#include <rte_memory.h>
+#include <rte_memzone.h>
+#include <rte_launch.h>
+#include <rte_cycles.h>
+#include <rte_tailq.h>
+#include <rte_eal.h>
+#include <rte_per_lcore.h>
+#include <rte_lcore.h>
+#include <rte_atomic.h>
+#include <rte_branch_prediction.h>
+#include <rte_ring.h>
+#include <rte_mempool.h>
+#include <rte_spinlock.h>
+#include <rte_malloc.h>
+
+#include "test.h"
+
+/*
+ * Mempool
+ * =======
+ *
+ * Basic tests: done on one core with and without cache:
+ *
+ *    - Get one object, put one object
+ *    - Get two objects, put two objects
+ *    - Get all objects, test that their content is not modified and
+ *      put them back in the pool.
+ */
+
+#define MEMPOOL_ELT_SIZE 2048
+#define MEMPOOL_SIZE (8 * 1024)
+
+static struct rte_mempool *mp;
+
+
+/*
+ * save the object number in the first 4 bytes of object data. All
+ * other bytes are set to 0.
+ */
+static void
+my_obj_init(struct rte_mempool *mp, __attribute__((unused)) void *arg,
+	    void *obj, unsigned i)
+{
+	uint32_t *objnum = obj;
+
+	memset(obj, 0, mp->elt_size);
+	*objnum = i;
+}
+
+/* basic tests (done on one core) */
+static int
+test_mempool_basic(void)
+{
+	uint32_t *objnum;
+	void **objtable;
+	void *obj, *obj2;
+	char *obj_data;
+	int ret = 0;
+	unsigned i, j;
+
+	/* dump the mempool status */
+	rte_mempool_dump(stdout, mp);
+
+	printf("get an object\n");
+	if (rte_mempool_get(mp, &obj) < 0)
+		return -1;
+	rte_mempool_dump(stdout, mp);
+
+	printf("get private data\n");
+	if (rte_mempool_get_priv(mp) != (char *) mp + sizeof(*mp))
+		return -1;
+
+	printf("get physical address of an object\n");
+	if (rte_mempool_virt2phy(mp, obj) !=
+			(phys_addr_t) (mp->phys_addr +
+			(phys_addr_t) ((char *) obj - (char *) mp)))
+		return -1;
+
+	printf("put the object back\n");
+	rte_mempool_put(mp, obj);
+	rte_mempool_dump(stdout, mp);
+
+	printf("get 2 objects\n");
+	if (rte_mempool_get(mp, &obj) < 0)
+		return -1;
+	if (rte_mempool_get(mp, &obj2) < 0) {
+		rte_mempool_put(mp, obj);
+		return -1;
+	}
+	rte_mempool_dump(stdout, mp);
+
+	printf("put the objects back\n");
+	rte_mempool_put(mp, obj);
+	rte_mempool_put(mp, obj2);
+	rte_mempool_dump(stdout, mp);
+
+	/*
+	 * get many objects: we cannot get them all because the cache
+	 * on other cores may not be empty.
+	 */
+	objtable = malloc(MEMPOOL_SIZE * sizeof(void *));
+	if (objtable == NULL)
+		return -1;
+
+	for (i = 0; i < MEMPOOL_SIZE; i++) {
+		if (rte_mempool_get(mp, &objtable[i]) < 0)
+			break;
+	}
+
+	printf("got %d buffers\n", i);
+	rte_mempool_dump(stdout, mp);
+
+	/*
+	 * for each object, check that its content was not modified,
+	 * and put objects back in pool
+	 */
+	while (i--) {
+		obj = objtable[i];
+		obj_data = obj;
+		objnum = obj;
+		if (*objnum > MEMPOOL_SIZE) {
+			printf("bad object number %u @%p\n", *objnum, objnum);
+			ret = -1;
+			break;
+		}
+		for (j = sizeof(*objnum); j < mp->elt_size; j++) {
+			if (obj_data[j] != 0)
+				ret = -1;
+		}
+
+		rte_mempool_put(mp, objtable[i]);
+	}
+
+	free(objtable);
+	if (ret == -1)
+		printf("objects were modified!\n");
+
+	return ret;
+}
+
+static int
+test_mempool(void)
+{
+	/* create a mempool (without cache) */
+	if (mp == NULL)
+		mp = rte_mempool_create("test", MEMPOOL_SIZE,
+						MEMPOOL_ELT_SIZE, 0, 0,
+						NULL, NULL,
+						my_obj_init, NULL,
+						SOCKET_ID_ANY, 0);
+	if (mp == NULL)
+		return -1;
+
+	/* retrieve the mempool from its name */
+	if (rte_mempool_lookup("test") != mp) {
+		printf("Cannot lookup mempool from its name\n");
+		return -1;
+	}
+
+	/* basic tests without cache */
+	mp = mp;
+	if (test_mempool_basic() < 0)
+		return -1;
+
+	return 0;
+}
+
+static struct test_command mempool_cmd = {
+	.command = "mempool_autotest",
+	.callback = test_mempool,
+};
+REGISTER_TEST_COMMAND(mempool_cmd);
diff --git a/lib/Makefile b/lib/Makefile
index 0ffc982..60aa0ff 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -34,7 +34,12 @@ include $(RTE_SDK)/mk/rte.vars.mk
 DIRS-$(CONFIG_RTE_LIBRTE_EAL) += librte_eal
 DIRS-$(CONFIG_RTE_LIBRTE_MALLOC) += librte_malloc
 DIRS-$(CONFIG_RTE_LIBRTE_RING) += librte_ring
+ifeq ($(CONFIG_RTE_ARCH),"tile")
+DIRS-$(CONFIG_RTE_LIBRTE_MEMPOOL) += librte_mempool_tile
+ODIR-librte_mempool_tile = librte_mempool
+else
 DIRS-$(CONFIG_RTE_LIBRTE_MEMPOOL) += librte_mempool
+endif
 DIRS-$(CONFIG_RTE_LIBRTE_MBUF) += librte_mbuf
 DIRS-$(CONFIG_RTE_LIBRTE_TIMER) += librte_timer
 DIRS-$(CONFIG_RTE_LIBRTE_CFGFILE) += librte_cfgfile
diff --git a/lib/librte_eal/linuxapp/eal/Makefile b/lib/librte_eal/linuxapp/eal/Makefile
index 99536b6..74aa503 100644
--- a/lib/librte_eal/linuxapp/eal/Makefile
+++ b/lib/librte_eal/linuxapp/eal/Makefile
@@ -39,7 +39,11 @@ CFLAGS += -I$(SRCDIR)/include
 CFLAGS += -I$(RTE_SDK)/lib/librte_eal/common
 CFLAGS += -I$(RTE_SDK)/lib/librte_eal/common/include
 CFLAGS += -I$(RTE_SDK)/lib/librte_ring
+ifeq ($(CONFIG_RTE_ARCH),"tile")
+CFLAGS += -I$(RTE_SDK)/lib/librte_mempool_tile
+else
 CFLAGS += -I$(RTE_SDK)/lib/librte_mempool
+endif
 CFLAGS += -I$(RTE_SDK)/lib/librte_malloc
 CFLAGS += -I$(RTE_SDK)/lib/librte_ether
 CFLAGS += -I$(RTE_SDK)/lib/librte_ivshmem
diff --git a/lib/librte_mempool_tile/Makefile b/lib/librte_mempool_tile/Makefile
new file mode 100644
index 0000000..65e8fa0
--- /dev/null
+++ b/lib/librte_mempool_tile/Makefile
@@ -0,0 +1,48 @@
+#   BSD LICENSE
+#
+#   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
+#   All rights reserved.
+#
+#   Redistribution and use in source and binary forms, with or without
+#   modification, are permitted provided that the following conditions
+#   are met:
+#
+#     * Redistributions of source code must retain the above copyright
+#       notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above copyright
+#       notice, this list of conditions and the following disclaimer in
+#       the documentation and/or other materials provided with the
+#       distribution.
+#     * Neither the name of Intel Corporation nor the names of its
+#       contributors may be used to endorse or promote products derived
+#       from this software without specific prior written permission.
+#
+#   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+#   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+#   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+#   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+#   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+#   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+#   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+#   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+#   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+#   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+#   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+include $(RTE_SDK)/mk/rte.vars.mk
+
+# library name
+LIB = librte_mempool.a
+
+CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) -O3
+CFLAGS += -I$(RTE_SDK)/lib/librte_mbuf
+
+# all source are stored in SRCS-y
+SRCS-$(CONFIG_RTE_LIBRTE_MEMPOOL) +=  rte_mempool.c
+# install includes
+SYMLINK-$(CONFIG_RTE_LIBRTE_MEMPOOL)-include := rte_mempool.h
+
+# this lib needs eal
+DEPDIRS-$(CONFIG_RTE_LIBRTE_MEMPOOL) += lib/librte_eal
+
+include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/lib/librte_mempool_tile/rte_mempool.c b/lib/librte_mempool_tile/rte_mempool.c
new file mode 100644
index 0000000..96ecaac
--- /dev/null
+++ b/lib/librte_mempool_tile/rte_mempool.c
@@ -0,0 +1,381 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of Intel Corporation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <inttypes.h>
+#include <errno.h>
+#include <sys/queue.h>
+
+#include <rte_common.h>
+#include <rte_log.h>
+#include <rte_debug.h>
+#include <rte_memory.h>
+#include <rte_memzone.h>
+#include <rte_malloc.h>
+#include <rte_atomic.h>
+#include <rte_launch.h>
+#include <rte_tailq.h>
+#include <rte_eal.h>
+#include <rte_mbuf.h>
+#include <rte_eal_memconfig.h>
+#include <rte_per_lcore.h>
+#include <rte_lcore.h>
+#include <rte_branch_prediction.h>
+#include <rte_ring.h>
+#include <rte_errno.h>
+#include <rte_string_fns.h>
+#include <rte_spinlock.h>
+
+#include "rte_mempool.h"
+
+/*
+ * The mPIPE buffer stack requires 128 byte aligned buffers, and restricts
+ * available headroom to a max of 127 bytes.  As a result of these
+ * restrictions, we keep the buffer metadata (mbuf, ofpbuf, etc.) outside the
+ * "mPIPE buffer", with some careful alignment jugglery and probing.
+ *
+ * The layout of each element in the mPIPE mempool is therefore as follows:
+ *
+ *   +--------------------------------+
+ *   | variable sized pad space       |
+ *   +--------------------------------+ cacheline boundary
+ *   | struct rte_mempool_obj_header  |
+ *   +--------------------------------+ cacheline boundary
+ *   | struct rte_mbuf/ofpbuf/...     |
+ *   +--------------------------------+ 128 byte aligned boundary
+ *   | buffer data headroom           |
+ *   |                                |
+ *   | buffer data                    |
+ *   |                                |
+ *   +--------------------------------+
+ *
+ * The addresses pushed into the mPIPE buffer stack are the 128 byte aligned
+ * start address of the buffer headroom.  The mempool user transacts in
+ * objects that point to the start of the rte_mbuf/ofpbuf structures in the
+ * element.  These objects cannot directly be pushed into the mPIPE buffer
+ * stack.
+ */
+
+#define BSM_MEM_ALIGN		65536
+#define BSM_MAX_META		(4 * RTE_CACHE_LINE_SIZE)
+
+TAILQ_HEAD(rte_mempool_list, rte_tailq_entry);
+
+const struct rte_mempool *last_mp;
+
+/* register buffer memory with mPIPE. */
+static int
+__bsm_register_mem(struct rte_mempool *mp, void *mem, size_t size)
+{
+	uintptr_t pagesz = mp->mz->hugepage_sz;
+	uintptr_t start = (uintptr_t)mem & ~(pagesz - 1);
+	uintptr_t end = (uintptr_t)mem + size;
+	int rc, count = 0;
+
+	while (start < end) {
+		rc = gxio_mpipe_register_page(mp->context, mp->stack_idx,
+					      (void *)start, pagesz, 0);
+		if (rc < 0)
+			return rc;
+		start += pagesz;
+		count++;
+	}
+	return count;
+}
+
+/* Probe the element constructor to figure out the metadata size. */
+static unsigned
+__bsm_meta_size(unsigned elt_size, rte_mempool_obj_ctor_t *obj_init,
+		void *obj_init_arg)
+{
+	struct rte_mempool mp;
+	unsigned offset;
+	union {
+		struct rte_mbuf mbuf;
+		unsigned char data[elt_size];
+	} u;
+
+	if (!obj_init) {
+		RTE_LOG(ERR, MEMPOOL, "No constructor to probe meta size!\n");
+		return 0;
+	}
+
+	memset(&u, 0, sizeof(u));
+	memset(&mp, 0, sizeof(mp));
+
+	mp.elt_size = elt_size;
+
+	obj_init(&mp, obj_init_arg, &u.mbuf, 0);
+
+	offset = (uintptr_t)u.mbuf.buf_addr - (uintptr_t)&u.mbuf;
+	if (offset > BSM_MAX_META) {
+		RTE_LOG(ERR, MEMPOOL, "Meta data overflow (%d > %d)!\n",
+			offset, BSM_MAX_META);
+		return 0;
+	}
+
+	RTE_LOG(ERR, MEMPOOL, "Meta data probed to be %d\n",
+		offset);
+
+	return offset;
+}
+
+/* create the mempool */
+struct rte_mempool *
+rte_mempool_create(const char *name, unsigned n, unsigned elt_size,
+		   unsigned cache_size __rte_unused, unsigned private_data_size,
+		   rte_mempool_ctor_t *mp_init, void *mp_init_arg,
+		   rte_mempool_obj_ctor_t *obj_init, void *obj_init_arg,
+		   int socket_id, unsigned flags)
+{
+	unsigned bsm_size, meta_size, pool_size, total_size, i;
+	int mz_flags = RTE_MEMZONE_1GB | RTE_MEMZONE_SIZE_HINT_ONLY;
+	gxio_mpipe_buffer_size_enum_t size_code;
+	char mz_name[RTE_MEMZONE_NAMESIZE];
+	gxio_mpipe_context_t *context;
+	const struct rte_memzone *mz;
+	int rc, instance, stack_idx;
+	struct rte_tailq_entry *te;
+	struct rte_mempool *mp;
+	void *obj, *buf;
+	char *mem;
+
+	instance = socket_id % rte_eal_mpipe_instances;
+	context = rte_eal_mpipe_context(instance);
+
+	if (!context) {
+		RTE_LOG(ERR, MEMPOOL, "No mPIPE context!\n");
+		return NULL;
+	}
+
+	/* check that we have an initialised tail queue */
+	if (RTE_TAILQ_LOOKUP_BY_IDX(RTE_TAILQ_MEMPOOL,
+			rte_mempool_list) == NULL) {
+		RTE_LOG(ERR, MEMPOOL, "Uninitialized tailq list!\n");
+		return NULL;
+	}
+
+	/* We cannot operate without hugepages. */
+	if (!rte_eal_has_hugepages()) {
+		RTE_LOG(ERR, MEMPOOL, "Mempool requires hugepages!\n");
+		return NULL;
+	}
+
+	/* try to allocate tailq entry */
+	te = rte_zmalloc("MEMPOOL_TAILQ_ENTRY", sizeof(*te), 0);
+	if (te == NULL) {
+		RTE_LOG(ERR, MEMPOOL, "Cannot allocate tailq entry!\n");
+		return NULL;
+	}
+
+	bsm_size  = gxio_mpipe_calc_buffer_stack_bytes(n);
+	bsm_size  = RTE_ALIGN_CEIL(bsm_size, BSM_ALIGN_SIZE);
+
+	pool_size = sizeof(struct rte_mempool) + private_data_size;
+	pool_size = RTE_ALIGN_CEIL(pool_size, BSM_ALIGN_SIZE);
+
+	meta_size = __bsm_meta_size(elt_size, obj_init, obj_init_arg);
+	size_code =
+	gxio_mpipe_buffer_size_to_buffer_size_enum(elt_size - meta_size);
+	elt_size  = gxio_mpipe_buffer_size_enum_to_buffer_size(size_code) +
+			meta_size;
+
+	total_size = (BSM_MEM_ALIGN + bsm_size + pool_size + n * elt_size);
+
+	snprintf(mz_name, sizeof(mz_name), RTE_MEMPOOL_MZ_FORMAT, name);
+
+	rc = gxio_mpipe_alloc_buffer_stacks(context, 1, 0, 0);
+	if (rc < 0) {
+		RTE_LOG(ERR, MEMPOOL, "Cannot allocate buffer stack!\n");
+		return NULL;
+	}
+	stack_idx = rc;
+
+	rte_rwlock_write_lock(RTE_EAL_MEMPOOL_RWLOCK);
+
+	mz = rte_memzone_reserve(mz_name, total_size, socket_id, mz_flags);
+	if (!mz) {
+		rte_rwlock_write_unlock(RTE_EAL_MEMPOOL_RWLOCK);
+		return NULL;
+	}
+
+	mem = mz->addr;
+	mp  = mz->addr;
+	memset(mp, 0, sizeof(*mp));
+	snprintf(mp->name, sizeof(mp->name), "%s", name);
+	mp->phys_addr = mz->phys_addr;
+	mp->mz = mz;
+	mp->size = n;
+	mp->flags = flags;
+	mp->meta_size = meta_size;
+	mp->elt_size = elt_size;
+	mp->private_data_size = private_data_size;
+	mp->stack_idx = stack_idx;
+	mp->size_code = size_code;
+	mp->context = context;
+	mp->instance = instance;
+
+	mem += pool_size;
+
+	mem = RTE_PTR_ALIGN_CEIL(mem, BSM_MEM_ALIGN);
+	rc = gxio_mpipe_init_buffer_stack(context, stack_idx, size_code,
+					  mem, bsm_size, 0);
+	if (rc < 0) {
+		rte_rwlock_write_unlock(RTE_EAL_MEMPOOL_RWLOCK);
+		RTE_LOG(ERR, MEMPOOL, "Cannot initialize buffer stack!\n");
+		return NULL;
+	}
+	mem += bsm_size;
+
+	mem = RTE_PTR_ALIGN_CEIL(mem, BSM_ALIGN_SIZE);
+	rc = __bsm_register_mem(mp, mem, n * elt_size);
+	if (rc < 0) {
+		rte_rwlock_write_unlock(RTE_EAL_MEMPOOL_RWLOCK);
+		RTE_LOG(ERR, MEMPOOL, "Cannot register buffer mem (%d)!\n", rc);
+		return NULL;
+	}
+
+	/* call the initializer */
+	if (mp_init)
+		mp_init(mp, mp_init_arg);
+
+	for (i = 0; i < n; i++) {
+		buf = RTE_PTR_ALIGN_CEIL(mem + meta_size, BSM_ALIGN_SIZE);
+		obj = __mempool_buf_to_obj(mp, buf);
+
+		if (obj_init)
+			obj_init(mp, obj_init_arg, obj, i);
+		rte_mempool_mp_put(mp, obj);
+		mem = RTE_PTR_ADD(obj, mp->elt_size);
+	}
+
+	te->data = (void *) mp;
+	RTE_EAL_TAILQ_INSERT_TAIL(RTE_TAILQ_MEMPOOL, rte_mempool_list, te);
+
+	rte_rwlock_write_unlock(RTE_EAL_MEMPOOL_RWLOCK);
+
+	return mp;
+}
+
+/* dump the status of the mempool on the console */
+void
+rte_mempool_dump(FILE *f, const struct rte_mempool *mp)
+{
+	fprintf(f, "mempool <%s>@%p\n", mp->name, mp);
+	fprintf(f, "  flags=%x\n", mp->flags);
+	fprintf(f, "  count=%d\n", rte_mempool_count(mp));
+}
+
+/* dump the status of all mempools on the console */
+void
+rte_mempool_list_dump(FILE *f)
+{
+	const struct rte_mempool *mp = NULL;
+	struct rte_tailq_entry *te;
+	struct rte_mempool_list *mempool_list;
+
+	mempool_list = RTE_TAILQ_LOOKUP_BY_IDX(RTE_TAILQ_MEMPOOL,
+						rte_mempool_list);
+	if (mempool_list == NULL) {
+		rte_errno = E_RTE_NO_TAILQ;
+		return;
+	}
+
+	rte_rwlock_read_lock(RTE_EAL_MEMPOOL_RWLOCK);
+
+	TAILQ_FOREACH(te, mempool_list, next) {
+		mp = (struct rte_mempool *) te->data;
+		rte_mempool_dump(f, mp);
+	}
+
+	rte_rwlock_read_unlock(RTE_EAL_MEMPOOL_RWLOCK);
+}
+
+/* search a mempool from its name */
+struct rte_mempool *
+rte_mempool_lookup(const char *name)
+{
+	struct rte_mempool *mp = NULL;
+	struct rte_tailq_entry *te;
+	struct rte_mempool_list *mempool_list;
+
+	mempool_list = RTE_TAILQ_LOOKUP_BY_IDX(RTE_TAILQ_MEMPOOL,
+						rte_mempool_list);
+	if (mempool_list == NULL) {
+		rte_errno = E_RTE_NO_TAILQ;
+		return NULL;
+	}
+
+	rte_rwlock_read_lock(RTE_EAL_MEMPOOL_RWLOCK);
+
+	TAILQ_FOREACH(te, mempool_list, next) {
+		mp = (struct rte_mempool *) te->data;
+		if (strncmp(name, mp->name, RTE_MEMPOOL_NAMESIZE) == 0)
+			break;
+	}
+
+	rte_rwlock_read_unlock(RTE_EAL_MEMPOOL_RWLOCK);
+
+	if (te == NULL) {
+		rte_errno = ENOENT;
+		return NULL;
+	}
+
+	return mp;
+}
+
+void rte_mempool_walk(void (*func)(const struct rte_mempool *, void *),
+		      void *arg)
+{
+	struct rte_tailq_entry *te = NULL;
+	struct rte_mempool_list *mempool_list;
+
+	mempool_list = RTE_TAILQ_LOOKUP_BY_IDX(RTE_TAILQ_MEMPOOL,
+						rte_mempool_list);
+	if (mempool_list == NULL) {
+		rte_errno = E_RTE_NO_TAILQ;
+		return;
+	}
+
+	rte_rwlock_read_lock(RTE_EAL_MEMPOOL_RWLOCK);
+
+	TAILQ_FOREACH(te, mempool_list, next) {
+		(*func)((struct rte_mempool *) te->data, arg);
+	}
+
+	rte_rwlock_read_unlock(RTE_EAL_MEMPOOL_RWLOCK);
+}
diff --git a/lib/librte_mempool_tile/rte_mempool.h b/lib/librte_mempool_tile/rte_mempool.h
new file mode 100644
index 0000000..ca893d5
--- /dev/null
+++ b/lib/librte_mempool_tile/rte_mempool.h
@@ -0,0 +1,634 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of Intel Corporation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _RTE_MEMPOOL_TILE_H_
+#define _RTE_MEMPOOL_TILE_H_
+
+/**
+ * @file
+ * RTE Mempool.
+ *
+ * A memory pool is an allocator of fixed-size object. It is
+ * identified by its name, and uses a ring to store free objects. It
+ * provides some other optional services, like a per-core object
+ * cache, and an alignment helper to ensure that objects are padded
+ * to spread them equally on all RAM channels, ranks, and so on.
+ *
+ * Objects owned by a mempool should never be added in another
+ * mempool. When an object is freed using rte_mempool_put() or
+ * equivalent, the object data is not modified; the user can save some
+ * meta-data in the object data and retrieve them when allocating a
+ * new object.
+ *
+ * Note: the mempool implementation is not preemptable. A lcore must
+ * not be interrupted by another task that uses the same mempool
+ * (because it uses a ring which is not preemptable). Also, mempool
+ * functions must not be used outside the DPDK environment: for
+ * example, in linuxapp environment, a thread that is not created by
+ * the EAL must not use mempools. This is due to the per-lcore cache
+ * that won't work as rte_lcore_id() will not return a correct value.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <sys/queue.h>
+
+#include <rte_log.h>
+#include <rte_debug.h>
+#include <rte_lcore.h>
+#include <rte_common.h>
+#include <rte_memory.h>
+#include <rte_prefetch.h>
+#include <rte_branch_prediction.h>
+
+#include <rte_mpipe.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define RTE_MEMPOOL_NAMESIZE	32
+#define RTE_MEMPOOL_MZ_PREFIX	"TMP_"
+#define	RTE_MEMPOOL_MZ_FORMAT	RTE_MEMPOOL_MZ_PREFIX "%s"
+#define	RTE_MEMPOOL_OBJ_NAME	RTE_MEMPOOL_MZ_FORMAT
+
+struct rte_mempool {
+	TAILQ_ENTRY(rte_mempool) next;   /**< Next in list. */
+	char         name[RTE_MEMPOOL_NAMESIZE]; /**< Name of mempool. */
+	uint32_t     flags;              /**< Flags of the mempool. */
+	uint32_t     size;               /*<< Number of elements in pool. */
+	uint32_t     elt_size;           /**< Size of an element. */
+	uint32_t     meta_size;          /**< Size of buffer metadata. */
+	int          stack_idx;          /**< mPIPE buffer stack index. */
+	int          instance;           /**< mPIPE instance. */
+	gxio_mpipe_buffer_size_enum_t size_code; /**< mPIPE buffer size enum. */
+	gxio_mpipe_context_t *context;   /**< mPIPE context. */
+	uint32_t     private_data_size;  /**< Size of private data. */
+	phys_addr_t  phys_addr;          /**< Phys. addr. of mempool struct. */
+	const struct rte_memzone *mz;    /**< Memory zone. */
+
+	char         private_data[0] __rte_cache_aligned;
+}  __rte_cache_aligned;
+
+#define MEMPOOL_F_NO_SPREAD      0x0001 /**< Do not spread in memory. */
+#define MEMPOOL_F_NO_CACHE_ALIGN 0x0002 /**< Do not align objs on cache lines.*/
+#define MEMPOOL_F_SP_PUT         0x0004 /**< Default put is "single-producer".*/
+#define MEMPOOL_F_SC_GET         0x0008 /**< Default get is "single-consumer".*/
+
+static inline void *__attribute__((always_inline))
+__mempool_buf_to_obj(const struct rte_mempool *mp, void *buf)
+{
+	return RTE_PTR_SUB(buf, mp->meta_size);
+}
+
+static inline void *__attribute__((always_inline))
+__mempool_obj_to_buf(const struct rte_mempool *mp, void *obj)
+{
+	return RTE_PTR_ADD(obj, mp->meta_size);
+}
+
+/**
+ * @internal Put several objects back in the mempool; used internally.
+ * @param mp
+ *   A pointer to the mempool structure.
+ * @param obj_table
+ *   A pointer to a table of void * pointers (objects).
+ * @param n
+ *   The number of objects to store back in the mempool, must be strictly
+ *   positive.
+ * @param is_mp
+ *   Mono-producer (0) or multi-producers (1).
+ */
+static inline void __attribute__((always_inline))
+__mempool_put_bulk(struct rte_mempool *mp, void **obj_table,
+		    unsigned n)
+{
+	unsigned i;
+	void *buf;
+
+	for (i = 0; i < n; i++) {
+		buf = __mempool_obj_to_buf(mp, obj_table[i]);
+		gxio_mpipe_push_buffer(mp->context, mp->stack_idx, buf);
+	}
+}
+
+
+/**
+ * Put several objects back in the mempool (multi-producers safe).
+ *
+ * @param mp
+ *   A pointer to the mempool structure.
+ * @param obj_table
+ *   A pointer to a table of void * pointers (objects).
+ * @param n
+ *   The number of objects to add in the mempool from the obj_table.
+ */
+static inline void __attribute__((always_inline))
+rte_mempool_mp_put_bulk(struct rte_mempool *mp, void **obj_table,
+			unsigned n)
+{
+	__mempool_put_bulk(mp, obj_table, n);
+}
+
+/**
+ * Put several objects back in the mempool (NOT multi-producers safe).
+ *
+ * @param mp
+ *   A pointer to the mempool structure.
+ * @param obj_table
+ *   A pointer to a table of void * pointers (objects).
+ * @param n
+ *   The number of objects to add in the mempool from obj_table.
+ */
+static inline void __attribute__((always_inline))
+rte_mempool_sp_put_bulk(struct rte_mempool *mp, void **obj_table,
+			unsigned n)
+{
+	__mempool_put_bulk(mp, obj_table, n);
+}
+
+/**
+ * Put several objects back in the mempool.
+ *
+ * This function calls the multi-producer or the single-producer
+ * version depending on the default behavior that was specified at
+ * mempool creation time (see flags).
+ *
+ * @param mp
+ *   A pointer to the mempool structure.
+ * @param obj_table
+ *   A pointer to a table of void * pointers (objects).
+ * @param n
+ *   The number of objects to add in the mempool from obj_table.
+ */
+static inline void __attribute__((always_inline))
+rte_mempool_put_bulk(struct rte_mempool *mp, void **obj_table,
+		     unsigned n)
+{
+	__mempool_put_bulk(mp, obj_table, n);
+}
+
+/**
+ * Put one object in the mempool (multi-producers safe).
+ *
+ * @param mp
+ *   A pointer to the mempool structure.
+ * @param obj
+ *   A pointer to the object to be added.
+ */
+static inline void __attribute__((always_inline))
+rte_mempool_mp_put(struct rte_mempool *mp, void *obj)
+{
+	rte_mempool_mp_put_bulk(mp, &obj, 1);
+}
+
+/**
+ * Put one object back in the mempool (NOT multi-producers safe).
+ *
+ * @param mp
+ *   A pointer to the mempool structure.
+ * @param obj
+ *   A pointer to the object to be added.
+ */
+static inline void __attribute__((always_inline))
+rte_mempool_sp_put(struct rte_mempool *mp, void *obj)
+{
+	rte_mempool_sp_put_bulk(mp, &obj, 1);
+}
+
+/**
+ * Put one object back in the mempool.
+ *
+ * This function calls the multi-producer or the single-producer
+ * version depending on the default behavior that was specified at
+ * mempool creation time (see flags).
+ *
+ * @param mp
+ *   A pointer to the mempool structure.
+ * @param obj
+ *   A pointer to the object to be added.
+ */
+static inline void __attribute__((always_inline))
+rte_mempool_put(struct rte_mempool *mp, void *obj)
+{
+	rte_mempool_put_bulk(mp, &obj, 1);
+}
+
+/**
+ * @internal Get several objects from the mempool; used internally.
+ * @param mp
+ *   A pointer to the mempool structure.
+ * @param obj_table
+ *   A pointer to a table of void * pointers (objects).
+ * @param n
+ *   The number of objects to get, must be strictly positive.
+ * @param is_mc
+ *   Mono-consumer (0) or multi-consumers (1).
+ * @return
+ *   - >=0: Success; number of objects supplied.
+ *   - <0: Error; code of ring dequeue function.
+ */
+static inline int __attribute__((always_inline))
+__mempool_get_bulk(struct rte_mempool *mp, void **obj_table,
+		   unsigned n)
+{
+	unsigned i;
+	void *buf;
+
+	for (i = 0; i < n; i++) {
+		buf = gxio_mpipe_pop_buffer(mp->context, mp->stack_idx);
+		if (unlikely(!buf)) {
+			__mempool_put_bulk(mp, obj_table, i);
+			return -ENOENT;
+		}
+		obj_table[i] = __mempool_buf_to_obj(mp, buf);
+		rte_prefetch0(obj_table[i]);
+	}
+	return i;
+}
+
+/**
+ * Get several objects from the mempool (multi-consumers safe).
+ *
+ * If cache is enabled, objects will be retrieved first from cache,
+ * subsequently from the common pool. Note that it can return -ENOENT when
+ * the local cache and common pool are empty, even if cache from other
+ * lcores are full.
+ *
+ * @param mp
+ *   A pointer to the mempool structure.
+ * @param obj_table
+ *   A pointer to a table of void * pointers (objects) that will be filled.
+ * @param n
+ *   The number of objects to get from mempool to obj_table.
+ * @return
+ *   - 0: Success; objects taken.
+ *   - -ENOENT: Not enough entries in the mempool; no object is retrieved.
+ */
+static inline int __attribute__((always_inline))
+rte_mempool_mc_get_bulk(struct rte_mempool *mp, void **obj_table, unsigned n)
+{
+	return __mempool_get_bulk(mp, obj_table, n);
+}
+
+/**
+ * Get several objects from the mempool (NOT multi-consumers safe).
+ *
+ * If cache is enabled, objects will be retrieved first from cache,
+ * subsequently from the common pool. Note that it can return -ENOENT when
+ * the local cache and common pool are empty, even if cache from other
+ * lcores are full.
+ *
+ * @param mp
+ *   A pointer to the mempool structure.
+ * @param obj_table
+ *   A pointer to a table of void * pointers (objects) that will be filled.
+ * @param n
+ *   The number of objects to get from the mempool to obj_table.
+ * @return
+ *   - 0: Success; objects taken.
+ *   - -ENOENT: Not enough entries in the mempool; no object is
+ *     retrieved.
+ */
+static inline int __attribute__((always_inline))
+rte_mempool_sc_get_bulk(struct rte_mempool *mp, void **obj_table, unsigned n)
+{
+	return __mempool_get_bulk(mp, obj_table, n);
+}
+
+/**
+ * Get several objects from the mempool.
+ *
+ * This function calls the multi-consumers or the single-consumer
+ * version, depending on the default behaviour that was specified at
+ * mempool creation time (see flags).
+ *
+ * If cache is enabled, objects will be retrieved first from cache,
+ * subsequently from the common pool. Note that it can return -ENOENT when
+ * the local cache and common pool are empty, even if cache from other
+ * lcores are full.
+ *
+ * @param mp
+ *   A pointer to the mempool structure.
+ * @param obj_table
+ *   A pointer to a table of void * pointers (objects) that will be filled.
+ * @param n
+ *   The number of objects to get from the mempool to obj_table.
+ * @return
+ *   - 0: Success; objects taken
+ *   - -ENOENT: Not enough entries in the mempool; no object is retrieved.
+ */
+static inline int __attribute__((always_inline))
+rte_mempool_get_bulk(struct rte_mempool *mp, void **obj_table, unsigned n)
+{
+	return __mempool_get_bulk(mp, obj_table, n);
+}
+
+/**
+ * Get one object from the mempool (multi-consumers safe).
+ *
+ * If cache is enabled, objects will be retrieved first from cache,
+ * subsequently from the common pool. Note that it can return -ENOENT when
+ * the local cache and common pool are empty, even if cache from other
+ * lcores are full.
+ *
+ * @param mp
+ *   A pointer to the mempool structure.
+ * @param obj_p
+ *   A pointer to a void * pointer (object) that will be filled.
+ * @return
+ *   - 0: Success; objects taken.
+ *   - -ENOENT: Not enough entries in the mempool; no object is retrieved.
+ */
+static inline int __attribute__((always_inline))
+rte_mempool_mc_get(struct rte_mempool *mp, void **obj_p)
+{
+	return rte_mempool_mc_get_bulk(mp, obj_p, 1);
+}
+
+/**
+ * Get one object from the mempool (NOT multi-consumers safe).
+ *
+ * If cache is enabled, objects will be retrieved first from cache,
+ * subsequently from the common pool. Note that it can return -ENOENT when
+ * the local cache and common pool are empty, even if cache from other
+ * lcores are full.
+ *
+ * @param mp
+ *   A pointer to the mempool structure.
+ * @param obj_p
+ *   A pointer to a void * pointer (object) that will be filled.
+ * @return
+ *   - 0: Success; objects taken.
+ *   - -ENOENT: Not enough entries in the mempool; no object is retrieved.
+ */
+static inline int __attribute__((always_inline))
+rte_mempool_sc_get(struct rte_mempool *mp, void **obj_p)
+{
+	return rte_mempool_sc_get_bulk(mp, obj_p, 1);
+}
+
+/**
+ * Get one object from the mempool.
+ *
+ * This function calls the multi-consumers or the single-consumer
+ * version, depending on the default behavior that was specified at
+ * mempool creation (see flags).
+ *
+ * If cache is enabled, objects will be retrieved first from cache,
+ * subsequently from the common pool. Note that it can return -ENOENT when
+ * the local cache and common pool are empty, even if cache from other
+ * lcores are full.
+ *
+ * @param mp
+ *   A pointer to the mempool structure.
+ * @param obj_p
+ *   A pointer to a void * pointer (object) that will be filled.
+ * @return
+ *   - 0: Success; objects taken.
+ *   - -ENOENT: Not enough entries in the mempool; no object is retrieved.
+ */
+static inline int __attribute__((always_inline))
+rte_mempool_get(struct rte_mempool *mp, void **obj_p)
+{
+	return rte_mempool_get_bulk(mp, obj_p, 1);
+}
+
+/**
+ * An object constructor callback function for mempool.
+ *
+ * Arguments are the mempool, the opaque pointer given by the user in
+ * rte_mempool_create(), the pointer to the element and the index of
+ * the element in the pool.
+ */
+typedef void (rte_mempool_obj_ctor_t)(struct rte_mempool *, void *,
+				      void *, unsigned);
+
+/**
+ * A mempool constructor callback function.
+ *
+ * Arguments are the mempool and the opaque pointer given by the user in
+ * rte_mempool_create().
+ */
+typedef void (rte_mempool_ctor_t)(struct rte_mempool *, void *);
+
+/**
+ * Creates a new mempool named *name* in memory.
+ *
+ * This function uses ``memzone_reserve()`` to allocate memory. The
+ * pool contains n elements of elt_size. Its size is set to n.
+ * All elements of the mempool are allocated together with the mempool header,
+ * in one physically continuous chunk of memory.
+ *
+ * @param name
+ *   The name of the mempool.
+ * @param n
+ *   The number of elements in the mempool. The optimum size (in terms of
+ *   memory usage) for a mempool is when n is a power of two minus one:
+ *   n = (2^q - 1).
+ * @param elt_size
+ *   The size of each element.
+ * @param cache_size
+ *   If cache_size is non-zero, the rte_mempool library will try to
+ *   limit the accesses to the common lockless pool, by maintaining a
+ *   per-lcore object cache. This argument must be lower or equal to
+ *   CONFIG_RTE_MEMPOOL_CACHE_MAX_SIZE. It is advised to choose
+ *   cache_size to have "n modulo cache_size == 0": if this is
+ *   not the case, some elements will always stay in the pool and will
+ *   never be used. The access to the per-lcore table is of course
+ *   faster than the multi-producer/consumer pool. The cache can be
+ *   disabled if the cache_size argument is set to 0; it can be useful to
+ *   avoid losing objects in cache. Note that even if not used, the
+ *   memory space for cache is always reserved in a mempool structure,
+ *   except if CONFIG_RTE_MEMPOOL_CACHE_MAX_SIZE is set to 0.
+ * @param private_data_size
+ *   The size of the private data appended after the mempool
+ *   structure. This is useful for storing some private data after the
+ *   mempool structure, as is done for rte_mbuf_pool for example.
+ * @param mp_init
+ *   A function pointer that is called for initialization of the pool,
+ *   before object initialization. The user can initialize the private
+ *   data in this function if needed. This parameter can be NULL if
+ *   not needed.
+ * @param mp_init_arg
+ *   An opaque pointer to data that can be used in the mempool
+ *   constructor function.
+ * @param obj_init
+ *   A function pointer that is called for each object at
+ *   initialization of the pool. The user can set some meta data in
+ *   objects if needed. This parameter can be NULL if not needed.
+ *   The obj_init() function takes the mempool pointer, the init_arg,
+ *   the object pointer and the object number as parameters.
+ * @param obj_init_arg
+ *   An opaque pointer to data that can be used as an argument for
+ *   each call to the object constructor function.
+ * @param socket_id
+ *   The *socket_id* argument is the socket identifier in the case of
+ *   NUMA. The value can be *SOCKET_ID_ANY* if there is no NUMA
+ *   constraint for the reserved zone.
+ * @param flags
+ *   The *flags* arguments is an OR of following flags:
+ *   - MEMPOOL_F_NO_SPREAD: By default, objects addresses are spread
+ *     between channels in RAM: the pool allocator will add padding
+ *     between objects depending on the hardware configuration. See
+ *     Memory alignment constraints for details. If this flag is set,
+ *     the allocator will just align them to a cache line.
+ *   - MEMPOOL_F_NO_CACHE_ALIGN: By default, the returned objects are
+ *     cache-aligned. This flag removes this constraint, and no
+ *     padding will be present between objects. This flag implies
+ *     MEMPOOL_F_NO_SPREAD.
+ *   - MEMPOOL_F_SP_PUT: If this flag is set, the default behavior
+ *     when using rte_mempool_put() or rte_mempool_put_bulk() is
+ *     "single-producer". Otherwise, it is "multi-producers".
+ *   - MEMPOOL_F_SC_GET: If this flag is set, the default behavior
+ *     when using rte_mempool_get() or rte_mempool_get_bulk() is
+ *     "single-consumer". Otherwise, it is "multi-consumers".
+ * @return
+ *   The pointer to the new allocated mempool, on success. NULL on error
+ *   with rte_errno set appropriately. Possible rte_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
+ *    - E_RTE_NO_TAILQ - no tailq list could be got for the ring or mempool list
+ *    - EINVAL - cache size provided is too large
+ *    - 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_mempool *
+rte_mempool_create(const char *name, unsigned n, unsigned elt_size,
+		   unsigned cache_size, unsigned private_data_size,
+		   rte_mempool_ctor_t *mp_init, void *mp_init_arg,
+		   rte_mempool_obj_ctor_t *obj_init, void *obj_init_arg,
+		   int socket_id, unsigned flags);
+
+/**
+ * Search a mempool from its name
+ *
+ * @param name
+ *   The name of the mempool.
+ * @return
+ *   The pointer to the mempool matching the name, or NULL if not found.
+ *   NULL on error
+ *   with rte_errno set appropriately. Possible rte_errno values include:
+ *    - ENOENT - required entry not available to return.
+ *
+ */
+struct rte_mempool *rte_mempool_lookup(const char *name);
+
+/**
+ * Dump the status of the mempool to the console.
+ *
+ * @param f
+ *   A pointer to a file for output
+ * @param mp
+ *   A pointer to the mempool structure.
+ */
+void rte_mempool_dump(FILE *f, const struct rte_mempool *mp);
+
+/**
+ * Dump the status of all mempools on the console
+ *
+ * @param f
+ *   A pointer to a file for output
+ */
+void rte_mempool_list_dump(FILE *f);
+
+/**
+ * Walk list of all memory pools
+ *
+ * @param func
+ *   Iterator function
+ * @param arg
+ *   Argument passed to iterator
+ */
+void rte_mempool_walk(void (*func)(const struct rte_mempool *, void *arg),
+		      void *arg);
+
+
+/**
+ * Return the physical address of elt, which is an element of the pool mp.
+ *
+ * @param mp
+ *   A pointer to the mempool structure.
+ * @param elt
+ *   A pointer (virtual address) to the element of the pool.
+ * @return
+ *   The physical address of the elt element.
+ */
+static inline phys_addr_t __attribute__((always_inline))
+rte_mempool_virt2phy(const struct rte_mempool *mp, const void *elt)
+{
+	uintptr_t off = (const char *)elt - (const char *)mp;
+
+	return mp->phys_addr + off;
+}
+
+/**
+ * Return a pointer to the private data in an mempool structure.
+ *
+ * @param mp
+ *   A pointer to the mempool structure.
+ * @return
+ *   A pointer to the private data.
+ */
+static inline void *rte_mempool_get_priv(struct rte_mempool *mp)
+{
+	return mp->private_data;
+}
+
+/**
+ * Return the number of entries in the mempool.
+ *
+ * When cache is enabled, this function has to browse the length of
+ * all lcores, so it should not be used in a data path, but only for
+ * debug purposes.
+ *
+ * @param mp
+ *   A pointer to the mempool structure.
+ * @return
+ *   The number of entries in the mempool.
+ */
+static inline unsigned
+rte_mempool_count(const struct rte_mempool *mp)
+{
+	return gxio_mpipe_get_buffer_count(mp->context, mp->stack_idx);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RTE_MEMPOOL_TILE_H_ */
-- 
2.1.2

  parent reply	other threads:[~2014-12-08  9:04 UTC|newest]

Thread overview: 32+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-12-08  8:59 [dpdk-dev] [PATCH 00/15] Patches for DPDK to support tile architecture Zhigang Lu
2014-12-08  8:59 ` [dpdk-dev] [PATCH 01/15] mk: introduce Tilera Tile architecture Zhigang Lu
2014-12-08 11:09   ` Bruce Richardson
2014-12-08 14:25     ` Neil Horman
2014-12-08 21:34       ` Cyril Chemparathy
2014-12-08  8:59 ` [dpdk-dev] [PATCH 02/15] eal/tile: add atomic operations for TileGx Zhigang Lu
2014-12-08 14:28   ` Neil Horman
2014-12-08 21:29     ` Cyril Chemparathy
2014-12-08  8:59 ` [dpdk-dev] [PATCH 03/15] eal/tile: add byte order " Zhigang Lu
2014-12-08  8:59 ` [dpdk-dev] [PATCH 04/15] eal/tile: add spinlock " Zhigang Lu
2014-12-08  8:59 ` [dpdk-dev] [PATCH 05/15] eal/tile: add prefetch " Zhigang Lu
2014-12-08  8:59 ` [dpdk-dev] [PATCH 06/15] eal/tile: add memcpy " Zhigang Lu
2014-12-08  8:59 ` [dpdk-dev] [PATCH 07/15] eal/tile: add CPU flags " Zhigang Lu
2014-12-08  8:59 ` [dpdk-dev] [PATCH 08/15] eal/tile: add cycle " Zhigang Lu
2014-12-08  8:59 ` [dpdk-dev] [PATCH 09/15] eal: split vector operations to architecture specific Zhigang Lu
2014-12-08  8:59 ` [dpdk-dev] [PATCH 10/15] eal/tile: add vector operations for TileGx Zhigang Lu
2014-12-08  8:59 ` [dpdk-dev] [PATCH 11/15] eal/tile: add EAL support for global mPIPE initialization Zhigang Lu
2014-12-08 20:03   ` Neil Horman
2014-12-08 21:32     ` Cyril Chemparathy
2014-12-09 11:36       ` Neil Horman
2014-12-08  8:59 ` Zhigang Lu [this message]
2014-12-09 14:07   ` [dpdk-dev] [PATCH 12/15] eal/tile: add mPIPE buffer stack mempool provider Neil Horman
2014-12-12  8:30     ` Tony Lu
2014-12-12 13:03       ` Neil Horman
2014-12-08  8:59 ` [dpdk-dev] [PATCH 13/15] pmd/tile: add mPIPE poll mode driver for TileGx Zhigang Lu
2014-12-08  8:59 ` [dpdk-dev] [PATCH 14/15] app/test: turn off cpu flag checks for tile architecture Zhigang Lu
2014-12-09 15:03   ` Neil Horman
2014-12-11  4:43     ` Tony Lu
2014-12-11 13:39       ` Neil Horman
2014-12-12  8:10         ` Tony Lu
2014-12-12 13:07           ` Neil Horman
2014-12-08  8:59 ` [dpdk-dev] [PATCH 15/15] eal: allow empty set of compile time cpuflags Zhigang Lu

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1418029178-25162-13-git-send-email-zlu@ezchip.com \
    --to=zlu@ezchip.com \
    --cc=cchemparathy@ezchip.com \
    --cc=dev@dpdk.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).