blob: 1eebc1c150ee09ffa5d3af819579a276a3061c70 [file] [log] [blame]
/* Copyright (c) 2021 Intel Corporation
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef ZEPHYR_INCLUDE_SYS_MULTI_HEAP_H_
#define ZEPHYR_INCLUDE_SYS_MULTI_HEAP_H_
#include <zephyr/types.h>
#define MAX_MULTI_HEAPS 8
/**
* @brief Multi-heap allocator
*
* A sys_multi_heap represents a single allocator made from multiple,
* separately managed pools of memory that must be accessed via a
* unified API. They can be discontiguous, and in many cases will be
* expected to have different capabilities (for example: latency,
* cacheability, cpu affinity, etc...)
*
* Allocation from the multiheap provides an opaque "configuration"
* value to specify requirements and heuristics to assist the choice
* in backend, which is then provided to a user-specified "choice"
* function whose job it is to select a heap based on information in
* the config specifier and runtime state (heap full state, etc...)
*/
struct sys_multi_heap;
/**
* @brief Multi-heap choice function
*
* This is a user-provided functions whose responsibility is selecting
* a specific sys_heap backend based on the opaque cfg value, which is
* specified by the user as an argument to sys_multi_heap_alloc(), and
* performing the allocation on behalf of the caller. The callback is
* free to choose any registered heap backend to perform the
* allocation, and may choose to pad the user-provided values as
* needed, and to use an aligned allocation where required by the
* specified configuration.
*
* NULL may be returned, which will cause the
* allocation to fail and a NULL reported to the calling code.
*
* @param mheap Multi-heap structure.
* @param cfg An opaque user-provided value. It may be interpreted in
* any way by the application
* @param align Alignment of requested memory (or zero for no alignment)
* @param size The user-specified allocation size in bytes
* @return A pointer to the allocated memory
*/
typedef void *(*sys_multi_heap_fn_t)(struct sys_multi_heap *mheap, void *cfg,
size_t align, size_t size);
struct sys_multi_heap_rec {
struct sys_heap *heap;
void *user_data;
};
struct sys_multi_heap {
int nheaps;
sys_multi_heap_fn_t choice;
struct sys_multi_heap_rec heaps[MAX_MULTI_HEAPS];
};
/**
* @brief Initialize multi-heap
*
* Initialize a sys_multi_heap struct with the specified choice
* function. Note that individual heaps must be added later with
* sys_multi_heap_add_heap so that the heap bounds can be tracked by
* the multi heap code.
*
* @note In general a multiheap is likely to be instantiated
* semi-statically from system configuration (for example, via
* linker-provided bounds on available memory in different regions, or
* from devicetree definitions of hardware-provided addressable
* memory, etc...). The general expectation is that a soc- or
* board-level platform device will be initialized at system boot from
* these upstream configuration sources and not that an application
* will assemble a multi-heap on its own.
*
* @param heap A sys_multi_heap to initialize
* @param choice_fn A sys_multi_heap_fn_t callback used to select
* heaps at allocation time
*/
void sys_multi_heap_init(struct sys_multi_heap *heap,
sys_multi_heap_fn_t choice_fn);
/**
* @brief Add sys_heap to multi heap
*
* This adds a known sys_heap backend to an existing multi heap,
* allowing the multi heap internals to track the bounds of the heap
* and determine which heap (if any) from which a freed block was
* allocated.
*
* @param mheap A sys_multi_heap to which to add a heap
* @param heap The heap to add
* @param user_data pointer to any data for the heap
*/
void sys_multi_heap_add_heap(struct sys_multi_heap *mheap, struct sys_heap *heap, void *user_data);
/**
* @brief Allocate memory from multi heap
*
* Just as for sys_heap_alloc(), allocates a block of memory of the
* specified size in bytes. Takes an opaque configuration pointer
* passed to the multi heap choice function, which is used by
* integration code to choose a heap backend.
*
* @param mheap Multi heap pointer
* @param cfg Opaque configuration parameter, as for sys_multi_heap_fn_t
* @param bytes Requested size of the allocation, in bytes
* @return A valid pointer to heap memory, or NULL if no memory is available
*/
void *sys_multi_heap_alloc(struct sys_multi_heap *mheap, void *cfg, size_t bytes);
/**
* @brief Allocate aligned memory from multi heap
*
* Just as for sys_multi_heap_alloc(), allocates a block of memory of
* the specified size in bytes. Takes an additional parameter
* specifying a power of two alignment, in bytes.
*
* @param mheap Multi heap pointer
* @param cfg Opaque configuration parameter, as for sys_multi_heap_fn_t
* @param align Power of two alignment for the returned pointer, in bytes
* @param bytes Requested size of the allocation, in bytes
* @return A valid pointer to heap memory, or NULL if no memory is available
*/
void *sys_multi_heap_aligned_alloc(struct sys_multi_heap *mheap,
void *cfg, size_t align, size_t bytes);
/**
* @brief Get a specific heap for provided address
*
* Finds a single system heap (with user_data)
* controlling the provided pointer
*
* @param mheap Multi heap pointer
* @param addr address to be found, must be a pointer to a block allocated by sys_multi_heap_alloc
* @return 0 multi_heap_rec pointer to a structure to be filled with return data
* or NULL if the heap has not been found
*/
const struct sys_multi_heap_rec *sys_multi_heap_get_heap(const struct sys_multi_heap *mheap,
void *addr);
/**
* @brief Free memory allocated from multi heap
*
* Returns the specified block, which must be the return value of a
* previously successful sys_multi_heap_alloc() or
* sys_multi_heap_aligned_alloc() call, to the heap backend from which
* it was allocated.
*
* Accepts NULL as a block parameter, which is specified to have no
* effect.
*
* @param mheap Multi heap pointer
* @param block Block to free, must be a pointer to a block allocated by sys_multi_heap_alloc
*/
void sys_multi_heap_free(struct sys_multi_heap *mheap, void *block);
#endif /* ZEPHYR_INCLUDE_SYS_MULTI_HEAP_H_ */