/* * Copyright (C) Mellanox Technologies Ltd. 2018. ALL RIGHTS RESERVED. * See file LICENSE for terms. */ #ifndef UCS_STRIDED_ALLOC_H_ #define UCS_STRIDED_ALLOC_H_ #include "queue_types.h" #include #include #include #include BEGIN_C_DECLS /** @file strided_alloc.h */ /* the distance between allocated elements */ #define UCS_STRIDED_ALLOC_STRIDE (128 * UCS_KBYTE) /** * Get a pointer to another element in the strided object * * Example with stride_count=3: * * chunk * start -+ * | * | * | <-- 128 kB --> . <-- 128 kB --> . * | . . * \/ . . * +--------+-- ... --+--------+-- ... --+--------+ * | stride | | stride | | stride | * obj0: | elem 0 | | elem 1 | | elem 2 | * | (base) | | | | | * +--------+-- ... --+--------+-- ... --+--------+ * +--------+-- ... --+--------+-- ... --+--------+ * | stride | | stride | | stride | * obj1: | elem 0 | | elem 1 | | elem 2 | * | (base) | | | | | * +--------+-- ... -+--------+-- ... --+--------+ * +--------+-- ... --+--------+-- ... --+--------+ * | stride | | stride | | stride | * obj2: | elem 0 | | elem 1 | | elem 2 | * | (base) | | | | | * +--------+-- ... -+--------+-- ... --+--------+ * * ... * * @param _elem Pointer to the current element * @param _stride_idx Stride index of the current element * @param _wanted_idx Stride index of the desired element * * @return Pointer to the desired element */ #define ucs_strided_elem_get(_elem, _stride_idx, _wanted_idx) \ UCS_PTR_BYTE_OFFSET(_elem, (ptrdiff_t)UCS_STRIDED_ALLOC_STRIDE * \ ((ptrdiff_t)(_wanted_idx) - (ptrdiff_t)(_stride_idx))) /* Forward declaration, used internally */ typedef struct ucs_strided_alloc_elem ucs_strided_alloc_elem_t; /** * Strided allocator - allows allocating objects which are split to several * memory areas with a constant stride (gap) in-between. * This improves the cache locality when the first memory area is used mostly. */ typedef struct ucs_strided_alloc { ucs_strided_alloc_elem_t *freelist; /* LIFO of free elements */ ucs_queue_head_t chunks; /* Queue of allocated chunks */ size_t elem_size; /* Size of a single memory area */ unsigned stride_count; /* Number of strides */ unsigned inuse_count; /* Number of allocated elements */ } ucs_strided_alloc_t; /** * Initialize the split allocator context * * @param [in] sa Strided allocator structure to initialize * @param [in] elem_size Size of a single stride element * @param [in] stride_count How many memory strides per object */ void ucs_strided_alloc_init(ucs_strided_alloc_t *sa, size_t elem_size, unsigned stride_count); /** * Cleanup the split allocator context * * @param [in] sa Strided allocator structure to cleanup */ void ucs_strided_alloc_cleanup(ucs_strided_alloc_t *sa); /** * Allocate an object * * @param [in] sa Strided allocator to allocate on * @param [in] alloc_name Debug name of the allocation * * @return Pointer to the first stride of the allocated object. */ void* ucs_strided_alloc_get(ucs_strided_alloc_t *sa, const char *alloc_name); /** * Release an object * * @param [in] sa Strided allocator to release the object to * @param [in] base Pointer to the first stride of the object to release */ void ucs_strided_alloc_put(ucs_strided_alloc_t *sa, void *base); /** * Get the number of currently allocated objects * * @param [in] sa Strided allocator to get the information for * * @return Number of currently allocated objects */ unsigned ucs_strided_alloc_inuse_count(ucs_strided_alloc_t *sa); END_C_DECLS #endif