From 1d64e46eb8c4fb8085513e9be824f2377b9c70c7 Mon Sep 17 00:00:00 2001 From: Olivier Matz Date: Fri, 9 May 2014 12:14:53 +0200 Subject: [PATCH] ring: allow to initialize without memzone Allow to initialize a ring in an already allocated memory. The rte_ring_create() function that allocates a ring in a rte_memzone is still available and now uses the new rte_ring_init() function in order to factorize the code. Signed-off-by: Olivier Matz Acked-by: Konstantin Ananyev --- lib/librte_ring/rte_ring.c | 63 ++++++++++++++++++++++---------------- lib/librte_ring/rte_ring.h | 51 +++++++++++++++++++++++++++--- 2 files changed, 82 insertions(+), 32 deletions(-) diff --git a/lib/librte_ring/rte_ring.c b/lib/librte_ring/rte_ring.c index 156fe49f31..2eaa6c899e 100644 --- a/lib/librte_ring/rte_ring.c +++ b/lib/librte_ring/rte_ring.c @@ -113,18 +113,10 @@ rte_ring_get_memsize(unsigned count) return sz; } -/* create the ring */ -struct rte_ring * -rte_ring_create(const char *name, unsigned count, int socket_id, - unsigned flags) +int +rte_ring_init(struct rte_ring *r, const char *name, unsigned count, + unsigned flags) { - char mz_name[RTE_MEMZONE_NAMESIZE]; - struct rte_ring *r; - const struct rte_memzone *mz; - ssize_t ring_size; - int mz_flags = 0; - struct rte_ring_list* ring_list = NULL; - /* compilation-time checks */ RTE_BUILD_BUG_ON((sizeof(struct rte_ring) & CACHE_LINE_MASK) != 0); @@ -141,11 +133,38 @@ rte_ring_create(const char *name, unsigned count, int socket_id, CACHE_LINE_MASK) != 0); #endif + /* init the ring structure */ + memset(r, 0, sizeof(*r)); + rte_snprintf(r->name, sizeof(r->name), "%s", name); + r->flags = flags; + r->prod.watermark = count; + r->prod.sp_enqueue = !!(flags & RING_F_SP_ENQ); + r->cons.sc_dequeue = !!(flags & RING_F_SC_DEQ); + r->prod.size = r->cons.size = count; + r->prod.mask = r->cons.mask = count-1; + r->prod.head = r->cons.head = 0; + r->prod.tail = r->cons.tail = 0; + + return 0; +} + +/* create the ring */ +struct rte_ring * +rte_ring_create(const char *name, unsigned count, int socket_id, + unsigned flags) +{ + char mz_name[RTE_MEMZONE_NAMESIZE]; + struct rte_ring *r; + const struct rte_memzone *mz; + ssize_t ring_size; + int mz_flags = 0; + struct rte_ring_list* ring_list = NULL; + /* check that we have an initialised tail queue */ - if ((ring_list = + if ((ring_list = RTE_TAILQ_LOOKUP_BY_IDX(RTE_TAILQ_RING, rte_ring_list)) == NULL) { rte_errno = E_RTE_NO_TAILQ; - return NULL; + return NULL; } ring_size = rte_ring_get_memsize(count); @@ -164,26 +183,16 @@ rte_ring_create(const char *name, unsigned count, int socket_id, mz = rte_memzone_reserve(mz_name, ring_size, socket_id, mz_flags); if (mz != NULL) { r = mz->addr; - - /* init the ring structure */ - memset(r, 0, sizeof(*r)); - rte_snprintf(r->name, sizeof(r->name), "%s", name); - r->flags = flags; - r->prod.watermark = count; - r->prod.sp_enqueue = !!(flags & RING_F_SP_ENQ); - r->cons.sc_dequeue = !!(flags & RING_F_SC_DEQ); - r->prod.size = r->cons.size = count; - r->prod.mask = r->cons.mask = count-1; - r->prod.head = r->cons.head = 0; - r->prod.tail = r->cons.tail = 0; - + /* no need to check return value here, we already checked the + * arguments above */ + rte_ring_init(r, name, count, flags); TAILQ_INSERT_TAIL(ring_list, r, next); } else { r = NULL; RTE_LOG(ERR, RING, "Cannot reserve memory\n"); } rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK); - + return r; } diff --git a/lib/librte_ring/rte_ring.h b/lib/librte_ring/rte_ring.h index e8493f2687..96232d35d9 100644 --- a/lib/librte_ring/rte_ring.h +++ b/lib/librte_ring/rte_ring.h @@ -214,14 +214,55 @@ struct rte_ring { */ ssize_t rte_ring_get_memsize(unsigned count); +/** + * Initialize a ring structure. + * + * Initialize a ring structure in memory pointed by "r". The size of the + * memory area must be large enough to store the ring structure and the + * object table. It is advised to use rte_ring_get_memsize() to get the + * appropriate size. + * + * The ring size is set to *count*, which must be a power of two. Water + * marking is disabled by default. The real usable ring size is + * *count-1* instead of *count* to differentiate a free ring from an + * empty ring. + * + * The ring is not added in RTE_TAILQ_RING global list. Indeed, the + * memory given by the caller may not be shareable among dpdk + * processes. + * + * @param r + * The pointer to the ring structure followed by the objects table. + * @param name + * The name of the ring. + * @param count + * The number of elements in the ring (must be a power of 2). + * @param flags + * An OR of the following: + * - RING_F_SP_ENQ: If this flag is set, the default behavior when + * using ``rte_ring_enqueue()`` or ``rte_ring_enqueue_bulk()`` + * is "single-producer". Otherwise, it is "multi-producers". + * - RING_F_SC_DEQ: If this flag is set, the default behavior when + * using ``rte_ring_dequeue()`` or ``rte_ring_dequeue_bulk()`` + * is "single-consumer". Otherwise, it is "multi-consumers". + * @return + * 0 on success, or a negative value on error. + */ +int rte_ring_init(struct rte_ring *r, const char *name, unsigned count, + unsigned flags); + /** * Create a new ring named *name* in memory. * - * This function uses ``memzone_reserve()`` to allocate memory. Its size is - * set to *count*, which must be a power of two. Water marking is - * disabled by default. - * Note that the real usable ring size is *count-1* instead of - * *count*. + * This function uses ``memzone_reserve()`` to allocate memory. Then it + * calls rte_ring_init() to initialize an empty ring. + * + * The new ring size is set to *count*, which must be a power of + * two. Water marking is disabled by default. The real usable ring size + * is *count-1* instead of *count* to differentiate a free ring from an + * empty ring. + * + * The ring is added in RTE_TAILQ_RING list. * * @param name * The name of the ring. -- 2.20.1