[dpdk-dev] [dpdk-dev, v5, 2/3] app/test: test external mempool handler
Jan Viktorin
viktorin at rehivetech.com
Mon May 23 14:45:30 CEST 2016
On Thu, 19 May 2016 14:45:00 +0100
David Hunt <david.hunt at intel.com> wrote:
> Use a minimal custom mempool external handler and check that it also
> passes basic mempool autotests.
>
> Signed-off-by: Olivier Matz <olivier.matz at 6wind.com>
> Signed-off-by: David Hunt <david.hunt at intel.com>
>
> ---
> app/test/test_mempool.c | 113 ++++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 113 insertions(+)
>
> diff --git a/app/test/test_mempool.c b/app/test/test_mempool.c
> index 9f02758..f55d126 100644
> --- a/app/test/test_mempool.c
> +++ b/app/test/test_mempool.c
> @@ -85,6 +85,96 @@
> static rte_atomic32_t synchro;
>
> /*
> + * Simple example of custom mempool structure. Holds pointers to all the
> + * elements which are simply malloc'd in this example.
> + */
> +struct custom_mempool {
> + rte_spinlock_t lock;
> + unsigned count;
> + unsigned size;
> + void *elts[];
> +};
> +
> +/*
> + * Loop though all the element pointers and allocate a chunk of memory, then
s/though/through/
> + * insert that memory into the ring.
> + */
> +static void *
> +custom_mempool_alloc(struct rte_mempool *mp)
> +{
> + struct custom_mempool *cm;
> +
> + cm = rte_zmalloc("custom_mempool",
> + sizeof(struct custom_mempool) + mp->size * sizeof(void *), 0);
> + if (cm == NULL)
> + return NULL;
> +
> + rte_spinlock_init(&cm->lock);
> + cm->count = 0;
> + cm->size = mp->size;
> + return cm;
> +}
> +
> +static void
> +custom_mempool_free(void *p)
> +{
> + rte_free(p);
> +}
> +
> +static int
> +custom_mempool_put(void *p, void * const *obj_table, unsigned n)
> +{
> + struct custom_mempool *cm = (struct custom_mempool *)p;
> + int ret = 0;
> +
> + rte_spinlock_lock(&cm->lock);
> + if (cm->count + n > cm->size) {
> + ret = -ENOBUFS;
> + } else {
> + memcpy(&cm->elts[cm->count], obj_table, sizeof(void *) * n);
> + cm->count += n;
> + }
> + rte_spinlock_unlock(&cm->lock);
> + return ret;
> +}
> +
> +
> +static int
> +custom_mempool_get(void *p, void **obj_table, unsigned n)
> +{
> + struct custom_mempool *cm = (struct custom_mempool *)p;
> + int ret = 0;
> +
> + rte_spinlock_lock(&cm->lock);
> + if (n > cm->count) {
> + ret = -ENOENT;
> + } else {
> + cm->count -= n;
> + memcpy(obj_table, &cm->elts[cm->count], sizeof(void *) * n);
> + }
> + rte_spinlock_unlock(&cm->lock);
> + return ret;
> +}
> +
> +static unsigned
> +custom_mempool_get_count(void *p)
> +{
> + struct custom_mempool *cm = (struct custom_mempool *)p;
> + return cm->count;
> +}
> +
> +static struct rte_mempool_handler mempool_handler_custom = {
> + .name = "custom_handler",
> + .alloc = custom_mempool_alloc,
> + .free = custom_mempool_free,
> + .put = custom_mempool_put,
> + .get = custom_mempool_get,
> + .get_count = custom_mempool_get_count,
> +};
> +
> +MEMPOOL_REGISTER_HANDLER(mempool_handler_custom);
What about to drop the rte_mempool_handler.name field and derive the
name from the variable name given to the MEMPOOL_REGISTER_HANDLER.
The MEMPOOL_REGISTER_HANDLER sould do some macro magic inside and call
rte_mempool_handler_register(name, handler);
Just an idea...
> +
> +/*
> * save the object number in the first 4 bytes of object data. All
> * other bytes are set to 0.
> */
> @@ -479,6 +569,7 @@ test_mempool(void)
> {
> struct rte_mempool *mp_cache = NULL;
> struct rte_mempool *mp_nocache = NULL;
> + struct rte_mempool *mp_ext = NULL;
>
> rte_atomic32_init(&synchro);
>
> @@ -507,6 +598,27 @@ test_mempool(void)
> goto err;
> }
>
> + /* create a mempool with an external handler */
> + mp_ext = rte_mempool_create_empty("test_ext",
> + MEMPOOL_SIZE,
> + MEMPOOL_ELT_SIZE,
> + RTE_MEMPOOL_CACHE_MAX_SIZE, 0,
> + SOCKET_ID_ANY, 0);
> +
> + if (mp_ext == NULL) {
> + printf("cannot allocate mp_ext mempool\n");
> + goto err;
> + }
> + if (rte_mempool_set_handler(mp_ext, "custom_handler") < 0) {
> + printf("cannot set custom handler\n");
> + goto err;
> + }
> + if (rte_mempool_populate_default(mp_ext) < 0) {
> + printf("cannot populate mp_ext mempool\n");
> + goto err;
> + }
> + rte_mempool_obj_iter(mp_ext, my_obj_init, NULL);
> +
The test becomes quite complex. What about having several smaller
tests with a clear setup and cleanup steps?
> /* retrieve the mempool from its name */
> if (rte_mempool_lookup("test_nocache") != mp_nocache) {
> printf("Cannot lookup mempool from its name\n");
> @@ -547,6 +659,7 @@ test_mempool(void)
> err:
> rte_mempool_free(mp_nocache);
> rte_mempool_free(mp_cache);
> + rte_mempool_free(mp_ext);
> return -1;
> }
>
More information about the dev
mailing list