[dpdk-dev,3/5] mempool: add custom external mempool handler example
Commit Message
adds a simple ring-based mempool handler using mallocs for each object
Signed-off-by: David Hunt <david.hunt@intel.com>
---
lib/librte_mempool/Makefile | 1 +
lib/librte_mempool/custom_mempool.c | 160 ++++++++++++++++++++++++++++++++++++
2 files changed, 161 insertions(+)
create mode 100644 lib/librte_mempool/custom_mempool.c
Comments
On Tue, Jan 26, 2016 at 05:25:53PM +0000, David Hunt wrote:
> adds a simple ring-based mempool handler using mallocs for each object
nit,
$ git am /export/dh/3
Applying: mempool: add custom external mempool handler example
/export/dpdk-master/.git/rebase-apply/patch:184: new blank line at EOF.
+
warning: 1 line adds whitespace errors.
>
> Signed-off-by: David Hunt <david.hunt@intel.com>
> ---
> lib/librte_mempool/Makefile | 1 +
> lib/librte_mempool/custom_mempool.c | 160 ++++++++++++++++++++++++++++++++++++
> 2 files changed, 161 insertions(+)
> create mode 100644 lib/librte_mempool/custom_mempool.c
>
> diff --git a/lib/librte_mempool/Makefile b/lib/librte_mempool/Makefile
> index d795b48..4f72546 100644
> --- a/lib/librte_mempool/Makefile
> +++ b/lib/librte_mempool/Makefile
> @@ -44,6 +44,7 @@ LIBABIVER := 1
> SRCS-$(CONFIG_RTE_LIBRTE_MEMPOOL) += rte_mempool.c
> SRCS-$(CONFIG_RTE_LIBRTE_MEMPOOL) += rte_mempool_default.c
> SRCS-$(CONFIG_RTE_LIBRTE_MEMPOOL) += rte_mempool_stack.c
> +SRCS-$(CONFIG_RTE_LIBRTE_MEMPOOL) += custom_mempool.c
> ifeq ($(CONFIG_RTE_LIBRTE_XEN_DOM0),y)
> SRCS-$(CONFIG_RTE_LIBRTE_MEMPOOL) += rte_dom0_mempool.c
> endif
> diff --git a/lib/librte_mempool/custom_mempool.c b/lib/librte_mempool/custom_mempool.c
> new file mode 100644
> index 0000000..a9da8c5
> --- /dev/null
> +++ b/lib/librte_mempool/custom_mempool.c
> @@ -0,0 +1,160 @@
> +/*-
> + * BSD LICENSE
> + *
> + * Copyright(c) 2010-2016 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_mempool.h>
> +
> +#include "rte_mempool_internal.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 TIME_S 5
> +#define MEMPOOL_ELT_SIZE 2048
> +#define MAX_KEEP 128
> +#define MEMPOOL_SIZE 8192
> +
> +#if 0
> +/*
> + * For our example mempool handler, we use the following struct to
> + * pass info to our create callback so it can call rte_mempool_create
> + */
> +struct custom_mempool_alloc_params {
> + char ring_name[RTE_RING_NAMESIZE];
> + unsigned n_elt;
> + unsigned elt_size;
> +};
> +#endif
> +
> +/*
> + * Simple example of custom mempool structure. Holds pointers to all the
> + * elements which are simply malloc'd in this example.
> + */
> +struct custom_mempool {
> + struct rte_ring *r; /* Ring to manage elements */
> + void *elements[MEMPOOL_SIZE]; /* Element pointers */
> +};
> +
> +/*
> + * Loop though all the element pointers and allocate a chunk of memory, then
> + * insert that memory into the ring.
> + */
> +static void *
> +custom_mempool_alloc(struct rte_mempool *mp,
> + const char *name, unsigned n,
> + __attribute__((unused)) int socket_id,
> + __attribute__((unused)) unsigned flags)
> +
> +{
> + static struct custom_mempool *cm;
> + uint32_t *objnum;
> + unsigned int i;
> +
> + cm = malloc(sizeof(struct custom_mempool));
> +
> + /* Create the ring so we can enqueue/dequeue */
> + cm->r = rte_ring_create(name,
> + rte_align32pow2(n+1), 0, 0);
> + if (cm->r == NULL)
> + return NULL;
> +
> + /*
> + * Loop around the elements an allocate the required memory
> + * and place them in the ring.
> + * Not worried about alignment or performance for this example.
> + * Also, set the first 32-bits to be the element number so we
> + * can check later on.
> + */
> + for (i = 0; i < n; i++) {
> + cm->elements[i] = malloc(mp->elt_size);
> + memset(cm->elements[i], 0, mp->elt_size);
> + objnum = (uint32_t *)cm->elements[i];
> + *objnum = i;
> + rte_ring_sp_enqueue_bulk(cm->r, &(cm->elements[i]), 1);
> + }
> +
> + return cm;
> +}
> +
> +static int
> +custom_mempool_put(void *p, void * const *obj_table, unsigned n)
> +{
> + struct custom_mempool *cm = (struct custom_mempool *)p;
> +
> + return rte_ring_mp_enqueue_bulk(cm->r, obj_table, n);
> +}
> +
> +
> +static int
> +custom_mempool_get(void *p, void **obj_table, unsigned n)
> +{
> + struct custom_mempool *cm = (struct custom_mempool *)p;
> +
> + return rte_ring_mc_dequeue_bulk(cm->r, obj_table, n);
> +}
> +
> +static unsigned
> +custom_mempool_get_count(void *p)
> +{
> + struct custom_mempool *cm = (struct custom_mempool *)p;
> +
> + return rte_ring_count(cm->r);
> +}
> +
> +static struct rte_mempool_handler mempool_handler_custom = {
> + .name = "custom_handler",
> + .alloc = custom_mempool_alloc,
> + .put = custom_mempool_put,
> + .get = custom_mempool_get,
> + .get_count = custom_mempool_get_count,
> +};
> +
> +REGISTER_MEMPOOL_HANDLER(mempool_handler_custom);
> +
> --
> 1.9.3
>
@@ -44,6 +44,7 @@ LIBABIVER := 1
SRCS-$(CONFIG_RTE_LIBRTE_MEMPOOL) += rte_mempool.c
SRCS-$(CONFIG_RTE_LIBRTE_MEMPOOL) += rte_mempool_default.c
SRCS-$(CONFIG_RTE_LIBRTE_MEMPOOL) += rte_mempool_stack.c
+SRCS-$(CONFIG_RTE_LIBRTE_MEMPOOL) += custom_mempool.c
ifeq ($(CONFIG_RTE_LIBRTE_XEN_DOM0),y)
SRCS-$(CONFIG_RTE_LIBRTE_MEMPOOL) += rte_dom0_mempool.c
endif
new file mode 100644
@@ -0,0 +1,160 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2010-2016 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_mempool.h>
+
+#include "rte_mempool_internal.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 TIME_S 5
+#define MEMPOOL_ELT_SIZE 2048
+#define MAX_KEEP 128
+#define MEMPOOL_SIZE 8192
+
+#if 0
+/*
+ * For our example mempool handler, we use the following struct to
+ * pass info to our create callback so it can call rte_mempool_create
+ */
+struct custom_mempool_alloc_params {
+ char ring_name[RTE_RING_NAMESIZE];
+ unsigned n_elt;
+ unsigned elt_size;
+};
+#endif
+
+/*
+ * Simple example of custom mempool structure. Holds pointers to all the
+ * elements which are simply malloc'd in this example.
+ */
+struct custom_mempool {
+ struct rte_ring *r; /* Ring to manage elements */
+ void *elements[MEMPOOL_SIZE]; /* Element pointers */
+};
+
+/*
+ * Loop though all the element pointers and allocate a chunk of memory, then
+ * insert that memory into the ring.
+ */
+static void *
+custom_mempool_alloc(struct rte_mempool *mp,
+ const char *name, unsigned n,
+ __attribute__((unused)) int socket_id,
+ __attribute__((unused)) unsigned flags)
+
+{
+ static struct custom_mempool *cm;
+ uint32_t *objnum;
+ unsigned int i;
+
+ cm = malloc(sizeof(struct custom_mempool));
+
+ /* Create the ring so we can enqueue/dequeue */
+ cm->r = rte_ring_create(name,
+ rte_align32pow2(n+1), 0, 0);
+ if (cm->r == NULL)
+ return NULL;
+
+ /*
+ * Loop around the elements an allocate the required memory
+ * and place them in the ring.
+ * Not worried about alignment or performance for this example.
+ * Also, set the first 32-bits to be the element number so we
+ * can check later on.
+ */
+ for (i = 0; i < n; i++) {
+ cm->elements[i] = malloc(mp->elt_size);
+ memset(cm->elements[i], 0, mp->elt_size);
+ objnum = (uint32_t *)cm->elements[i];
+ *objnum = i;
+ rte_ring_sp_enqueue_bulk(cm->r, &(cm->elements[i]), 1);
+ }
+
+ return cm;
+}
+
+static int
+custom_mempool_put(void *p, void * const *obj_table, unsigned n)
+{
+ struct custom_mempool *cm = (struct custom_mempool *)p;
+
+ return rte_ring_mp_enqueue_bulk(cm->r, obj_table, n);
+}
+
+
+static int
+custom_mempool_get(void *p, void **obj_table, unsigned n)
+{
+ struct custom_mempool *cm = (struct custom_mempool *)p;
+
+ return rte_ring_mc_dequeue_bulk(cm->r, obj_table, n);
+}
+
+static unsigned
+custom_mempool_get_count(void *p)
+{
+ struct custom_mempool *cm = (struct custom_mempool *)p;
+
+ return rte_ring_count(cm->r);
+}
+
+static struct rte_mempool_handler mempool_handler_custom = {
+ .name = "custom_handler",
+ .alloc = custom_mempool_alloc,
+ .put = custom_mempool_put,
+ .get = custom_mempool_get,
+ .get_count = custom_mempool_get_count,
+};
+
+REGISTER_MEMPOOL_HANDLER(mempool_handler_custom);
+