From 8756fe121f2f5eb295cff1643503f14d8b0e879b Mon Sep 17 00:00:00 2001 From: Jan Musial Date: Mon, 8 Mar 2021 10:21:22 +0100 Subject: [PATCH] Add mpools to POSIX env Signed-off-by: Jan Musial --- env/posix/ocf_env.h | 4 ++ env/posix/utils_mpool.c | 146 ++++++++++++++++++++++++++++++++++++++++ env/posix/utils_mpool.h | 91 +++++++++++++++++++++++++ 3 files changed, 241 insertions(+) create mode 100644 env/posix/utils_mpool.c create mode 100644 env/posix/utils_mpool.h diff --git a/env/posix/ocf_env.h b/env/posix/ocf_env.h index 5294989..2434efa 100644 --- a/env/posix/ocf_env.h +++ b/env/posix/ocf_env.h @@ -34,6 +34,7 @@ #include "ocf_env_list.h" #include "ocf_env_headers.h" #include "ocf/ocf_err.h" +#include "utils_mpool.h" /* linux sector 512-bytes */ #define ENV_SECTOR_SHIFT 9 @@ -201,6 +202,9 @@ typedef struct _env_allocator env_allocator; env_allocator *env_allocator_create(uint32_t size, const char *fmt_name, ...); +#define env_allocator_create_extended(size, fmt_name, limit) \ + env_allocator_create(size, fmt_name) + void env_allocator_destroy(env_allocator *allocator); void *env_allocator_new(env_allocator *allocator); diff --git a/env/posix/utils_mpool.c b/env/posix/utils_mpool.c new file mode 100644 index 0000000..2b04304 --- /dev/null +++ b/env/posix/utils_mpool.c @@ -0,0 +1,146 @@ +/* + * Copyright(c) 2012-2021 Intel Corporation + * SPDX-License-Identifier: BSD-3-Clause-Clear + */ + +#include "utils_mpool.h" +#include "ocf_env.h" + +struct env_mpool { + int mpool_max; + /*!< Max mpool allocation order */ + + env_allocator *allocator[env_mpool_max]; + /*!< OS handle to memory pool */ + + uint32_t hdr_size; + /*!< Data header size (constant allocation part) */ + + uint32_t elem_size; + /*!< Per element size increment (variable allocation part) */ + + bool fallback; + /*!< Should mpool fallback to vmalloc */ + + int flags; + /*!< Allocation flags */ +}; + +struct env_mpool *env_mpool_create(uint32_t hdr_size, uint32_t elem_size, + int flags, int mpool_max, bool fallback, + const uint32_t limits[env_mpool_max], + const char *name_perfix) +{ + uint32_t i; + char name[MPOOL_ALLOCATOR_NAME_MAX] = { '\0' }; + int result; + struct env_mpool *mpool; + size_t size; + + mpool = env_zalloc(sizeof(*mpool), ENV_MEM_NORMAL); + if (!mpool) + return NULL; + + mpool->flags = flags; + mpool->fallback = fallback; + mpool->mpool_max = mpool_max; + mpool->hdr_size = hdr_size; + mpool->elem_size = elem_size; + + for (i = 0; i < min(env_mpool_max, mpool_max + 1); i++) { + result = snprintf(name, sizeof(name), "%s_%u", name_perfix, + (1 << i)); + if (result < 0 || result >= sizeof(name)) + goto err; + + size = hdr_size + (elem_size * (1 << i)); + + mpool->allocator[i] = env_allocator_create_extended( + size, name, limits ? limits[i] : -1); + + if (!mpool->allocator[i]) + goto err; + } + + return mpool; + +err: + env_mpool_destroy(mpool); + return NULL; +} + +void env_mpool_destroy(struct env_mpool *mallocator) +{ + if (mallocator) { + uint32_t i; + + for (i = 0; i < env_mpool_max; i++) + if (mallocator->allocator[i]) + env_allocator_destroy(mallocator->allocator[i]); + + env_free(mallocator); + } +} + +static env_allocator *env_mpool_get_allocator( + struct env_mpool *mallocator, uint32_t count) +{ + unsigned int idx; + + if (unlikely(count == 0)) + return env_mpool_1; + + idx = 31 - __builtin_clz(count); + + if (__builtin_ffs(count) <= idx) + idx++; + + if (idx >= env_mpool_max || idx > mallocator->mpool_max) + return NULL; + + return mallocator->allocator[idx]; +} + +void *env_mpool_new_f(struct env_mpool *mpool, uint32_t count, int flags) +{ + void *items = NULL; + env_allocator *allocator; + size_t size = mpool->hdr_size + (mpool->elem_size * count); + + allocator = env_mpool_get_allocator(mpool, count); + + if (allocator) { + items = env_allocator_new(allocator); + } else if(mpool->fallback) { + items = env_zalloc(size, 0); + } + +#ifdef ZERO_OR_NULL_PTR + if (ZERO_OR_NULL_PTR(items)) + return NULL; +#endif + + return items; +} + +void *env_mpool_new(struct env_mpool *mpool, uint32_t count) +{ + return env_mpool_new_f(mpool, count, mpool->flags); +} + +bool env_mpool_del(struct env_mpool *mpool, + void *items, uint32_t count) +{ + env_allocator *allocator; + + allocator = env_mpool_get_allocator(mpool, count); + + if (allocator) + env_allocator_del(allocator, items); + else if (mpool->fallback) + env_free(items); + else + return false; + + return true; +} diff --git a/env/posix/utils_mpool.h b/env/posix/utils_mpool.h new file mode 100644 index 0000000..00c7ff5 --- /dev/null +++ b/env/posix/utils_mpool.h @@ -0,0 +1,91 @@ +/* + * Copyright(c) 2012-2021 Intel Corporation + * SPDX-License-Identifier: BSD-3-Clause-Clear + */ + +#ifndef UTILS_MPOOL_H_ +#define UTILS_MPOOL_H_ + +#include +#include + +#define MPOOL_ALLOCATOR_NAME_MAX 128 + +enum { + env_mpool_1, + env_mpool_2, + env_mpool_4, + env_mpool_8, + env_mpool_16, + env_mpool_32, + env_mpool_64, + env_mpool_128, + + env_mpool_max +}; + +struct env_mpool; + +/** + * @brief Create CAS memory pool + * + * @param hdr_size size of constant allocation part + * @param elem_size size increment for each element + * @param flags Allocation flags + * @param mpool_max Maximal allocator size (power of two) + * @param fallback Should allocations fall back to vmalloc if allocator fails + * @param limits Array of rpool preallocation limits per each mpool allocation + * order or NULL if defaults are to be used. Array should have + * mpool_max elements + * @param name_prefix Format name prefix + * + * @return CAS memory pool + */ +struct env_mpool *env_mpool_create(uint32_t hdr_size, uint32_t elem_size, + int flags, int mpool_max, bool fallback, + const uint32_t limits[env_mpool_max], + const char *name_perfix); + +/** + * @brief Destroy existing memory pool + * + * @param mpool memory pool + */ +void env_mpool_destroy(struct env_mpool *mpool); + +/** + * @brief Allocate new items of memory pool + * + * @note Allocation based on ATOMIC memory pool and this function can be called + * when IRQ disable + * + * @param mpool CAS memory pool reference + * @param count Count of elements to be allocated + * + * @return Pointer to the new items + */ +void *env_mpool_new(struct env_mpool *mpool, uint32_t count); + +/** + * @brief Allocate new items of memory pool with specified allocation flag + * + * @param mpool CAS memory pool reference + * @param count Count of elements to be allocated + * @param flags Kernel allocation falgs + * + * @return Pointer to the new items + */ +void *env_mpool_new_f(struct env_mpool *mpool, uint32_t count, int flags); + +/** + * @brief Free existing items of memory pool + * + * @param mpool CAS memory pool reference + * @param items Items to be freed + * @param count - Count of elements to be free + * + * @return Allocation was freed + */ +bool env_mpool_del(struct env_mpool *mpool, void *items, uint32_t count); + +#endif /* UTILS_MPOOL_H_ */