X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=lib%2Flibrte_mempool%2Frte_mempool.h;h=bdb217b3b7d9c07e54fbeb34856258b6550afb00;hb=3d7e7f026efe919b95a4f860e687b72919e7ae60;hp=a8054e139e840dcab55c95a37729f36fe72d5a81;hpb=00e481412a4c48412dc03a0b63fcf0c3dd3085f3;p=dpdk.git diff --git a/lib/librte_mempool/rte_mempool.h b/lib/librte_mempool/rte_mempool.h index a8054e139e..bdb217b3b7 100644 --- a/lib/librte_mempool/rte_mempool.h +++ b/lib/librte_mempool/rte_mempool.h @@ -2,6 +2,7 @@ * BSD LICENSE * * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. + * Copyright(c) 2016 6WIND S.A. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -95,7 +96,6 @@ struct rte_mempool_debug_stats { } __rte_cache_aligned; #endif -#if RTE_MEMPOOL_CACHE_MAX_SIZE > 0 /** * A structure that stores a per-core object cache. */ @@ -107,7 +107,6 @@ struct rte_mempool_cache { */ void *objs[RTE_MEMPOOL_CACHE_MAX_SIZE * 3]; /**< Cache objects */ } __rte_cache_aligned; -#endif /* RTE_MEMPOOL_CACHE_MAX_SIZE > 0 */ /** * A structure that stores the size of mempool elements. @@ -142,21 +141,34 @@ struct rte_mempool_objsz { /** Mempool over one chunk of physically continuous memory */ #define MEMPOOL_PG_NUM_DEFAULT 1 +#ifndef RTE_MEMPOOL_ALIGN +#define RTE_MEMPOOL_ALIGN RTE_CACHE_LINE_SIZE +#endif + +#define RTE_MEMPOOL_ALIGN_MASK (RTE_MEMPOOL_ALIGN - 1) + /** * Mempool object header structure * * Each object stored in mempools are prefixed by this header structure, - * it allows to retrieve the mempool pointer from the object. When debug - * is enabled, a cookie is also added in this structure preventing - * corruptions and double-frees. + * it allows to retrieve the mempool pointer from the object and to + * iterate on all objects attached to a mempool. When debug is enabled, + * a cookie is also added in this structure preventing corruptions and + * double-frees. */ struct rte_mempool_objhdr { + STAILQ_ENTRY(rte_mempool_objhdr) next; /**< Next in list. */ struct rte_mempool *mp; /**< The mempool owning the object. */ #ifdef RTE_LIBRTE_MEMPOOL_DEBUG uint64_t cookie; /**< Debug cookie. */ #endif }; +/** + * A list of object headers type + */ +STAILQ_HEAD(rte_mempool_objhdr_list, rte_mempool_objhdr); + /** * Mempool object trailer structure * @@ -188,10 +200,9 @@ struct rte_mempool { unsigned private_data_size; /**< Size of private data. */ -#if RTE_MEMPOOL_CACHE_MAX_SIZE > 0 - /** Per-lcore local cache. */ - struct rte_mempool_cache local_cache[RTE_MAX_LCORE]; -#endif + struct rte_mempool_cache *local_cache; /**< Per-lcore local cache */ + + struct rte_mempool_objhdr_list elt_list; /**< List of objects in pool */ #ifdef RTE_LIBRTE_MEMPOOL_DEBUG /** Per-lcore statistics. */ @@ -213,7 +224,7 @@ struct rte_mempool { } __rte_cache_aligned; -#define MEMPOOL_F_NO_SPREAD 0x0001 /**< Do not spread in memory. */ +#define MEMPOOL_F_NO_SPREAD 0x0001 /**< Do not spread among memory channels. */ #define MEMPOOL_F_NO_CACHE_ALIGN 0x0002 /**< Do not align objs on cache lines.*/ #define MEMPOOL_F_SP_PUT 0x0004 /**< Default put is "single-producer".*/ #define MEMPOOL_F_SC_GET 0x0008 /**< Default get is "single-consumer".*/ @@ -240,6 +251,13 @@ struct rte_mempool { #define __MEMPOOL_STAT_ADD(mp, name, n) do {} while(0) #endif +/** + * Size of elt_pa array size based on number of pages. (Internal use) + */ +#define __PA_SIZE(mp, pgn) \ + RTE_ALIGN_CEIL((((pgn) - RTE_DIM((mp)->elt_pa)) * \ + sizeof((mp)->elt_pa[0])), RTE_CACHE_LINE_SIZE) + /** * Calculate the size of the mempool header. * @@ -247,10 +265,12 @@ struct rte_mempool { * Pointer to the memory pool. * @param pgn * Number of pages used to store mempool objects. + * @param cs + * Size of the per-lcore cache. */ -#define MEMPOOL_HEADER_SIZE(mp, pgn) (sizeof(*(mp)) + \ - RTE_ALIGN_CEIL(((pgn) - RTE_DIM((mp)->elt_pa)) * \ - sizeof ((mp)->elt_pa[0]), RTE_CACHE_LINE_SIZE)) +#define MEMPOOL_HEADER_SIZE(mp, pgn, cs) \ + (sizeof(*(mp)) + __PA_SIZE(mp, pgn) + (((cs) == 0) ? 0 : \ + (sizeof(struct rte_mempool_cache) * RTE_MAX_LCORE))) /** * Return true if the whole mempool is in contiguous memory. @@ -262,17 +282,10 @@ struct rte_mempool { /* return the header of a mempool object (internal) */ static inline struct rte_mempool_objhdr *__mempool_get_header(void *obj) { - return (struct rte_mempool_objhdr *)((char *)obj - + return (struct rte_mempool_objhdr *)RTE_PTR_SUB(obj, sizeof(struct rte_mempool_objhdr)); } -/* return the trailer of a mempool object (internal) */ -static inline struct rte_mempool_objtlr *__mempool_get_trailer(void *obj) -{ - return (struct rte_mempool_objtlr *)((char *)obj - - sizeof(struct rte_mempool_objtlr)); -} - /** * Return a pointer to the mempool owning this object. * @@ -288,6 +301,13 @@ static inline struct rte_mempool *rte_mempool_from_obj(void *obj) return hdr->mp; } +/* return the trailer of a mempool object (internal) */ +static inline struct rte_mempool_objtlr *__mempool_get_trailer(void *obj) +{ + struct rte_mempool *mp = rte_mempool_from_obj(obj); + return (struct rte_mempool_objtlr *)RTE_PTR_ADD(obj, mp->elt_size); +} + /** * @internal Check and update cookies or panic. * @@ -302,140 +322,24 @@ static inline struct rte_mempool *rte_mempool_from_obj(void *obj) * - 1: object is supposed to be free, mark it as allocated * - 2: just check that cookie is valid (free or allocated) */ +void rte_mempool_check_cookies(const struct rte_mempool *mp, + void * const *obj_table_const, unsigned n, int free); + #ifdef RTE_LIBRTE_MEMPOOL_DEBUG -#ifndef __INTEL_COMPILER -#pragma GCC diagnostic ignored "-Wcast-qual" -#endif -static inline void __mempool_check_cookies(const struct rte_mempool *mp, - void * const *obj_table_const, - unsigned n, int free) -{ - struct rte_mempool_objhdr *hdr; - struct rte_mempool_objtlr *tlr; - uint64_t cookie; - void *tmp; - void *obj; - void **obj_table; - - /* Force to drop the "const" attribute. This is done only when - * DEBUG is enabled */ - tmp = (void *) obj_table_const; - obj_table = (void **) tmp; - - while (n--) { - obj = obj_table[n]; - - if (rte_mempool_from_obj(obj) != mp) - rte_panic("MEMPOOL: object is owned by another " - "mempool\n"); - - hdr = __mempool_get_header(obj); - cookie = hdr->cookie; - - if (free == 0) { - if (cookie != RTE_MEMPOOL_HEADER_COOKIE1) { - rte_log_set_history(0); - RTE_LOG(CRIT, MEMPOOL, - "obj=%p, mempool=%p, cookie=%" PRIx64 "\n", - obj, (const void *) mp, cookie); - rte_panic("MEMPOOL: bad header cookie (put)\n"); - } - hdr->cookie = RTE_MEMPOOL_HEADER_COOKIE2; - } - else if (free == 1) { - if (cookie != RTE_MEMPOOL_HEADER_COOKIE2) { - rte_log_set_history(0); - RTE_LOG(CRIT, MEMPOOL, - "obj=%p, mempool=%p, cookie=%" PRIx64 "\n", - obj, (const void *) mp, cookie); - rte_panic("MEMPOOL: bad header cookie (get)\n"); - } - hdr->cookie = RTE_MEMPOOL_HEADER_COOKIE1; - } - else if (free == 2) { - if (cookie != RTE_MEMPOOL_HEADER_COOKIE1 && - cookie != RTE_MEMPOOL_HEADER_COOKIE2) { - rte_log_set_history(0); - RTE_LOG(CRIT, MEMPOOL, - "obj=%p, mempool=%p, cookie=%" PRIx64 "\n", - obj, (const void *) mp, cookie); - rte_panic("MEMPOOL: bad header cookie (audit)\n"); - } - } - tlr = __mempool_get_trailer(obj); - cookie = tlr->cookie; - if (cookie != RTE_MEMPOOL_TRAILER_COOKIE) { - rte_log_set_history(0); - RTE_LOG(CRIT, MEMPOOL, - "obj=%p, mempool=%p, cookie=%" PRIx64 "\n", - obj, (const void *) mp, cookie); - rte_panic("MEMPOOL: bad trailer cookie\n"); - } - } -} -#ifndef __INTEL_COMPILER -#pragma GCC diagnostic error "-Wcast-qual" -#endif +#define __mempool_check_cookies(mp, obj_table_const, n, free) \ + rte_mempool_check_cookies(mp, obj_table_const, n, free) #else #define __mempool_check_cookies(mp, obj_table_const, n, free) do {} while(0) #endif /* RTE_LIBRTE_MEMPOOL_DEBUG */ /** - * A mempool object iterator callback function. - */ -typedef void (*rte_mempool_obj_iter_t)(void * /*obj_iter_arg*/, - void * /*obj_start*/, - void * /*obj_end*/, - uint32_t /*obj_index */); - -/** - * Call a function for each mempool object in a memory chunk - * - * Iterate across objects of the given size and alignment in the - * provided chunk of memory. The given memory buffer can consist of - * disjoint physical pages. + * An object callback function for mempool. * - * For each object, calls the provided callback (if any). This function - * is used to populate mempool, walk through all elements of the - * mempool, estimate how many elements of the given size could be - * created in the given memory buffer. - * - * @param vaddr - * Virtual address of the memory buffer. - * @param elt_num - * Maximum number of objects to iterate through. - * @param elt_sz - * Size of each object. - * @param paddr - * Array of physical addresses of the pages that comprises given memory - * buffer. - * @param pg_num - * Number of elements in the paddr array. - * @param pg_shift - * LOG2 of the physical pages size. - * @param obj_iter - * Object iterator callback function (could be NULL). - * @param obj_iter_arg - * User defined parameter for the object iterator callback function. - * - * @return - * Number of objects iterated through. + * Used by rte_mempool_create() and rte_mempool_obj_iter(). */ - -uint32_t rte_mempool_obj_iter(void *vaddr, - uint32_t elt_num, size_t elt_sz, size_t align, - const phys_addr_t paddr[], uint32_t pg_num, uint32_t pg_shift, - rte_mempool_obj_iter_t obj_iter, void *obj_iter_arg); - -/** - * An object constructor callback function for mempool. - * - * Arguments are the mempool, the opaque pointer given by the user in - * rte_mempool_create(), the pointer to the element and the index of - * the element in the pool. - */ -typedef void (rte_mempool_obj_ctor_t)(struct rte_mempool *, void *, - void *, unsigned); +typedef void (rte_mempool_obj_cb_t)(struct rte_mempool *mp, + void *opaque, void *obj, unsigned obj_idx); +typedef rte_mempool_obj_cb_t rte_mempool_obj_ctor_t; /* compat */ /** * A mempool constructor callback function. @@ -530,14 +434,15 @@ struct rte_mempool * rte_mempool_create(const char *name, unsigned n, unsigned elt_size, unsigned cache_size, unsigned private_data_size, rte_mempool_ctor_t *mp_init, void *mp_init_arg, - rte_mempool_obj_ctor_t *obj_init, void *obj_init_arg, + rte_mempool_obj_cb_t *obj_init, void *obj_init_arg, int socket_id, unsigned flags); /** * Create a new mempool named *name* in memory. * - * This function uses ``memzone_reserve()`` to allocate memory. The - * pool contains n elements of elt_size. Its size is set to n. + * The pool contains n elements of elt_size. Its size is set to n. + * This function uses ``memzone_reserve()`` to allocate the mempool header + * (and the objects if vaddr is NULL). * Depending on the input parameters, mempool elements can be either allocated * together with the mempool header, or an externally provided memory buffer * could be used to store mempool objects. In later case, that external @@ -552,18 +457,7 @@ rte_mempool_create(const char *name, unsigned n, unsigned elt_size, * @param elt_size * The size of each element. * @param cache_size - * If cache_size is non-zero, the rte_mempool library will try to - * limit the accesses to the common lockless pool, by maintaining a - * per-lcore object cache. This argument must be lower or equal to - * CONFIG_RTE_MEMPOOL_CACHE_MAX_SIZE. It is advised to choose - * cache_size to have "n modulo cache_size == 0": if this is - * not the case, some elements will always stay in the pool and will - * never be used. The access to the per-lcore table is of course - * faster than the multi-producer/consumer pool. The cache can be - * disabled if the cache_size argument is set to 0; it can be useful to - * avoid losing objects in cache. Note that even if not used, the - * memory space for cache is always reserved in a mempool structure, - * except if CONFIG_RTE_MEMPOOL_CACHE_MAX_SIZE is set to 0. + * Size of the cache. See rte_mempool_create() for details. * @param private_data_size * The size of the private data appended after the mempool * structure. This is useful for storing some private data after the @@ -577,35 +471,17 @@ rte_mempool_create(const char *name, unsigned n, unsigned elt_size, * An opaque pointer to data that can be used in the mempool * constructor function. * @param obj_init - * A function pointer that is called for each object at - * initialization of the pool. The user can set some meta data in - * objects if needed. This parameter can be NULL if not needed. - * The obj_init() function takes the mempool pointer, the init_arg, - * the object pointer and the object number as parameters. + * A function called for each object at initialization of the pool. + * See rte_mempool_create() for details. * @param obj_init_arg - * An opaque pointer to data that can be used as an argument for - * each call to the object constructor function. + * An opaque pointer passed to the object constructor function. * @param socket_id * The *socket_id* argument is the socket identifier in the case of * NUMA. The value can be *SOCKET_ID_ANY* if there is no NUMA * constraint for the reserved zone. * @param flags - * The *flags* arguments is an OR of following flags: - * - MEMPOOL_F_NO_SPREAD: By default, objects addresses are spread - * between channels in RAM: the pool allocator will add padding - * between objects depending on the hardware configuration. See - * Memory alignment constraints for details. If this flag is set, - * the allocator will just align them to a cache line. - * - MEMPOOL_F_NO_CACHE_ALIGN: By default, the returned objects are - * cache-aligned. This flag removes this constraint, and no - * padding will be present between objects. This flag implies - * MEMPOOL_F_NO_SPREAD. - * - MEMPOOL_F_SP_PUT: If this flag is set, the default behavior - * when using rte_mempool_put() or rte_mempool_put_bulk() is - * "single-producer". Otherwise, it is "multi-producers". - * - MEMPOOL_F_SC_GET: If this flag is set, the default behavior - * when using rte_mempool_get() or rte_mempool_get_bulk() is - * "single-consumer". Otherwise, it is "multi-consumers". + * Flags controlling the behavior of the mempool. See + * rte_mempool_create() for details. * @param vaddr * Virtual address of the externally allocated memory buffer. * Will be used to store mempool objects. @@ -618,23 +494,16 @@ rte_mempool_create(const char *name, unsigned n, unsigned elt_size, * LOG2 of the physical pages size. * @return * The pointer to the new allocated mempool, on success. NULL on error - * with rte_errno set appropriately. Possible rte_errno values include: - * - E_RTE_NO_CONFIG - function could not get pointer to rte_config structure - * - E_RTE_SECONDARY - function was called from a secondary process instance - * - EINVAL - cache size provided is too large - * - ENOSPC - the maximum number of memzones has already been allocated - * - EEXIST - a memzone with the same name already exists - * - ENOMEM - no appropriate memory area found in which to create memzone + * with rte_errno set appropriately. See rte_mempool_create() for details. */ struct rte_mempool * rte_mempool_xmem_create(const char *name, unsigned n, unsigned elt_size, unsigned cache_size, unsigned private_data_size, rte_mempool_ctor_t *mp_init, void *mp_init_arg, - rte_mempool_obj_ctor_t *obj_init, void *obj_init_arg, + rte_mempool_obj_cb_t *obj_init, void *obj_init_arg, int socket_id, unsigned flags, void *vaddr, const phys_addr_t paddr[], uint32_t pg_num, uint32_t pg_shift); -#ifdef RTE_LIBRTE_XEN_DOM0 /** * Create a new mempool named *name* in memory on Xen Dom0. * @@ -720,9 +589,27 @@ struct rte_mempool * rte_dom0_mempool_create(const char *name, unsigned n, unsigned elt_size, unsigned cache_size, unsigned private_data_size, rte_mempool_ctor_t *mp_init, void *mp_init_arg, - rte_mempool_obj_ctor_t *obj_init, void *obj_init_arg, + rte_mempool_obj_cb_t *obj_init, void *obj_init_arg, int socket_id, unsigned flags); -#endif + + +/** + * Call a function for each mempool element + * + * Iterate across all objects attached to a rte_mempool and call the + * callback function on it. + * + * @param mp + * A pointer to an initialized mempool. + * @param obj_cb + * A function pointer that is called for each object. + * @param obj_cb_arg + * An opaque pointer passed to the callback function. + * @return + * Number of objects iterated. + */ +uint32_t rte_mempool_obj_iter(struct rte_mempool *mp, + rte_mempool_obj_cb_t *obj_cb, void *obj_cb_arg); /** * Dump the status of the mempool to the console. @@ -732,7 +619,7 @@ rte_dom0_mempool_create(const char *name, unsigned n, unsigned elt_size, * @param mp * A pointer to the mempool structure. */ -void rte_mempool_dump(FILE *f, const struct rte_mempool *mp); +void rte_mempool_dump(FILE *f, struct rte_mempool *mp); /** * @internal Put several objects back in the mempool; used internally. @@ -750,19 +637,16 @@ static inline void __attribute__((always_inline)) __mempool_put_bulk(struct rte_mempool *mp, void * const *obj_table, unsigned n, int is_mp) { -#if RTE_MEMPOOL_CACHE_MAX_SIZE > 0 struct rte_mempool_cache *cache; uint32_t index; void **cache_objs; unsigned lcore_id = rte_lcore_id(); uint32_t cache_size = mp->cache_size; uint32_t flushthresh = mp->cache_flushthresh; -#endif /* RTE_MEMPOOL_CACHE_MAX_SIZE > 0 */ /* increment stat now, adding in mempool always success */ __MEMPOOL_STAT_ADD(mp, put, n); -#if RTE_MEMPOOL_CACHE_MAX_SIZE > 0 /* cache is not enabled or single producer or non-EAL thread */ if (unlikely(cache_size == 0 || is_mp == 0 || lcore_id >= RTE_MAX_LCORE)) @@ -797,7 +681,6 @@ __mempool_put_bulk(struct rte_mempool *mp, void * const *obj_table, return; ring_enqueue: -#endif /* RTE_MEMPOOL_CACHE_MAX_SIZE > 0 */ /* push remaining objects in ring */ #ifdef RTE_LIBRTE_MEMPOOL_DEBUG @@ -941,7 +824,6 @@ __mempool_get_bulk(struct rte_mempool *mp, void **obj_table, unsigned n, int is_mc) { int ret; -#if RTE_MEMPOOL_CACHE_MAX_SIZE > 0 struct rte_mempool_cache *cache; uint32_t index, len; void **cache_objs; @@ -987,7 +869,6 @@ __mempool_get_bulk(struct rte_mempool *mp, void **obj_table, return 0; ring_dequeue: -#endif /* RTE_MEMPOOL_CACHE_MAX_SIZE > 0 */ /* get remaining objects from ring */ if (is_mc) @@ -1255,7 +1136,7 @@ rte_mempool_virt2phy(const struct rte_mempool *mp, const void *elt) uintptr_t off; off = (const char *)elt - (const char *)mp->elt_va_start; - return (mp->elt_pa[off >> mp->pg_shift] + (off & mp->pg_mask)); + return mp->elt_pa[off >> mp->pg_shift] + (off & mp->pg_mask); } else { /* * If huge pages are disabled, we cannot assume the @@ -1276,7 +1157,7 @@ rte_mempool_virt2phy(const struct rte_mempool *mp, const void *elt) * @param mp * A pointer to the mempool structure. */ -void rte_mempool_audit(const struct rte_mempool *mp); +void rte_mempool_audit(struct rte_mempool *mp); /** * Return a pointer to the private data in an mempool structure. @@ -1288,7 +1169,8 @@ void rte_mempool_audit(const struct rte_mempool *mp); */ static inline void *rte_mempool_get_priv(struct rte_mempool *mp) { - return (char *)mp + MEMPOOL_HEADER_SIZE(mp, mp->pg_num); + return (char *)mp + + MEMPOOL_HEADER_SIZE(mp, mp->pg_num, mp->cache_size); } /** @@ -1320,7 +1202,7 @@ struct rte_mempool *rte_mempool_lookup(const char *name); * calculates header, trailer, body and total sizes of the mempool object. * * @param elt_size - * The size of each element. + * The size of each element, without header and trailer. * @param flags * The flags used for the mempool creation. * Consult rte_mempool_create() for more information about possible values. @@ -1346,14 +1228,15 @@ uint32_t rte_mempool_calc_obj_size(uint32_t elt_size, uint32_t flags, * * @param elt_num * Number of elements. - * @param elt_sz - * The size of each element. + * @param total_elt_sz + * The size of each element, including header and trailer, as returned + * by rte_mempool_calc_obj_size(). * @param pg_shift * LOG2 of the physical pages size. * @return * Required memory size aligned at page boundary. */ -size_t rte_mempool_xmem_size(uint32_t elt_num, size_t elt_sz, +size_t rte_mempool_xmem_size(uint32_t elt_num, size_t total_elt_sz, uint32_t pg_shift); /** @@ -1367,8 +1250,9 @@ size_t rte_mempool_xmem_size(uint32_t elt_num, size_t elt_sz, * Will be used to store mempool objects. * @param elt_num * Number of elements. - * @param elt_sz - * The size of each element. + * @param total_elt_sz + * The size of each element, including header and trailer, as returned + * by rte_mempool_calc_obj_size(). * @param paddr * Array of physical addresses of the pages that comprises given memory * buffer. @@ -1382,8 +1266,9 @@ size_t rte_mempool_xmem_size(uint32_t elt_num, size_t elt_sz, * buffer is too small, return a negative value whose absolute value * is the actual number of elements that can be stored in that buffer. */ -ssize_t rte_mempool_xmem_usage(void *vaddr, uint32_t elt_num, size_t elt_sz, - const phys_addr_t paddr[], uint32_t pg_num, uint32_t pg_shift); +ssize_t rte_mempool_xmem_usage(void *vaddr, uint32_t elt_num, + size_t total_elt_sz, const phys_addr_t paddr[], uint32_t pg_num, + uint32_t pg_shift); /** * Walk list of all memory pools @@ -1393,7 +1278,7 @@ ssize_t rte_mempool_xmem_usage(void *vaddr, uint32_t elt_num, size_t elt_sz, * @param arg * Argument passed to iterator */ -void rte_mempool_walk(void (*func)(const struct rte_mempool *, void *arg), +void rte_mempool_walk(void (*func)(struct rte_mempool *, void *arg), void *arg); #ifdef __cplusplus