LCOV - code coverage report
Current view: top level - zephyr/sys - mem_blocks.h Hit Total Coverage
Test: new.info Lines: 18 19 94.7 %
Date: 2024-12-22 00:14:23

          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 1.14