X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=lib%2Flibrte_stack%2Frte_stack.h;h=abf64207666d08bd898dbf81c6f1557f604603d3;hb=a617494eeb01ff;hp=42d042715b571c311e37fa0fe2fcfef1d82c40e8;hpb=05d3b5283cc1a61b2e204ddd6bc30b6f3053f280;p=dpdk.git diff --git a/lib/librte_stack/rte_stack.h b/lib/librte_stack/rte_stack.h index 42d042715b..abf6420766 100644 --- a/lib/librte_stack/rte_stack.h +++ b/lib/librte_stack/rte_stack.h @@ -4,9 +4,12 @@ /** * @file rte_stack.h - * @b EXPERIMENTAL: this API may change without prior notice * - * RTE Stack + * RTE Stack. + * + * @warning + * @b EXPERIMENTAL: + * All functions in this file may be changed or removed without prior notice. * * librte_stack provides an API for configuration and use of a bounded stack of * pointers. Push and pop operations are MT-safe, allowing concurrent access, @@ -20,6 +23,7 @@ extern "C" { #endif +#include #include #include #include @@ -32,6 +36,35 @@ extern "C" { #define RTE_STACK_NAMESIZE (RTE_MEMZONE_NAMESIZE - \ sizeof(RTE_STACK_MZ_PREFIX) + 1) +struct rte_stack_lf_elem { + void *data; /**< Data pointer */ + struct rte_stack_lf_elem *next; /**< Next pointer */ +}; + +struct rte_stack_lf_head { + struct rte_stack_lf_elem *top; /**< Stack top */ + uint64_t cnt; /**< Modification counter for avoiding ABA problem */ +}; + +struct rte_stack_lf_list { + /** List head */ + struct rte_stack_lf_head head __rte_aligned(16); + /** List len */ + uint64_t len; +}; + +/* Structure containing two lock-free LIFO lists: the stack itself and a list + * of free linked-list elements. + */ +struct rte_stack_lf { + /** LIFO list of elements */ + struct rte_stack_lf_list used __rte_cache_aligned; + /** LIFO list of free elements */ + struct rte_stack_lf_list free __rte_cache_aligned; + /** LIFO elements */ + struct rte_stack_lf_elem elems[] __rte_cache_aligned; +}; + /* Structure containing the LIFO, its current length, and a lock for mutual * exclusion. */ @@ -51,10 +84,21 @@ struct rte_stack { const struct rte_memzone *memzone; uint32_t capacity; /**< Usable size of the stack. */ uint32_t flags; /**< Flags supplied at creation. */ - struct rte_stack_std stack_std; /**< LIFO structure. */ + RTE_STD_C11 + union { + struct rte_stack_lf stack_lf; /**< Lock-free LIFO structure. */ + struct rte_stack_std stack_std; /**< LIFO structure. */ + }; } __rte_cache_aligned; +/** + * The stack uses lock-free push and pop functions. This flag is only + * supported on x86_64 platforms, currently. + */ +#define RTE_STACK_F_LF 0x0001 + #include "rte_stack_std.h" +#include "rte_stack_lf.h" /** * @warning @@ -71,13 +115,17 @@ struct rte_stack { * @return * Actual number of objects pushed (either 0 or *n*). */ -static __rte_always_inline unsigned int __rte_experimental +__rte_experimental +static __rte_always_inline unsigned int rte_stack_push(struct rte_stack *s, void * const *obj_table, unsigned int n) { RTE_ASSERT(s != NULL); RTE_ASSERT(obj_table != NULL); - return __rte_stack_std_push(s, obj_table, n); + if (s->flags & RTE_STACK_F_LF) + return __rte_stack_lf_push(s, obj_table, n); + else + return __rte_stack_std_push(s, obj_table, n); } /** @@ -95,13 +143,17 @@ rte_stack_push(struct rte_stack *s, void * const *obj_table, unsigned int n) * @return * Actual number of objects popped (either 0 or *n*). */ -static __rte_always_inline unsigned int __rte_experimental +__rte_experimental +static __rte_always_inline unsigned int rte_stack_pop(struct rte_stack *s, void **obj_table, unsigned int n) { RTE_ASSERT(s != NULL); RTE_ASSERT(obj_table != NULL); - return __rte_stack_std_pop(s, obj_table, n); + if (s->flags & RTE_STACK_F_LF) + return __rte_stack_lf_pop(s, obj_table, n); + else + return __rte_stack_std_pop(s, obj_table, n); } /** @@ -115,12 +167,16 @@ rte_stack_pop(struct rte_stack *s, void **obj_table, unsigned int n) * @return * The number of used entries in the stack. */ -static __rte_always_inline unsigned int __rte_experimental +__rte_experimental +static __rte_always_inline unsigned int rte_stack_count(struct rte_stack *s) { RTE_ASSERT(s != NULL); - return __rte_stack_std_count(s); + if (s->flags & RTE_STACK_F_LF) + return __rte_stack_lf_count(s); + else + return __rte_stack_std_count(s); } /** @@ -134,7 +190,8 @@ rte_stack_count(struct rte_stack *s) * @return * The number of free entries in the stack. */ -static __rte_always_inline unsigned int __rte_experimental +__rte_experimental +static __rte_always_inline unsigned int rte_stack_free_count(struct rte_stack *s) { RTE_ASSERT(s != NULL); @@ -160,7 +217,10 @@ rte_stack_free_count(struct rte_stack *s) * NUMA. The value can be *SOCKET_ID_ANY* if there is no NUMA * constraint for the reserved zone. * @param flags - * Reserved for future use. + * An OR of the following: + * - RTE_STACK_F_LF: If this flag is set, the stack uses lock-free + * variants of the push and pop functions. Otherwise, it achieves + * thread-safety using a lock. * @return * On success, the pointer to the new allocated stack. NULL on error with * rte_errno set appropriately. Possible errno values include: @@ -169,7 +229,8 @@ rte_stack_free_count(struct rte_stack *s) * - ENOMEM - insufficient memory to create the stack * - ENAMETOOLONG - name size exceeds RTE_STACK_NAMESIZE */ -struct rte_stack *__rte_experimental +__rte_experimental +struct rte_stack * rte_stack_create(const char *name, unsigned int count, int socket_id, uint32_t flags); @@ -182,7 +243,8 @@ rte_stack_create(const char *name, unsigned int count, int socket_id, * @param s * Stack to free */ -void __rte_experimental +__rte_experimental +void rte_stack_free(struct rte_stack *s); /** @@ -199,7 +261,8 @@ rte_stack_free(struct rte_stack *s); * - ENOENT - Stack with name *name* not found. * - EINVAL - *name* pointer is NULL. */ -struct rte_stack * __rte_experimental +__rte_experimental +struct rte_stack * rte_stack_lookup(const char *name); #ifdef __cplusplus