From 3c47f91be4f879c9f1eac4c2be0a1bdd2de426ff Mon Sep 17 00:00:00 2001 From: Victor Brzeski Date: Fri, 20 Jun 2025 16:16:01 -0700 Subject: [PATCH] include: kernel: add macros to enable allocation from specific sections This change adds two macros that allow the user to specify the section the memslab buffer should be allocated from. This is useful for systems where memory must reside in DMA-able memory like USB. Signed-off-by: Victor Brzeski --- include/zephyr/kernel.h | 84 +++++++++++++++++++++++++++++++++-------- 1 file changed, 69 insertions(+), 15 deletions(-) diff --git a/include/zephyr/kernel.h b/include/zephyr/kernel.h index dc8f1fb130d..614b2eab1b9 100644 --- a/include/zephyr/kernel.h +++ b/include/zephyr/kernel.h @@ -5456,6 +5456,41 @@ struct k_mem_slab { * @{ */ +/** + * @brief Statically define and initialize a memory slab in a user-provided memory section with + * public (non-static) scope. + * + * The memory slab's buffer contains @a slab_num_blocks memory blocks + * that are @a slab_block_size bytes long. The buffer is aligned to a + * @a slab_align -byte boundary. To ensure that each memory block is similarly + * aligned to this boundary, @a slab_block_size must also be a multiple of + * @a slab_align. + * + * The memory slab can be accessed outside the module where it is defined + * using: + * + * @code extern struct k_mem_slab ; @endcode + * + * @note This macro cannot be used together with a static keyword. + * If such a use-case is desired, use @ref K_MEM_SLAB_DEFINE_IN_SECT_STATIC + * instead. + * + * @param name Name of the memory slab. + * @param in_section Section attribute specifier such as Z_GENERIC_SECTION. + * @param slab_block_size Size of each memory block (in bytes). + * @param slab_num_blocks Number memory blocks. + * @param slab_align Alignment of the memory slab's buffer (power of 2). + */ +#define K_MEM_SLAB_DEFINE_IN_SECT(name, in_section, slab_block_size, slab_num_blocks, slab_align) \ + BUILD_ASSERT(((slab_block_size) % (slab_align)) == 0, \ + "slab_block_size must be a multiple of slab_align"); \ + BUILD_ASSERT((((slab_align) & ((slab_align) - 1)) == 0), \ + "slab_align must be a power of 2"); \ + char in_section __aligned(WB_UP( \ + slab_align)) _k_mem_slab_buf_##name[(slab_num_blocks) * WB_UP(slab_block_size)]; \ + STRUCT_SECTION_ITERABLE(k_mem_slab, name) = Z_MEM_SLAB_INITIALIZER( \ + name, _k_mem_slab_buf_##name, WB_UP(slab_block_size), slab_num_blocks) + /** * @brief Statically define and initialize a memory slab in a public (non-static) scope. * @@ -5479,13 +5514,36 @@ struct k_mem_slab { * @param slab_num_blocks Number memory blocks. * @param slab_align Alignment of the memory slab's buffer (power of 2). */ -#define K_MEM_SLAB_DEFINE(name, slab_block_size, slab_num_blocks, slab_align) \ - char __noinit_named(k_mem_slab_buf_##name) \ - __aligned(WB_UP(slab_align)) \ - _k_mem_slab_buf_##name[(slab_num_blocks) * WB_UP(slab_block_size)]; \ - STRUCT_SECTION_ITERABLE(k_mem_slab, name) = \ - Z_MEM_SLAB_INITIALIZER(name, _k_mem_slab_buf_##name, \ - WB_UP(slab_block_size), slab_num_blocks) +#define K_MEM_SLAB_DEFINE(name, slab_block_size, slab_num_blocks, slab_align) \ + K_MEM_SLAB_DEFINE_IN_SECT(name, __noinit_named(k_mem_slab_buf_##name), slab_block_size, \ + slab_num_blocks, slab_align) + +/** + * @brief Statically define and initialize a memory slab in a user-provided memory section with + * private (static) scope. + * + * The memory slab's buffer contains @a slab_num_blocks memory blocks + * that are @a slab_block_size bytes long. The buffer is aligned to a + * @a slab_align -byte boundary. To ensure that each memory block is similarly + * aligned to this boundary, @a slab_block_size must also be a multiple of + * @a slab_align. + * + * @param name Name of the memory slab. + * @param in_section Section attribute specifier such as Z_GENERIC_SECTION. + * @param slab_block_size Size of each memory block (in bytes). + * @param slab_num_blocks Number memory blocks. + * @param slab_align Alignment of the memory slab's buffer (power of 2). + */ +#define K_MEM_SLAB_DEFINE_IN_SECT_STATIC(name, in_section, slab_block_size, slab_num_blocks, \ + slab_align) \ + BUILD_ASSERT(((slab_block_size) % (slab_align)) == 0, \ + "slab_block_size must be a multiple of slab_align"); \ + BUILD_ASSERT((((slab_align) & ((slab_align) - 1)) == 0), \ + "slab_align must be a power of 2"); \ + static char in_section __aligned(WB_UP( \ + slab_align)) _k_mem_slab_buf_##name[(slab_num_blocks) * WB_UP(slab_block_size)]; \ + static STRUCT_SECTION_ITERABLE(k_mem_slab, name) = Z_MEM_SLAB_INITIALIZER( \ + name, _k_mem_slab_buf_##name, WB_UP(slab_block_size), slab_num_blocks) /** * @brief Statically define and initialize a memory slab in a private (static) scope. @@ -5501,13 +5559,9 @@ struct k_mem_slab { * @param slab_num_blocks Number memory blocks. * @param slab_align Alignment of the memory slab's buffer (power of 2). */ -#define K_MEM_SLAB_DEFINE_STATIC(name, slab_block_size, slab_num_blocks, slab_align) \ - static char __noinit_named(k_mem_slab_buf_##name) \ - __aligned(WB_UP(slab_align)) \ - _k_mem_slab_buf_##name[(slab_num_blocks) * WB_UP(slab_block_size)]; \ - static STRUCT_SECTION_ITERABLE(k_mem_slab, name) = \ - Z_MEM_SLAB_INITIALIZER(name, _k_mem_slab_buf_##name, \ - WB_UP(slab_block_size), slab_num_blocks) +#define K_MEM_SLAB_DEFINE_STATIC(name, slab_block_size, slab_num_blocks, slab_align) \ + K_MEM_SLAB_DEFINE_IN_SECT_STATIC(name, __noinit_named(k_mem_slab_buf_##name), \ + slab_block_size, slab_num_blocks, slab_align) /** * @brief Initialize a memory slab. @@ -5806,7 +5860,7 @@ void k_heap_free(struct k_heap *h, void *mem) __attribute_nonnull(1); * * @param name Symbol name for the struct k_heap object * @param bytes Size of memory region, in bytes - * @param in_section __attribute__((section(name)) + * @param in_section Section attribute specifier such as Z_GENERIC_SECTION. */ #define Z_HEAP_DEFINE_IN_SECT(name, bytes, in_section) \ char in_section \