X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=lib%2Flibrte_ring%2Frte_ring.h;h=86faede8100611bda3e411ab8f8b991a021724ab;hb=0d352661e066fe2cb386753c89368f014fc4396b;hp=e5a175cb3900147cd8295849bb58c89d09163b0c;hpb=7f9f46d6cef5b03681a3935b9a18378e08ca6f62;p=dpdk.git diff --git a/lib/librte_ring/rte_ring.h b/lib/librte_ring/rte_ring.h index e5a175cb39..86faede810 100644 --- a/lib/librte_ring/rte_ring.h +++ b/lib/librte_ring/rte_ring.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: BSD-3-Clause * - * Copyright (c) 2010-2017 Intel Corporation + * Copyright (c) 2010-2020 Intel Corporation * Copyright (c) 2007-2009 Kip Macy kmacy@freebsd.org * All rights reserved. * Derived from FreeBSD's bufring.h @@ -25,6 +25,9 @@ * - Multi- or single-producer enqueue. * - Bulk dequeue. * - Bulk enqueue. + * - Ability to select different sync modes for producer/consumer. + * - Dequeue start/finish (depending on consumer sync modes). + * - Enqueue start/finish (depending on producer sync mode). * * Note: the ring implementation is not preemptible. Refer to Programmer's * guide/Environment Abstraction Layer/Multiple pthread/Known Issues/rte_ring @@ -36,91 +39,7 @@ extern "C" { #endif -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define RTE_TAILQ_RING_NAME "RTE_RING" - -enum rte_ring_queue_behavior { - RTE_RING_QUEUE_FIXED = 0, /* Enq/Deq a fixed number of items from a ring */ - RTE_RING_QUEUE_VARIABLE /* Enq/Deq as many items as possible from ring */ -}; - -#define RTE_RING_MZ_PREFIX "RG_" -/** The maximum length of a ring name. */ -#define RTE_RING_NAMESIZE (RTE_MEMZONE_NAMESIZE - \ - sizeof(RTE_RING_MZ_PREFIX) + 1) - -/* structure to hold a pair of head/tail values and other metadata */ -struct rte_ring_headtail { - volatile uint32_t head; /**< Prod/consumer head. */ - volatile uint32_t tail; /**< Prod/consumer tail. */ - uint32_t single; /**< True if single prod/cons */ -}; - -/** - * 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 rte_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] __rte_cache_aligned; /**< Name of the ring. */ - int flags; /**< Flags supplied at creation. */ - const struct rte_memzone *memzone; - /**< Memzone, if any, containing the rte_ring */ - uint32_t size; /**< Size of ring. */ - uint32_t mask; /**< Mask (size-1) of ring. */ - uint32_t capacity; /**< Usable size of ring */ - - char pad0 __rte_cache_aligned; /**< empty cache line */ - - /** Ring producer status. */ - struct rte_ring_headtail prod __rte_cache_aligned; - char pad1 __rte_cache_aligned; /**< empty cache line */ - - /** Ring consumer status. */ - struct rte_ring_headtail cons __rte_cache_aligned; - char pad2 __rte_cache_aligned; /**< empty cache line */ -}; - -#define RING_F_SP_ENQ 0x0001 /**< The default enqueue is "single-producer". */ -#define RING_F_SC_DEQ 0x0002 /**< The default dequeue is "single-consumer". */ -/** - * Ring is to hold exactly requested number of entries. - * Without this flag set, the ring size requested must be a power of 2, and the - * usable space will be that size - 1. With the flag, the requested size will - * be rounded up to the next power of two, but the usable space will be exactly - * that requested. Worst case, if a power-of-2 size is requested, half the - * ring space will be wasted. - */ -#define RING_F_EXACT_SZ 0x0004 -#define RTE_RING_SZ_MASK (0x7fffffffU) /**< Ring size mask */ - -/* @internal defines for passing to the enqueue dequeue worker functions */ -#define __IS_SP 1 -#define __IS_MP 0 -#define __IS_SC 1 -#define __IS_MC 0 +#include /** * Calculate the memory size needed for a ring @@ -163,12 +82,30 @@ ssize_t rte_ring_get_memsize(unsigned 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". + * - One of mutually exclusive flags that define producer behavior: + * - 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". + * - RING_F_MP_RTS_ENQ: If this flag is set, the default behavior when + * using ``rte_ring_enqueue()`` or ``rte_ring_enqueue_bulk()`` + * is "multi-producer RTS mode". + * - RING_F_MP_HTS_ENQ: If this flag is set, the default behavior when + * using ``rte_ring_enqueue()`` or ``rte_ring_enqueue_bulk()`` + * is "multi-producer HTS mode". + * If none of these flags is set, then default "multi-producer" + * behavior is selected. + * - One of mutually exclusive flags that define consumer behavior: + * - 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". + * - RING_F_MC_RTS_DEQ: If this flag is set, the default behavior when + * using ``rte_ring_dequeue()`` or ``rte_ring_dequeue_bulk()`` + * is "multi-consumer RTS mode". + * - RING_F_MC_HTS_DEQ: If this flag is set, the default behavior when + * using ``rte_ring_dequeue()`` or ``rte_ring_dequeue_bulk()`` + * is "multi-consumer HTS mode". + * If none of these flags is set, then default "multi-consumer" + * behavior is selected. * @return * 0 on success, or a negative value on error. */ @@ -198,12 +135,30 @@ int rte_ring_init(struct rte_ring *r, const char *name, unsigned count, * constraint for the reserved zone. * @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". + * - One of mutually exclusive flags that define producer behavior: + * - 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". + * - RING_F_MP_RTS_ENQ: If this flag is set, the default behavior when + * using ``rte_ring_enqueue()`` or ``rte_ring_enqueue_bulk()`` + * is "multi-producer RTS mode". + * - RING_F_MP_HTS_ENQ: If this flag is set, the default behavior when + * using ``rte_ring_enqueue()`` or ``rte_ring_enqueue_bulk()`` + * is "multi-producer HTS mode". + * If none of these flags is set, then default "multi-producer" + * behavior is selected. + * - One of mutually exclusive flags that define consumer behavior: + * - 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". + * - RING_F_MC_RTS_DEQ: If this flag is set, the default behavior when + * using ``rte_ring_dequeue()`` or ``rte_ring_dequeue_bulk()`` + * is "multi-consumer RTS mode". + * - RING_F_MC_HTS_DEQ: If this flag is set, the default behavior when + * using ``rte_ring_dequeue()`` or ``rte_ring_dequeue_bulk()`` + * is "multi-consumer HTS mode". + * If none of these flags is set, then default "multi-consumer" + * behavior is selected. * @return * On success, the pointer to the new allocated ring. NULL on error with * rte_errno set appropriately. Possible errno values include: @@ -216,6 +171,7 @@ int rte_ring_init(struct rte_ring *r, const char *name, unsigned count, */ struct rte_ring *rte_ring_create(const char *name, unsigned count, int socket_id, unsigned flags); + /** * De-allocate all memory used by the ring. * @@ -419,7 +375,7 @@ rte_ring_mp_enqueue_bulk(struct rte_ring *r, void * const *obj_table, unsigned int n, unsigned int *free_space) { return __rte_ring_do_enqueue(r, obj_table, n, RTE_RING_QUEUE_FIXED, - __IS_MP, free_space); + RTE_RING_SYNC_MT, free_space); } /** @@ -442,9 +398,13 @@ rte_ring_sp_enqueue_bulk(struct rte_ring *r, void * const *obj_table, unsigned int n, unsigned int *free_space) { return __rte_ring_do_enqueue(r, obj_table, n, RTE_RING_QUEUE_FIXED, - __IS_SP, free_space); + RTE_RING_SYNC_ST, free_space); } +#ifdef ALLOW_EXPERIMENTAL_API +#include +#endif + /** * Enqueue several objects on a ring. * @@ -468,8 +428,24 @@ static __rte_always_inline unsigned int rte_ring_enqueue_bulk(struct rte_ring *r, void * const *obj_table, unsigned int n, unsigned int *free_space) { - return __rte_ring_do_enqueue(r, obj_table, n, RTE_RING_QUEUE_FIXED, - r->prod.single, free_space); + switch (r->prod.sync_type) { + case RTE_RING_SYNC_MT: + return rte_ring_mp_enqueue_bulk(r, obj_table, n, free_space); + case RTE_RING_SYNC_ST: + return rte_ring_sp_enqueue_bulk(r, obj_table, n, free_space); +#ifdef ALLOW_EXPERIMENTAL_API + case RTE_RING_SYNC_MT_RTS: + return rte_ring_mp_rts_enqueue_bulk(r, obj_table, n, + free_space); + case RTE_RING_SYNC_MT_HTS: + return rte_ring_mp_hts_enqueue_bulk(r, obj_table, n, + free_space); +#endif + } + + /* valid ring should never reach this point */ + RTE_ASSERT(0); + return 0; } /** @@ -553,7 +529,7 @@ rte_ring_mc_dequeue_bulk(struct rte_ring *r, void **obj_table, unsigned int n, unsigned int *available) { return __rte_ring_do_dequeue(r, obj_table, n, RTE_RING_QUEUE_FIXED, - __IS_MC, available); + RTE_RING_SYNC_MT, available); } /** @@ -577,7 +553,7 @@ rte_ring_sc_dequeue_bulk(struct rte_ring *r, void **obj_table, unsigned int n, unsigned int *available) { return __rte_ring_do_dequeue(r, obj_table, n, RTE_RING_QUEUE_FIXED, - __IS_SC, available); + RTE_RING_SYNC_ST, available); } /** @@ -603,8 +579,22 @@ static __rte_always_inline unsigned int rte_ring_dequeue_bulk(struct rte_ring *r, void **obj_table, unsigned int n, unsigned int *available) { - return __rte_ring_do_dequeue(r, obj_table, n, RTE_RING_QUEUE_FIXED, - r->cons.single, available); + switch (r->cons.sync_type) { + case RTE_RING_SYNC_MT: + return rte_ring_mc_dequeue_bulk(r, obj_table, n, available); + case RTE_RING_SYNC_ST: + return rte_ring_sc_dequeue_bulk(r, obj_table, n, available); +#ifdef ALLOW_EXPERIMENTAL_API + case RTE_RING_SYNC_MT_RTS: + return rte_ring_mc_rts_dequeue_bulk(r, obj_table, n, available); + case RTE_RING_SYNC_MT_HTS: + return rte_ring_mc_hts_dequeue_bulk(r, obj_table, n, available); +#endif + } + + /* valid ring should never reach this point */ + RTE_ASSERT(0); + return 0; } /** @@ -668,6 +658,23 @@ rte_ring_dequeue(struct rte_ring *r, void **obj_p) return rte_ring_dequeue_bulk(r, obj_p, 1, NULL) ? 0 : -ENOENT; } +/** + * Flush a ring. + * + * This function flush all the elements in a ring + * + * @b EXPERIMENTAL: this API may change without prior notice + * + * @warning + * Make sure the ring is not in use while calling this function. + * + * @param r + * A pointer to the ring structure. + */ +__rte_experimental +void +rte_ring_reset(struct rte_ring *r); + /** * Return the number of entries in a ring. * @@ -759,6 +766,62 @@ rte_ring_get_capacity(const struct rte_ring *r) return r->capacity; } +/** + * Return sync type used by producer in the ring. + * + * @param r + * A pointer to the ring structure. + * @return + * Producer sync type value. + */ +static inline enum rte_ring_sync_type +rte_ring_get_prod_sync_type(const struct rte_ring *r) +{ + return r->prod.sync_type; +} + +/** + * Check is the ring for single producer. + * + * @param r + * A pointer to the ring structure. + * @return + * true if ring is SP, zero otherwise. + */ +static inline int +rte_ring_is_prod_single(const struct rte_ring *r) +{ + return (rte_ring_get_prod_sync_type(r) == RTE_RING_SYNC_ST); +} + +/** + * Return sync type used by consumer in the ring. + * + * @param r + * A pointer to the ring structure. + * @return + * Consumer sync type value. + */ +static inline enum rte_ring_sync_type +rte_ring_get_cons_sync_type(const struct rte_ring *r) +{ + return r->cons.sync_type; +} + +/** + * Check is the ring for single consumer. + * + * @param r + * A pointer to the ring structure. + * @return + * true if ring is SC, zero otherwise. + */ +static inline int +rte_ring_is_cons_single(const struct rte_ring *r) +{ + return (rte_ring_get_cons_sync_type(r) == RTE_RING_SYNC_ST); +} + /** * Dump the status of all rings on the console * @@ -802,7 +865,7 @@ rte_ring_mp_enqueue_burst(struct rte_ring *r, void * const *obj_table, unsigned int n, unsigned int *free_space) { return __rte_ring_do_enqueue(r, obj_table, n, - RTE_RING_QUEUE_VARIABLE, __IS_MP, free_space); + RTE_RING_QUEUE_VARIABLE, RTE_RING_SYNC_MT, free_space); } /** @@ -825,7 +888,7 @@ rte_ring_sp_enqueue_burst(struct rte_ring *r, void * const *obj_table, unsigned int n, unsigned int *free_space) { return __rte_ring_do_enqueue(r, obj_table, n, - RTE_RING_QUEUE_VARIABLE, __IS_SP, free_space); + RTE_RING_QUEUE_VARIABLE, RTE_RING_SYNC_ST, free_space); } /** @@ -851,8 +914,24 @@ static __rte_always_inline unsigned rte_ring_enqueue_burst(struct rte_ring *r, void * const *obj_table, unsigned int n, unsigned int *free_space) { - return __rte_ring_do_enqueue(r, obj_table, n, RTE_RING_QUEUE_VARIABLE, - r->prod.single, free_space); + switch (r->prod.sync_type) { + case RTE_RING_SYNC_MT: + return rte_ring_mp_enqueue_burst(r, obj_table, n, free_space); + case RTE_RING_SYNC_ST: + return rte_ring_sp_enqueue_burst(r, obj_table, n, free_space); +#ifdef ALLOW_EXPERIMENTAL_API + case RTE_RING_SYNC_MT_RTS: + return rte_ring_mp_rts_enqueue_burst(r, obj_table, n, + free_space); + case RTE_RING_SYNC_MT_HTS: + return rte_ring_mp_hts_enqueue_burst(r, obj_table, n, + free_space); +#endif + } + + /* valid ring should never reach this point */ + RTE_ASSERT(0); + return 0; } /** @@ -880,7 +959,7 @@ rte_ring_mc_dequeue_burst(struct rte_ring *r, void **obj_table, unsigned int n, unsigned int *available) { return __rte_ring_do_dequeue(r, obj_table, n, - RTE_RING_QUEUE_VARIABLE, __IS_MC, available); + RTE_RING_QUEUE_VARIABLE, RTE_RING_SYNC_MT, available); } /** @@ -905,7 +984,7 @@ rte_ring_sc_dequeue_burst(struct rte_ring *r, void **obj_table, unsigned int n, unsigned int *available) { return __rte_ring_do_dequeue(r, obj_table, n, - RTE_RING_QUEUE_VARIABLE, __IS_SC, available); + RTE_RING_QUEUE_VARIABLE, RTE_RING_SYNC_ST, available); } /** @@ -931,9 +1010,24 @@ static __rte_always_inline unsigned rte_ring_dequeue_burst(struct rte_ring *r, void **obj_table, unsigned int n, unsigned int *available) { - return __rte_ring_do_dequeue(r, obj_table, n, - RTE_RING_QUEUE_VARIABLE, - r->cons.single, available); + switch (r->cons.sync_type) { + case RTE_RING_SYNC_MT: + return rte_ring_mc_dequeue_burst(r, obj_table, n, available); + case RTE_RING_SYNC_ST: + return rte_ring_sc_dequeue_burst(r, obj_table, n, available); +#ifdef ALLOW_EXPERIMENTAL_API + case RTE_RING_SYNC_MT_RTS: + return rte_ring_mc_rts_dequeue_burst(r, obj_table, n, + available); + case RTE_RING_SYNC_MT_HTS: + return rte_ring_mc_hts_dequeue_burst(r, obj_table, n, + available); +#endif + } + + /* valid ring should never reach this point */ + RTE_ASSERT(0); + return 0; } #ifdef __cplusplus