This adds similar ability of sys_multi_heap to the memory blocks allocator, where a choice function can be used to select which allocator (of a group) is used for memory block allocation. Signed-off-by: Daniel Leung <daniel.leung@intel.com>
315 lines
9.5 KiB
C
315 lines
9.5 KiB
C
/*
|
|
* Copyright (c) 2021 Intel Corporation
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
/**
|
|
* @file
|
|
*
|
|
* @brief Memory Blocks Allocator
|
|
*/
|
|
|
|
#ifndef ZEPHYR_INCLUDE_SYS_MEM_BLOCKS_H_
|
|
#define ZEPHYR_INCLUDE_SYS_MEM_BLOCKS_H_
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
#include <stddef.h>
|
|
#include <stdint.h>
|
|
|
|
#include <kernel.h>
|
|
#include <math/ilog2.h>
|
|
#include <sys/bitarray.h>
|
|
|
|
#define MAX_MULTI_ALLOCATORS 8
|
|
|
|
/**
|
|
* @defgroup mem_blocks_apis Memory Blocks APIs
|
|
* @{
|
|
*/
|
|
|
|
/**
|
|
* @brief Memory Blocks Allocator
|
|
*/
|
|
struct sys_mem_blocks;
|
|
|
|
/**
|
|
* @brief Multi Memory Blocks Allocator
|
|
*/
|
|
struct sys_multi_mem_blocks;
|
|
|
|
/**
|
|
* @typedef sys_mem_blocks_t
|
|
*
|
|
* @brief Memory Blocks Allocator
|
|
*/
|
|
typedef struct sys_mem_blocks sys_mem_blocks_t;
|
|
|
|
/**
|
|
* @typedef sys_multi_mem_blocks_t
|
|
*
|
|
* @brief Multi Memory Blocks Allocator
|
|
*/
|
|
typedef struct sys_multi_mem_blocks sys_multi_mem_blocks_t;
|
|
|
|
/**
|
|
* @brief Multi memory blocks allocator choice function
|
|
*
|
|
* This is a user-provided functions whose responsibility is selecting
|
|
* a specific memory blocks allocator based on the opaque cfg value,
|
|
* which is specified by the user as an argument to
|
|
* sys_multi_mem_blocks_alloc(). The callback returns a pointer to
|
|
* the chosen allocator where the allocation is performed.
|
|
*
|
|
* NULL may be returned, which will cause the
|
|
* allocation to fail and a -EINVAL reported to the calling code.
|
|
*
|
|
* @param group Multi memory blocks allocator structure.
|
|
* @param cfg An opaque user-provided value. It may be interpreted in
|
|
* any way by the application.
|
|
*
|
|
* @return A pointer to the chosen allocator, or NULL if none is chosen.
|
|
*/
|
|
typedef sys_mem_blocks_t *(*sys_multi_mem_blocks_choice_fn_t)
|
|
(struct sys_multi_mem_blocks *group, void *cfg);
|
|
|
|
/**
|
|
* @cond INTERNAL_HIDDEN
|
|
*/
|
|
|
|
struct sys_mem_blocks {
|
|
/* Number of blocks */
|
|
uint32_t num_blocks;
|
|
|
|
/* Bit shift for block size */
|
|
uint8_t blk_sz_shift;
|
|
|
|
/* Memory block buffer */
|
|
uint8_t *buffer;
|
|
|
|
/* Bitmap of allocated blocks */
|
|
sys_bitarray_t *bitmap;
|
|
|
|
};
|
|
|
|
struct sys_multi_mem_blocks {
|
|
/* Number of allocators in this group */
|
|
int num_allocators;
|
|
sys_multi_mem_blocks_choice_fn_t choice_fn;
|
|
sys_mem_blocks_t *allocators[MAX_MULTI_ALLOCATORS];
|
|
};
|
|
|
|
/**
|
|
* @def _SYS_MEM_BLOCKS_DEFINE_WITH_EXT_BUF
|
|
*
|
|
* @brief Create a memory block object with a providing backing buffer.
|
|
*
|
|
* @param name Name of the memory block object.
|
|
* @param blk_sz Size of each memory block (in bytes, power of 2).
|
|
* @param num_blks Total number of memory blocks.
|
|
* @param buf Backing buffer of type uint8_t.
|
|
* @param mbmod Modifier to the memory block struct
|
|
*/
|
|
#define _SYS_MEM_BLOCKS_DEFINE_WITH_EXT_BUF(name, blk_sz, num_blks, buf, mbmod) \
|
|
_SYS_BITARRAY_DEFINE(_sys_mem_blocks_bitmap_##name, \
|
|
num_blks, mbmod); \
|
|
mbmod sys_mem_blocks_t name = { \
|
|
.num_blocks = num_blks, \
|
|
.blk_sz_shift = ilog2(blk_sz), \
|
|
.buffer = buf, \
|
|
.bitmap = &_sys_mem_blocks_bitmap_##name, \
|
|
}
|
|
|
|
/**
|
|
* @def _SYS_MEM_BLOCKS_DEFINE
|
|
*
|
|
* @brief Create a memory block object with a new backing buffer.
|
|
*
|
|
* @param name Name of the memory block object.
|
|
* @param blk_sz Size of each memory block (in bytes, power of 2).
|
|
* @param num_blks Total number of memory blocks.
|
|
* @param balign Alignment of the memory block buffer (power of 2).
|
|
* @param mbmod Modifier to the memory block struct
|
|
*/
|
|
#define _SYS_MEM_BLOCKS_DEFINE(name, blk_sz, num_blks, balign, mbmod) \
|
|
mbmod uint8_t __noinit_named(sys_mem_blocks_buf_##name) \
|
|
__aligned(WB_UP(balign)) \
|
|
_sys_mem_blocks_buf_##name[num_blks * WB_UP(blk_sz)]; \
|
|
_SYS_MEM_BLOCKS_DEFINE_WITH_EXT_BUF(name, blk_sz, num_blks, \
|
|
_sys_mem_blocks_buf_##name, \
|
|
mbmod);
|
|
|
|
/**
|
|
* INTERNAL_HIDDEN @endcond
|
|
*/
|
|
|
|
/**
|
|
* @def SYS_MEM_BLOCKS_DEFINE
|
|
*
|
|
* @brief Create a memory block object with a new backing buffer.
|
|
*
|
|
* @param name Name of the memory block object.
|
|
* @param blk_sz Size of each memory block (in bytes).
|
|
* @param num_blks Total number of memory blocks.
|
|
* @param buf_align Alignment of the memory block buffer (power of 2).
|
|
*/
|
|
#define SYS_MEM_BLOCKS_DEFINE(name, blk_sz, num_blks, buf_align) \
|
|
_SYS_MEM_BLOCKS_DEFINE(name, blk_sz, num_blks, buf_align,)
|
|
|
|
/**
|
|
* @def SYS_MEM_BLOCKS_DEFINE_STATIC
|
|
*
|
|
* @brief Create a static memory block object with a new backing buffer.
|
|
*
|
|
* @param name Name of the memory block object.
|
|
* @param blk_sz Size of each memory block (in bytes).
|
|
* @param num_blks Total number of memory blocks.
|
|
* @param buf_align Alignment of the memory block buffer (power of 2).
|
|
*/
|
|
#define SYS_MEM_BLOCKS_DEFINE_STATIC(name, blk_sz, num_blks, buf_align) \
|
|
_SYS_MEM_BLOCKS_DEFINE(name, blk_sz, num_blks, buf_align, static)
|
|
|
|
|
|
/**
|
|
* @def SYS_MEM_BLOCKS_DEFINE_WITH_EXT_BUF
|
|
*
|
|
* @brief Create a memory block object with a providing backing buffer.
|
|
*
|
|
* @param name Name of the memory block object.
|
|
* @param blk_sz Size of each memory block (in bytes).
|
|
* @param num_blks Total number of memory blocks.
|
|
* @param buf Backing buffer of type uint8_t.
|
|
*/
|
|
#define SYS_MEM_BLOCKS_DEFINE_WITH_EXT_BUF(name, blk_sz, num_blks, buf) \
|
|
_SYS_MEM_BLOCKS_DEFINE_WITH_EXT_BUF(name, blk_sz, num_blks, buf,)
|
|
|
|
/**
|
|
* @def SYS_MEM_BLOCKS_DEFINE_STATIC_WITH_EXT_BUF
|
|
*
|
|
* @brief Create a static memory block object with a providing backing buffer.
|
|
*
|
|
* @param name Name of the memory block object.
|
|
* @param blk_sz Size of each memory block (in bytes).
|
|
* @param num_blks Total number of memory blocks.
|
|
* @param buf Backing buffer of type uint8_t.
|
|
*/
|
|
#define SYS_MEM_BLOCKS_DEFINE_STATIC_WITH_EXT_BUF(name, blk_sz, num_blks, buf) \
|
|
_SYS_MEM_BLOCKS_DEFINE_WITH_EXT_BUF(name, blk_sz, num_blks, buf, static)
|
|
|
|
/**
|
|
* @brief Allocate multiple memory blocks
|
|
*
|
|
* Allocate multiple memory blocks, and place their pointers into
|
|
* the output array.
|
|
*
|
|
* @param[in] mem_block Pointer to memory block object.
|
|
* @param[in] count Number of blocks to allocate.
|
|
* @param[out] out_blocks Output array to be populated by pointers to
|
|
* the memory blocks. It must have at least
|
|
* @p count elements.
|
|
*
|
|
* @retval 0 Successful
|
|
* @retval -EINVAL Invalid argument supplied.
|
|
* @retval -ENOMEM Not enough blocks for allocation.
|
|
*/
|
|
int sys_mem_blocks_alloc(sys_mem_blocks_t *mem_block, size_t count,
|
|
void **out_blocks);
|
|
|
|
/**
|
|
* @brief Free multiple memory blocks
|
|
*
|
|
* Free multiple memory blocks according to the array of memory
|
|
* block pointers.
|
|
*
|
|
* @param[in] mem_block Pointer to memory block object.
|
|
* @param[in] count Number of blocks to free.
|
|
* @param[in] in_blocks Input array of pointers to the memory blocks.
|
|
*
|
|
* @retval 0 Successful
|
|
* @retval -EINVAL Invalid argument supplied.
|
|
* @retval -EFAULT Invalid pointers supplied.
|
|
*/
|
|
int sys_mem_blocks_free(sys_mem_blocks_t *mem_block, size_t count,
|
|
void **in_blocks);
|
|
|
|
/**
|
|
* @brief Initialize multi memory blocks allocator group
|
|
*
|
|
* Initialize a sys_multi_mem_block struct with the specified choice
|
|
* function. Note that individual allocator must be added later with
|
|
* sys_multi_mem_blocks_add_allocator.
|
|
*
|
|
* @param group Multi memory blocks allocator structure.
|
|
* @param choice_fn A sys_multi_mem_blocks_choice_fn_t callback used to
|
|
* select the allocator to be used at allocation time
|
|
*/
|
|
void sys_multi_mem_blocks_init(sys_multi_mem_blocks_t *group,
|
|
sys_multi_mem_blocks_choice_fn_t choice_fn);
|
|
|
|
/**
|
|
* @brief Add an allocator to an allocator group
|
|
*
|
|
* This adds a known allocator to an existing multi memory blocks
|
|
* allocator group.
|
|
*
|
|
* @param group Multi memory blocks allocator structure.
|
|
* @param alloc Allocator to add
|
|
*/
|
|
void sys_multi_mem_blocks_add_allocator(sys_multi_mem_blocks_t *group,
|
|
sys_mem_blocks_t *alloc);
|
|
|
|
/**
|
|
* @brief Allocate memory from multi memory blocks allocator group
|
|
*
|
|
* Just as for sys_mem_blocks_alloc(), allocates multiple blocks of
|
|
* memory. Takes an opaque configuration pointer passed to the choice
|
|
* function, which is used by integration code to choose an allocator.
|
|
*
|
|
* @param[in] group Multi memory blocks allocator structure.
|
|
* @param[in] cfg Opaque configuration parameter,
|
|
* as for sys_multi_mem_blocks_choice_fn_t
|
|
* @param[in] count Number of blocks to allocate
|
|
* @param[out] out_blocks Output array to be populated by pointers to
|
|
* the memory blocks. It must have at least
|
|
* @p count elements.
|
|
* @param[out] blk_size If not NULL, output the block size of
|
|
* the chosen allocator.
|
|
*
|
|
* @retval 0 Successful
|
|
* @retval -EINVAL Invalid argument supplied, or no allocator chosen.
|
|
* @retval -ENOMEM Not enough blocks for allocation.
|
|
*/
|
|
int sys_multi_mem_blocks_alloc(sys_multi_mem_blocks_t *group,
|
|
void *cfg, size_t count,
|
|
void **out_blocks,
|
|
size_t *blk_size);
|
|
|
|
/**
|
|
* @brief Free memory allocated from multi memory blocks allocator group
|
|
*
|
|
* Free previous allocated memory blocks from sys_multi_mem_blocks_alloc().
|
|
*
|
|
* Note that all blocks in @p in_blocks must be from the same allocator.
|
|
*
|
|
* @param[in] group Multi memory blocks allocator structure.
|
|
* @param[in] count Number of blocks to free.
|
|
* @param[in] in_blocks Input array of pointers to the memory blocks.
|
|
*
|
|
* @retval 0 Successful
|
|
* @retval -EINVAL Invalid argument supplied, or no allocator chosen.
|
|
* @retval -EFAULT Invalid pointer(s) supplied.
|
|
*/
|
|
int sys_multi_mem_blocks_free(sys_multi_mem_blocks_t *group,
|
|
size_t count, void **in_blocks);
|
|
|
|
/** @} */
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif /* ZEPHYR_INCLUDE_SYS_MEM_BLOCKS_H_ */
|