LCOV - code coverage report
Current view: top level - zephyr/sys - mem_blocks.h Coverage Total Hit
Test: new.info Lines: 94.7 % 19 18
Test Date: 2025-09-05 20:47:19

            Line data    Source code
       1            1 : /*
       2              :  * Copyright (c) 2021 Intel Corporation
       3              :  *
       4              :  * SPDX-License-Identifier: Apache-2.0
       5              :  */
       6              : 
       7              : /**
       8              :  * @file
       9              :  *
      10              :  * @brief Memory Blocks Allocator
      11              :  */
      12              : 
      13              : #ifndef ZEPHYR_INCLUDE_SYS_MEM_BLOCKS_H_
      14              : #define ZEPHYR_INCLUDE_SYS_MEM_BLOCKS_H_
      15              : 
      16              : #ifdef __cplusplus
      17              : extern "C" {
      18              : #endif
      19              : 
      20              : #include <stddef.h>
      21              : #include <stdint.h>
      22              : 
      23              : #include <zephyr/kernel.h>
      24              : #include <zephyr/math/ilog2.h>
      25              : #include <zephyr/sys/bitarray.h>
      26              : #include <zephyr/sys/mem_stats.h>
      27              : 
      28            0 : #define MAX_MULTI_ALLOCATORS 8
      29              : 
      30              : /**
      31              :  * @defgroup mem_blocks_apis Memory Blocks APIs
      32              :  * @ingroup memory_management
      33              :  * @{
      34              :  */
      35              : 
      36              : /**
      37              :  * @brief Memory Blocks Allocator
      38              :  */
      39              : struct sys_mem_blocks;
      40              : 
      41              : /**
      42              :  * @brief Multi Memory Blocks Allocator
      43              :  */
      44              : struct sys_multi_mem_blocks;
      45              : 
      46              : /**
      47              :  * @typedef sys_mem_blocks_t
      48              :  *
      49              :  * @brief Memory Blocks Allocator
      50              :  */
      51            1 : typedef struct sys_mem_blocks sys_mem_blocks_t;
      52              : 
      53              : /**
      54              :  * @typedef sys_multi_mem_blocks_t
      55              :  *
      56              :  * @brief Multi Memory Blocks Allocator
      57              :  */
      58            1 : typedef struct sys_multi_mem_blocks sys_multi_mem_blocks_t;
      59              : 
      60              : /**
      61              :  * @brief Multi memory blocks allocator choice function
      62              :  *
      63              :  * This is a user-provided functions whose responsibility is selecting
      64              :  * a specific memory blocks allocator based on the opaque cfg value,
      65              :  * which is specified by the user as an argument to
      66              :  * sys_multi_mem_blocks_alloc(). The callback returns a pointer to
      67              :  * the chosen allocator where the allocation is performed.
      68              :  *
      69              :  * NULL may be returned, which will cause the
      70              :  * allocation to fail and a -EINVAL reported to the calling code.
      71              :  *
      72              :  * @param group Multi memory blocks allocator structure.
      73              :  * @param cfg   An opaque user-provided value. It may be interpreted in
      74              :  *              any way by the application.
      75              :  *
      76              :  * @return A pointer to the chosen allocator, or NULL if none is chosen.
      77              :  */
      78            1 : typedef sys_mem_blocks_t *(*sys_multi_mem_blocks_choice_fn_t)
      79              :         (struct sys_multi_mem_blocks *group, void *cfg);
      80              : 
      81              : /**
      82              :  * @cond INTERNAL_HIDDEN
      83              :  */
      84              : 
      85              : struct sys_mem_blocks_info {
      86              :         uint32_t num_blocks;       /* Total number of blocks */
      87              :         uint8_t  blk_sz_shift;     /* Bit shift for block size */
      88              : #ifdef CONFIG_SYS_MEM_BLOCKS_RUNTIME_STATS
      89              :         uint32_t used_blocks;      /* Current number of blocks in use */
      90              :         uint32_t max_used_blocks;  /* Maximum number of blocks in use */
      91              : #endif
      92              : };
      93              : 
      94              : struct sys_mem_blocks {
      95              :         struct sys_mem_blocks_info  info;
      96              : 
      97              :         /* Memory block buffer */
      98              :         uint8_t *buffer;
      99              : 
     100              :         /* Bitmap of allocated blocks */
     101              :         sys_bitarray_t *bitmap;
     102              : 
     103              : #ifdef CONFIG_SYS_MEM_BLOCKS_RUNTIME_STATS
     104              :         /* Spinlock guarding access to memory block internals */
     105              :         struct k_spinlock  lock;
     106              : #endif
     107              : #ifdef CONFIG_OBJ_CORE_SYS_MEM_BLOCKS
     108              :         struct k_obj_core obj_core;
     109              : #endif
     110              : };
     111              : 
     112              : struct sys_multi_mem_blocks {
     113              :         /* Number of allocators in this group */
     114              :         int num_allocators;
     115              :         sys_multi_mem_blocks_choice_fn_t choice_fn;
     116              :         sys_mem_blocks_t *allocators[MAX_MULTI_ALLOCATORS];
     117              : };
     118              : 
     119              : /**
     120              :  * @brief Create a memory block object with a providing backing buffer.
     121              :  *
     122              :  * @param name     Name of the memory block object.
     123              :  * @param blk_sz   Size of each memory block (in bytes, power of 2).
     124              :  * @param num_blks Total number of memory blocks.
     125              :  * @param buf      Backing buffer of type uint8_t.
     126              :  * @param mbmod    Modifier to the memory block struct
     127              :  */
     128              : #define _SYS_MEM_BLOCKS_DEFINE_WITH_EXT_BUF(name, blk_sz, num_blks, buf, mbmod) \
     129              :         _SYS_BITARRAY_DEFINE(_sys_mem_blocks_bitmap_##name,             \
     130              :                              num_blks, mbmod);                          \
     131              :         mbmod struct sys_mem_blocks name = {                            \
     132              :                 .info = {num_blks, ilog2(blk_sz)},                      \
     133              :                 .buffer = buf,                                          \
     134              :                 .bitmap = &_sys_mem_blocks_bitmap_##name,           \
     135              :         };                                                              \
     136              :         STRUCT_SECTION_ITERABLE_ALTERNATE(sys_mem_blocks_ptr,           \
     137              :                                           sys_mem_blocks *,             \
     138              :                                           __##name##_ptr) = &name;      \
     139              :         LINKER_KEEP(__##name##_ptr);
     140              : 
     141              : /**
     142              :  * @brief Create a memory block object with a new backing buffer.
     143              :  *
     144              :  * @param name     Name of the memory block object.
     145              :  * @param blk_sz   Size of each memory block (in bytes, power of 2).
     146              :  * @param num_blks Total number of memory blocks.
     147              :  * @param balign   Alignment of the memory block buffer (power of 2).
     148              :  * @param mbmod    Modifier to the memory block struct
     149              :  */
     150              : #define _SYS_MEM_BLOCKS_DEFINE(name, blk_sz, num_blks, balign, mbmod)   \
     151              :         mbmod uint8_t __noinit_named(sys_mem_blocks_buf_##name)         \
     152              :                 __aligned(WB_UP(balign))                                \
     153              :                 _sys_mem_blocks_buf_##name[num_blks * WB_UP(blk_sz)];   \
     154              :         _SYS_MEM_BLOCKS_DEFINE_WITH_EXT_BUF(name, blk_sz, num_blks,     \
     155              :                                            _sys_mem_blocks_buf_##name,  \
     156              :                                            mbmod);
     157              : 
     158              : /**
     159              :  * INTERNAL_HIDDEN @endcond
     160              :  */
     161              : 
     162              : /**
     163              :  * @brief Create a memory block object with a new backing buffer.
     164              :  *
     165              :  * @param name      Name of the memory block object.
     166              :  * @param blk_sz    Size of each memory block (in bytes).
     167              :  * @param num_blks  Total number of memory blocks.
     168              :  * @param buf_align Alignment of the memory block buffer (power of 2).
     169              :  */
     170            1 : #define SYS_MEM_BLOCKS_DEFINE(name, blk_sz, num_blks, buf_align) \
     171              :         _SYS_MEM_BLOCKS_DEFINE(name, blk_sz, num_blks, buf_align,)
     172              : 
     173              : /**
     174              :  * @brief Create a static memory block object with a new backing buffer.
     175              :  *
     176              :  * @param name      Name of the memory block object.
     177              :  * @param blk_sz    Size of each memory block (in bytes).
     178              :  * @param num_blks  Total number of memory blocks.
     179              :  * @param buf_align Alignment of the memory block buffer (power of 2).
     180              :  */
     181            1 : #define SYS_MEM_BLOCKS_DEFINE_STATIC(name, blk_sz, num_blks, buf_align) \
     182              :         _SYS_MEM_BLOCKS_DEFINE(name, blk_sz, num_blks, buf_align, static)
     183              : 
     184              : 
     185              : /**
     186              :  * @brief Create a memory block object with a providing backing buffer.
     187              :  *
     188              :  * @param name     Name of the memory block object.
     189              :  * @param blk_sz   Size of each memory block (in bytes).
     190              :  * @param num_blks Total number of memory blocks.
     191              :  * @param buf      Backing buffer of type uint8_t.
     192              :  */
     193            1 : #define SYS_MEM_BLOCKS_DEFINE_WITH_EXT_BUF(name, blk_sz, num_blks, buf) \
     194              :         _SYS_MEM_BLOCKS_DEFINE_WITH_EXT_BUF(name, blk_sz, num_blks, buf,)
     195              : 
     196              : /**
     197              :  * @brief Create a static memory block object with a providing backing buffer.
     198              :  *
     199              :  * @param name     Name of the memory block object.
     200              :  * @param blk_sz   Size of each memory block (in bytes).
     201              :  * @param num_blks Total number of memory blocks.
     202              :  * @param buf      Backing buffer of type uint8_t.
     203              :  */
     204            1 : #define SYS_MEM_BLOCKS_DEFINE_STATIC_WITH_EXT_BUF(name, blk_sz, num_blks, buf) \
     205              :         _SYS_MEM_BLOCKS_DEFINE_WITH_EXT_BUF(name, blk_sz, num_blks, buf, static)
     206              : 
     207              : /**
     208              :  * @brief Allocate multiple memory blocks
     209              :  *
     210              :  * Allocate multiple memory blocks, and place their pointers into
     211              :  * the output array.
     212              :  *
     213              :  * @param[in]  mem_block  Pointer to memory block object.
     214              :  * @param[in]  count      Number of blocks to allocate.
     215              :  * @param[out] out_blocks Output array to be populated by pointers to
     216              :  *                        the memory blocks. It must have at least
     217              :  *                        @p count elements.
     218              :  *
     219              :  * @retval 0       Successful
     220              :  * @retval -EINVAL Invalid argument supplied.
     221              :  * @retval -ENOMEM Not enough blocks for allocation.
     222              :  */
     223            1 : int sys_mem_blocks_alloc(sys_mem_blocks_t *mem_block, size_t count,
     224              :                          void **out_blocks);
     225              : 
     226              : /**
     227              :  * @brief Allocate a contiguous set of memory blocks
     228              :  *
     229              :  * Allocate multiple memory blocks, and place their pointers into
     230              :  * the output array.
     231              :  *
     232              :  * @param[in]  mem_block Pointer to memory block object.
     233              :  * @param[in]  count     Number of blocks to allocate.
     234              :  * @param[out] out_block Output pointer to the start of the allocated block set
     235              :  *
     236              :  * @retval 0       Successful
     237              :  * @retval -EINVAL Invalid argument supplied.
     238              :  * @retval -ENOMEM Not enough contiguous blocks for allocation.
     239              :  */
     240            1 : int sys_mem_blocks_alloc_contiguous(sys_mem_blocks_t *mem_block, size_t count,
     241              :                                    void **out_block);
     242              : 
     243              : /**
     244              :  * @brief Force allocation of a specified blocks in a memory block object
     245              :  *
     246              :  * Allocate a specified blocks in a memory block object.
     247              :  * Note: use caution when mixing sys_mem_blocks_get and sys_mem_blocks_alloc,
     248              :  * allocation may take any of the free memory space
     249              :  *
     250              :  *
     251              :  * @param[in]  mem_block  Pointer to memory block object.
     252              :  * @param[in]  in_block   Address of the first required block to allocate
     253              :  * @param[in]  count      Number of blocks to allocate.
     254              :  *
     255              :  * @retval 0       Successful
     256              :  * @retval -EINVAL Invalid argument supplied.
     257              :  * @retval -ENOMEM Some of blocks are taken and cannot be allocated
     258              :  */
     259            1 : int sys_mem_blocks_get(sys_mem_blocks_t *mem_block, void *in_block, size_t count);
     260              : 
     261              : /**
     262              :  * @brief check if the region is free
     263              :  *
     264              :  * @param[in]  mem_block  Pointer to memory block object.
     265              :  * @param[in]  in_block   Address of the first block to check
     266              :  * @param[in]  count      Number of blocks to check.
     267              :  *
     268              :  * @retval 1 All memory blocks are free
     269              :  * @retval 0 At least one of the memory blocks is taken
     270              :  */
     271            1 : int sys_mem_blocks_is_region_free(sys_mem_blocks_t *mem_block, void *in_block, size_t count);
     272              : 
     273              : /**
     274              :  * @brief Free multiple memory blocks
     275              :  *
     276              :  * Free multiple memory blocks according to the array of memory
     277              :  * block pointers.
     278              :  *
     279              :  * @param[in] mem_block Pointer to memory block object.
     280              :  * @param[in] count     Number of blocks to free.
     281              :  * @param[in] in_blocks Input array of pointers to the memory blocks.
     282              :  *
     283              :  * @retval 0       Successful
     284              :  * @retval -EINVAL Invalid argument supplied.
     285              :  * @retval -EFAULT Invalid pointers supplied.
     286              :  */
     287            1 : int sys_mem_blocks_free(sys_mem_blocks_t *mem_block, size_t count,
     288              :                         void **in_blocks);
     289              : 
     290              : /**
     291              :  * @brief Free contiguous multiple memory blocks
     292              :  *
     293              :  * Free contiguous multiple memory blocks
     294              :  *
     295              :  * @param[in] mem_block Pointer to memory block object.
     296              :  * @param[in] block     Pointer to the first memory block
     297              :  * @param[in] count     Number of blocks to free.
     298              :  *
     299              :  * @retval 0       Successful
     300              :  * @retval -EINVAL Invalid argument supplied.
     301              :  * @retval -EFAULT Invalid pointer supplied.
     302              :  */
     303            1 : int sys_mem_blocks_free_contiguous(sys_mem_blocks_t *mem_block, void *block, size_t count);
     304              : 
     305              : #ifdef CONFIG_SYS_MEM_BLOCKS_RUNTIME_STATS
     306              : /**
     307              :  * @brief Get the runtime statistics of a memory block
     308              :  *
     309              :  * This function retrieves the runtime stats for the specified memory block
     310              :  * @a mem_block and copies it into the memory pointed to by @a stats.
     311              :  *
     312              :  * @param mem_block Pointer to system memory block
     313              :  * @param stats Pointer to struct to copy statistics into
     314              :  *
     315              :  * @return -EINVAL if NULL pointer was passed, otherwise 0
     316              :  */
     317              : int sys_mem_blocks_runtime_stats_get(sys_mem_blocks_t *mem_block,
     318              :                                      struct sys_memory_stats *stats);
     319              : 
     320              : /**
     321              :  * @brief Reset the maximum memory block usage
     322              :  *
     323              :  * This routine resets the maximum memory usage in the specified memory
     324              :  * block @a mem_block to match that block's current memory usage.
     325              :  *
     326              :  * @param mem_block Pointer to system memory block
     327              :  *
     328              :  * @return -EINVAL if NULL pointer was passed, otherwise 0
     329              :  */
     330              : int sys_mem_blocks_runtime_stats_reset_max(sys_mem_blocks_t *mem_block);
     331              : #endif
     332              : 
     333              : /**
     334              :  * @brief Initialize multi memory blocks allocator group
     335              :  *
     336              :  * Initialize a sys_multi_mem_block struct with the specified choice
     337              :  * function. Note that individual allocator must be added later with
     338              :  * sys_multi_mem_blocks_add_allocator.
     339              :  *
     340              :  * @param group     Multi memory blocks allocator structure.
     341              :  * @param choice_fn A sys_multi_mem_blocks_choice_fn_t callback used to
     342              :  *                  select the allocator to be used at allocation time
     343              :  */
     344            1 : void sys_multi_mem_blocks_init(sys_multi_mem_blocks_t *group,
     345              :                                sys_multi_mem_blocks_choice_fn_t choice_fn);
     346              : 
     347              : /**
     348              :  * @brief Add an allocator to an allocator group
     349              :  *
     350              :  * This adds a known allocator to an existing multi memory blocks
     351              :  * allocator group.
     352              :  *
     353              :  * @param group Multi memory blocks allocator structure.
     354              :  * @param alloc Allocator to add
     355              :  */
     356            1 : void sys_multi_mem_blocks_add_allocator(sys_multi_mem_blocks_t *group,
     357              :                                         sys_mem_blocks_t *alloc);
     358              : 
     359              : /**
     360              :  * @brief Allocate memory from multi memory blocks allocator group
     361              :  *
     362              :  * Just as for sys_mem_blocks_alloc(), allocates multiple blocks of
     363              :  * memory. Takes an opaque configuration pointer passed to the choice
     364              :  * function, which is used by integration code to choose an allocator.
     365              :  *
     366              :  * @param[in]  group      Multi memory blocks allocator structure.
     367              :  * @param[in]  cfg        Opaque configuration parameter,
     368              :  *                        as for sys_multi_mem_blocks_choice_fn_t
     369              :  * @param[in]  count      Number of blocks to allocate
     370              :  * @param[out] out_blocks Output array to be populated by pointers to
     371              :  *                        the memory blocks. It must have at least
     372              :  *                        @p count elements.
     373              :  * @param[out] blk_size   If not NULL, output the block size of
     374              :  *                        the chosen allocator.
     375              :  *
     376              :  * @retval 0       Successful
     377              :  * @retval -EINVAL Invalid argument supplied, or no allocator chosen.
     378              :  * @retval -ENOMEM Not enough blocks for allocation.
     379              :  */
     380            1 : int sys_multi_mem_blocks_alloc(sys_multi_mem_blocks_t *group,
     381              :                                void *cfg, size_t count,
     382              :                                void **out_blocks,
     383              :                                size_t *blk_size);
     384              : 
     385              : /**
     386              :  * @brief Free memory allocated from multi memory blocks allocator group
     387              :  *
     388              :  * Free previous allocated memory blocks from sys_multi_mem_blocks_alloc().
     389              :  *
     390              :  * Note that all blocks in @p in_blocks must be from the same allocator.
     391              :  *
     392              :  * @param[in] group     Multi memory blocks allocator structure.
     393              :  * @param[in] count     Number of blocks to free.
     394              :  * @param[in] in_blocks Input array of pointers to the memory blocks.
     395              :  *
     396              :  * @retval 0       Successful
     397              :  * @retval -EINVAL Invalid argument supplied, or no allocator chosen.
     398              :  * @retval -EFAULT Invalid pointer(s) supplied.
     399              :  */
     400            1 : int sys_multi_mem_blocks_free(sys_multi_mem_blocks_t *group,
     401              :                               size_t count, void **in_blocks);
     402              : 
     403              : /** @} */
     404              : 
     405              : #ifdef __cplusplus
     406              : }
     407              : #endif
     408              : 
     409              : #endif /* ZEPHYR_INCLUDE_SYS_MEM_BLOCKS_H_ */
        

Generated by: LCOV version 2.0-1