1.. _sys_mem_blocks: 2 3Memory Blocks Allocator 4####################### 5 6The Memory Blocks Allocator allows memory blocks to be dynamically 7allocated from a designated memory region, where: 8 9* All memory blocks have a single fixed size. 10 11* Multiple blocks can be allocated or freed at the same time. 12 13* A group of blocks allocated together may not be contiguous. 14 This is useful for operations such as scatter-gather DMA transfers. 15 16* Bookkeeping of allocated blocks is done outside of the associated 17 buffer (unlike memory slab). This allows the buffer to reside in 18 memory regions where these can be powered down to conserve energy. 19 20.. contents:: 21 :local: 22 :depth: 2 23 24Concepts 25******** 26 27Any number of Memory Blocks Allocator can be defined (limited only by 28available RAM). Each allocator is referenced by its memory address. 29 30A memory blocks allocator has the following key properties: 31 32* The **block size** of each block, measured in bytes. 33 It must be at least 4N bytes long, where N is greater than 0. 34 35* The **number of blocks** available for allocation. 36 It must be greater than zero. 37 38* A **buffer** that provides the memory for the memory slab's blocks. 39 It must be at least "block size" times "number of blocks" bytes long. 40 41* A **blocks bitmap** to keep track of which block has been allocated. 42 43The buffer must be aligned to an N-byte boundary, where N is a power of 2 44larger than 2 (i.e. 4, 8, 16, ...). To ensure that all memory blocks in 45the buffer are similarly aligned to this boundary, the block size must 46also be a multiple of N. 47 48Due to the use of internal bookkeeping structures and their creation, 49each memory blocks allocator must be declared and defined at compile time. 50 51Internal Operation 52================== 53 54Each buffer associated with an allocator is an array of fixed-size blocks, 55with no wasted space between the blocks. 56 57The memory blocks allocator keeps track of unallocated blocks using 58a bitmap. 59 60Memory Blocks Allocator 61*********************** 62 63Internally, the memory blocks allocator uses a bitmap to keep track of 64which blocks have been allocated. Each allocator, utilizing 65the ``sys_bitarray`` interface, gets memory blocks one by one from 66the backing buffer up to the requested number of blocks. 67All the metadata about an allocator is stored outside of the backing 68buffer. This allows the memory region of the backing buffer to be 69powered down to conserve energy, as the allocator code never touches 70the content of the buffer. 71 72Multi Memory Blocks Allocator Group 73*********************************** 74 75The Multi Memory Blocks Allocator Group utility functions provide 76a convenient to manage a group of allocators. A custom allocator 77choosing function is used to choose which allocator to use among 78this group. 79 80An allocator group should be initialized at runtime via 81:c:func:`sys_multi_mem_blocks_init`. Each allocator can then be 82added via :c:func:`sys_multi_mem_blocks_add_allocator`. 83 84To allocate memory blocks from group, 85:c:func:`sys_multi_mem_blocks_alloc` is called with an opaque 86"configuration" parameter. This parameter is passed directly to 87the allocator choosing function so that an appropriate allocator 88can be chosen. After an allocator is chosen, memory blocks are 89allocated via :c:func:`sys_mem_blocks_alloc`. 90 91Allocated memory blocks can be freed via 92:c:func:`sys_multi_mem_blocks_free`. The caller does not need to 93pass a configuration parameter. The allocator code matches 94the passed in memory addresses to find the correct allocator 95and then memory blocks are freed via :c:func:`sys_mem_blocks_free`. 96 97Usage 98***** 99 100Defining a Memory Blocks Allocator 101================================== 102 103A memory blocks allocator is defined using a variable of type 104:c:type:`sys_mem_blocks_t`. It needs to be defined and initialized 105at compile time by calling :c:macro:`SYS_MEM_BLOCKS_DEFINE`. 106 107The following code defines and initializes a memory blocks allocator 108which has 4 blocks that are 64 bytes long, each of which is aligned 109to a 4-byte boundary: 110 111.. code-block:: c 112 113 SYS_MEM_BLOCKS_DEFINE(allocator, 64, 4, 4); 114 115Similarly, you can define a memory blocks allocator in private scope: 116 117.. code-block:: c 118 119 SYS_MEM_BLOCKS_DEFINE_STATIC(static_allocator, 64, 4, 4); 120 121A pre-defined buffer can also be provided to the allocator where 122the buffer can be placed separately. Note that the alignment of 123the buffer needs to be done at its definition. 124 125.. code-block:: c 126 127 uint8_t __aligned(4) backing_buffer[64 * 4]; 128 SYS_MEM_BLOCKS_DEFINE_WITH_EXT_BUF(allocator, 64, 4, backing_buffer); 129 130Allocating Memory Blocks 131======================== 132 133Memory blocks can be allocated by calling :c:func:`sys_mem_blocks_alloc`. 134 135.. code-block:: c 136 137 int ret; 138 uintptr_t blocks[2]; 139 140 ret = sys_mem_blocks_alloc(allocator, 2, blocks); 141 142If ``ret == 0``, the array ``blocks`` will contain an array of memory 143addresses pointing to the allocated blocks. 144 145Releasing a Memory Block 146======================== 147 148Memory blocks are released by calling :c:func:`sys_mem_blocks_free`. 149 150The following code builds on the example above which allocates 2 memory blocks, 151then releases them once they are no longer needed. 152 153.. code-block:: c 154 155 int ret; 156 uintptr_t blocks[2]; 157 158 ret = sys_mem_blocks_alloc(allocator, 2, blocks); 159 ... /* perform some operations on the allocated memory blocks */ 160 ret = sys_mem_blocks_free(allocator, 2, blocks); 161 162Using Multi Memory Blocks Allocator Group 163========================================= 164 165The following code demonstrates how to initialize an allocator group: 166 167.. code-block:: c 168 169 sys_mem_blocks_t *choice_fn(struct sys_multi_mem_blocks *group, void *cfg) 170 { 171 ... 172 } 173 174 SYS_MEM_BLOCKS_DEFINE(allocator0, 64, 4, 4); 175 SYS_MEM_BLOCKS_DEFINE(allocator1, 64, 4, 4); 176 177 static sys_multi_mem_blocks_t alloc_group; 178 179 sys_multi_mem_blocks_init(&alloc_group, choice_fn); 180 sys_multi_mem_blocks_add_allocator(&alloc_group, &allocator0); 181 sys_multi_mem_blocks_add_allocator(&alloc_group, &allocator1); 182 183To allocate and free memory blocks from the group: 184 185.. code-block:: c 186 187 int ret; 188 uintptr_t blocks[1]; 189 size_t blk_size; 190 191 ret = sys_multi_mem_blocks_alloc(&alloc_group, UINT_TO_POINTER(0), 192 1, blocks, &blk_size); 193 194 ret = sys_multi_mem_blocks_free(&alloc_group, 1, blocks); 195 196API Reference 197************* 198 199.. doxygengroup:: mem_blocks_apis 200