From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga02.intel.com (mga02.intel.com [134.134.136.20]) by dpdk.org (Postfix) with ESMTP id 2189AF940 for ; Wed, 11 Jan 2017 16:06:09 +0100 (CET) Received: from orsmga002.jf.intel.com ([10.7.209.21]) by orsmga101.jf.intel.com with ESMTP; 11 Jan 2017 07:06:09 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.33,346,1477983600"; d="scan'208";a="29056801" Received: from sivswdev01.ir.intel.com (HELO localhost.localdomain) ([10.237.217.45]) by orsmga002.jf.intel.com with ESMTP; 11 Jan 2017 07:06:08 -0800 From: Bruce Richardson To: olivier.matz@6wind.com Cc: dev@dpdk.org, Bruce Richardson Date: Wed, 11 Jan 2017 15:05:21 +0000 Message-Id: <1484147125-5948-8-git-send-email-bruce.richardson@intel.com> X-Mailer: git-send-email 1.7.0.7 In-Reply-To: <1484147125-5948-1-git-send-email-bruce.richardson@intel.com> References: <1484147125-5948-1-git-send-email-bruce.richardson@intel.com> Subject: [dpdk-dev] [RFC PATCH 07/11] ring: allow multiple typed rings in the same unit X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 11 Jan 2017 15:06:10 -0000 allow the typed ring header file to be included multiple times inside a C file so that we can have multiple different ring types in use. This is tested by having a second ring type in the unit tests, which works with small (16 byte) structures, rather than just pointers. Signed-off-by: Bruce Richardson --- app/test/test_typed_ring.c | 60 +++++++++++++++- lib/librte_ring/rte_typed_ring.h | 144 ++++++++++++++++++++------------------- 2 files changed, 132 insertions(+), 72 deletions(-) diff --git a/app/test/test_typed_ring.c b/app/test/test_typed_ring.c index aaef023..b403af5 100644 --- a/app/test/test_typed_ring.c +++ b/app/test/test_typed_ring.c @@ -37,6 +37,19 @@ #define RING_TYPE struct rte_mbuf * #define RING_TYPE_NAME rte_mbuf #include +#undef RING_TYPE_NAME +#undef RING_TYPE + +struct xyval { + uint64_t x; + void *y; +}; + +#define RING_TYPE struct xyval /* structure not pointer */ +#define RING_TYPE_NAME rte_xyval +#include +#undef RING_TYPE_NAME +#undef RING_TYPE #define RING_SIZE 256 #define BURST_SZ 32 @@ -73,6 +86,38 @@ test_mbuf_enqueue_dequeue(struct rte_mbuf_ring *r) return 0; } +static int +test_xyval_enqueue_dequeue(struct rte_xyval_ring *r) +{ + struct xyval inbufs[BURST_SZ]; + struct xyval outbufs[BURST_SZ]; + unsigned int i, j; + + for (i = 0; i < BURST_SZ; i++) + inbufs[i].x = rte_rand(); + + for (i = 0; i < ITERATIONS; i++) { + uint16_t in = rte_xyval_ring_enqueue_burst(r, inbufs, BURST_SZ); + if (in != BURST_SZ) { + printf("Error enqueuing xyvals\n"); + return -1; + } + uint16_t out = rte_xyval_ring_dequeue_burst(r, outbufs, BURST_SZ); + if (out != BURST_SZ) { + printf("Error dequeuing xyvals\n"); + return -1; + } + + for (j = 0; j < BURST_SZ; j++) + if (outbufs[j].x != inbufs[j].x || + outbufs[j].y != inbufs[j].y) { + printf("Error: dequeued val != enqueued val\n"); + return -1; + } + } + return 0; +} + /** * test entry point */ @@ -87,13 +132,24 @@ test_typed_ring(void) return -1; } rte_mbuf_ring_list_dump(stdout); - + printf("mbuf ring has memory size %u\n", + (unsigned int)rte_mbuf_ring_get_memsize(RING_SIZE)); if (test_mbuf_enqueue_dequeue(r) != 0) { rte_mbuf_ring_free(r); return -1; } - rte_mbuf_ring_free(r); + + struct rte_xyval_ring *r2; + r2 = rte_xyval_ring_create("xyval_ring", RING_SIZE, rte_socket_id(), + RING_F_SP_ENQ | RING_F_SC_DEQ); + if (test_xyval_enqueue_dequeue(r2) != 0) { + rte_xyval_ring_free(r2); + return -1; + } + printf("xyval ring has memory size %u\n", + (unsigned int)rte_xyval_ring_get_memsize(RING_SIZE)); + rte_xyval_ring_free(r2); return 0; } diff --git a/lib/librte_ring/rte_typed_ring.h b/lib/librte_ring/rte_typed_ring.h index 3f7514f..79edc65 100644 --- a/lib/librte_ring/rte_typed_ring.h +++ b/lib/librte_ring/rte_typed_ring.h @@ -114,14 +114,6 @@ extern "C" { #define _CAT(a, b) a ## _ ## b #define CAT(a, b) _CAT(a, b) -#ifndef RING_TYPE_NAME -#error "Need RING_TYPE_NAME defined before including" -#endif -#ifndef RING_TYPE -#error "Need RING_TYPE defined before including" -#endif -#define TYPE(x) CAT(RING_TYPE_NAME, x) - #define RTE_TAILQ_RING_NAME "RTE_RING" enum rte_ring_queue_behavior { @@ -160,63 +152,7 @@ struct rte_ring_debug_stats { #define RTE_RING_PAUSE_REP_COUNT 0 #endif -struct rte_memzone; /* forward declaration, so as not to require memzone.h */ - -/** - * An RTE ring structure. - * - * The producer and the consumer have a head and a tail index. The particularity - * of these index is that they are not between 0 and size(ring). These indexes - * are between 0 and 2^32, and we mask their value when we access the ring[] - * field. Thanks to this assumption, we can do subtractions between 2 index - * values in a modulo-32bit base: that's why the overflow of the indexes is not - * a problem. - */ -struct TYPE(ring) { - /* - * Note: this field kept the RTE_MEMZONE_NAMESIZE size due to ABI - * compatibility requirements, it could be changed to RTE_RING_NAMESIZE - * next time the ABI changes - */ - char name[RTE_MEMZONE_NAMESIZE]; /**< Name of the ring. */ - int flags; /**< Flags supplied at creation. */ - const struct rte_memzone *memzone; - /**< Memzone, if any, containing the ring */ - - /** Ring producer status. */ - struct prod { - uint32_t watermark; /**< Maximum items before EDQUOT. */ - uint32_t sp_enqueue; /**< True, if single producer. */ - uint32_t size; /**< Size of ring. */ - uint32_t mask; /**< Mask (size-1) of ring. */ - volatile uint32_t head; /**< Producer head. */ - volatile uint32_t tail; /**< Producer tail. */ - } prod __rte_cache_aligned; - - /** Ring consumer status. */ - struct cons { - uint32_t sc_dequeue; /**< True, if single consumer. */ - uint32_t size; /**< Size of the ring. */ - uint32_t mask; /**< Mask (size-1) of ring. */ - volatile uint32_t head; /**< Consumer head. */ - volatile uint32_t tail; /**< Consumer tail. */ -#ifdef RTE_RING_SPLIT_PROD_CONS - } cons __rte_cache_aligned; -#else - } cons; -#endif - -#ifdef RTE_LIBRTE_RING_DEBUG - struct rte_ring_debug_stats stats[RTE_MAX_LCORE]; -#endif - - /** - * Memory space of ring starts here. - * not volatile so need to be careful - * about compiler re-ordering - */ - RING_TYPE ring[] __rte_cache_aligned; -}; +TAILQ_HEAD(rte_ring_list, rte_tailq_entry); #define RING_F_SP_ENQ 0x0001 /**< The default enqueue is "single-producer". */ #define RING_F_SC_DEQ 0x0002 /**< The default dequeue is "single-consumer". */ @@ -304,6 +240,77 @@ struct TYPE(ring) { } \ } while (0) +extern struct rte_tailq_elem rte_ring_tailq; + +#endif /* _RTE_RING_H_ */ + +#ifndef RING_TYPE_NAME +#error "Need RING_TYPE_NAME defined before including" +#endif +#ifndef RING_TYPE +#error "Need RING_TYPE defined before including" +#endif +#define TYPE(x) CAT(RING_TYPE_NAME, x) + +struct rte_memzone; /* forward declaration, so as not to require memzone.h */ + +/** + * An RTE ring structure. + * + * The producer and the consumer have a head and a tail index. The particularity + * of these index is that they are not between 0 and size(ring). These indexes + * are between 0 and 2^32, and we mask their value when we access the ring[] + * field. Thanks to this assumption, we can do subtractions between 2 index + * values in a modulo-32bit base: that's why the overflow of the indexes is not + * a problem. + */ +struct TYPE(ring) { + /* + * Note: this field kept the RTE_MEMZONE_NAMESIZE size due to ABI + * compatibility requirements, it could be changed to RTE_RING_NAMESIZE + * next time the ABI changes + */ + char name[RTE_MEMZONE_NAMESIZE]; /**< Name of the ring. */ + int flags; /**< Flags supplied at creation. */ + const struct rte_memzone *memzone; + /**< Memzone, if any, containing the ring */ + + /** Ring producer status. */ + struct { + uint32_t watermark; /**< Maximum items before EDQUOT. */ + uint32_t sp_enqueue; /**< True, if single producer. */ + uint32_t size; /**< Size of ring. */ + uint32_t mask; /**< Mask (size-1) of ring. */ + volatile uint32_t head; /**< Producer head. */ + volatile uint32_t tail; /**< Producer tail. */ + } prod __rte_cache_aligned; + + /** Ring consumer status. */ + struct { + uint32_t sc_dequeue; /**< True, if single consumer. */ + uint32_t size; /**< Size of the ring. */ + uint32_t mask; /**< Mask (size-1) of ring. */ + volatile uint32_t head; /**< Consumer head. */ + volatile uint32_t tail; /**< Consumer tail. */ +#ifdef RTE_RING_SPLIT_PROD_CONS + } cons __rte_cache_aligned; +#else + } cons; +#endif + +#ifdef RTE_LIBRTE_RING_DEBUG + struct rte_ring_debug_stats stats[RTE_MAX_LCORE]; +#endif + + /** + * Memory space of ring starts here. + * not volatile so need to be careful + * about compiler re-ordering + */ + RING_TYPE ring[] __rte_cache_aligned; +}; + + /** * @internal Enqueue several objects on the ring (multi-producers safe). * @@ -1146,10 +1153,6 @@ TYPE(ring_dequeue_burst)(struct TYPE(ring) *r, RING_TYPE *obj_table, unsigned in return TYPE(ring_mc_dequeue_burst)(r, obj_table, n); } -TAILQ_HEAD(rte_ring_list, rte_tailq_entry); - -extern struct rte_tailq_elem rte_ring_tailq; - /** * Calculate the memory size needed for a ring * @@ -1559,8 +1562,9 @@ TYPE(ring_lookup)(const char *name) return r; } +#undef TYPE + #ifdef __cplusplus } #endif -#endif /* _RTE_RING_H_ */ -- 2.9.3