From 1df93bc9830f1debeb9cc9672bd44d95441d0441 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Fri, 22 Aug 2025 13:42:08 +0200 Subject: [PATCH 1/6] alloc: add functions to use a private heap Add sof_heap_alloc() and sof_heap_free() to allocate and free memory on a private heap. Signed-off-by: Guennadi Liakhovetski --- zephyr/include/rtos/alloc.h | 4 ++++ zephyr/lib/alloc.c | 24 ++++++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/zephyr/include/rtos/alloc.h b/zephyr/include/rtos/alloc.h index 2738a0ac230b..fe984808b682 100644 --- a/zephyr/include/rtos/alloc.h +++ b/zephyr/include/rtos/alloc.h @@ -120,6 +120,10 @@ void rfree(void *ptr); */ void l3_heap_save(void); +void *sof_heap_alloc(struct k_heap *heap, uint32_t flags, size_t bytes, + size_t alignment); +void sof_heap_free(struct k_heap *heap, void *addr); + /* TODO: remove - debug only - only needed for linking */ static inline void heap_trace_all(int force) {} diff --git a/zephyr/lib/alloc.c b/zephyr/lib/alloc.c index 4ec1bcccfd77..255f5bfdcf98 100644 --- a/zephyr/lib/alloc.c +++ b/zephyr/lib/alloc.c @@ -609,6 +609,30 @@ void rfree(void *ptr) } EXPORT_SYMBOL(rfree); +/* + * To match the fall-back SOF main heap all private heaps should also be in the + * uncached address range. + */ +void *sof_heap_alloc(struct k_heap *heap, uint32_t flags, size_t bytes, + size_t alignment) +{ + if (!heap) + heap = &sof_heap; + + if (flags & SOF_MEM_FLAG_COHERENT) + return heap_alloc_aligned(heap, alignment, bytes); + + return (__sparse_force void *)heap_alloc_aligned_cached(heap, alignment, bytes); +} + +void sof_heap_free(struct k_heap *heap, void *addr) +{ + if (!heap) + heap = &sof_heap; + + heap_free(heap, addr); +} + static int heap_init(void) { sys_heap_init(&sof_heap.heap, heapmem, HEAPMEM_SIZE - SHARED_BUFFER_HEAP_MEM_SIZE); From 9b9132ea6899b7af1c4e5044bb05731c85510ed0 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Mon, 13 Oct 2025 13:45:18 +0200 Subject: [PATCH 2/6] module-adapter: fix wrong memory freeing Memory, allocated using the module_driver_heap_*() API, should be freed using module_driver_heap_free(), not rfree(). Signed-off-by: Guennadi Liakhovetski --- src/audio/module_adapter/module_adapter.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/audio/module_adapter/module_adapter.c b/src/audio/module_adapter/module_adapter.c index c5e6c75ca649..d0d1c2f6a48a 100644 --- a/src/audio/module_adapter/module_adapter.c +++ b/src/audio/module_adapter/module_adapter.c @@ -181,10 +181,10 @@ struct comp_dev *module_adapter_new_ext(const struct comp_driver *drv, err: #if CONFIG_IPC_MAJOR_4 if (mod) - rfree(mod->priv.cfg.input_pins); + module_driver_heap_free(drv->user_heap, mod->priv.cfg.input_pins); #endif - rfree(mod); - rfree(dev); + module_driver_heap_free(drv->user_heap, mod); + module_driver_heap_free(drv->user_heap, dev); return NULL; } EXPORT_SYMBOL(module_adapter_new); @@ -1283,12 +1283,12 @@ void module_adapter_free(struct comp_dev *dev) mod_free_all(mod); #if CONFIG_IPC_MAJOR_4 - rfree(mod->priv.cfg.input_pins); + module_driver_heap_free(dev->drv->user_heap, mod->priv.cfg.input_pins); #endif rfree(mod->stream_params); - rfree(mod); - rfree(dev); + module_driver_heap_free(dev->drv->user_heap, mod); + module_driver_heap_free(dev->drv->user_heap, dev); } EXPORT_SYMBOL(module_adapter_free); From a564dc5886aa8e76d6febb41ad5037371bd63271 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Mon, 13 Oct 2025 14:14:42 +0200 Subject: [PATCH 3/6] module-adapter: move allocating and freeing into functions Allocate and free memory for module and device objects and for input pins to separate functions to support varying allocation methods. Signed-off-by: Guennadi Liakhovetski --- src/audio/module_adapter/module_adapter.c | 95 ++++++++++++++--------- 1 file changed, 59 insertions(+), 36 deletions(-) diff --git a/src/audio/module_adapter/module_adapter.c b/src/audio/module_adapter/module_adapter.c index d0d1c2f6a48a..65ffd97ac18b 100644 --- a/src/audio/module_adapter/module_adapter.c +++ b/src/audio/module_adapter/module_adapter.c @@ -44,6 +44,56 @@ struct comp_dev *module_adapter_new(const struct comp_driver *drv, return module_adapter_new_ext(drv, config, spec, NULL); } +static struct processing_module *module_adapter_mem_alloc(const struct comp_driver *drv, + const struct comp_ipc_config *config) +{ + struct comp_dev *dev = comp_alloc(drv, sizeof(*dev)); + + if (!dev) { + comp_cl_err(drv, "failed to allocate memory for comp_dev"); + return NULL; + } + + /* allocate module information. + * for DP shared modules this struct must be accessible from all cores + * Unfortunately at this point there's no information of components the module + * will be bound to. So we need to allocate shared memory for each DP module + * To be removed when pipeline 2.0 is ready + */ + int flags = config->proc_domain == COMP_PROCESSING_DOMAIN_DP ? + SOF_MEM_FLAG_USER | SOF_MEM_FLAG_COHERENT : SOF_MEM_FLAG_USER; + + struct processing_module *mod = module_driver_heap_rzalloc(drv->user_heap, flags, + sizeof(*mod)); + + if (!mod) { + comp_err(dev, "failed to allocate memory for module"); + goto err; + } + + dev->ipc_config = *config; + mod->dev = dev; + dev->mod = mod; + + return mod; + +err: + module_driver_heap_free(drv->user_heap, dev); + + return NULL; +} + +static void module_adapter_mem_free(struct processing_module *mod) +{ + const struct comp_driver *drv = mod->dev->drv; + +#if CONFIG_IPC_MAJOR_4 + module_driver_heap_free(drv->user_heap, mod->priv.cfg.input_pins); +#endif + module_driver_heap_free(drv->user_heap, mod->dev); + module_driver_heap_free(drv->user_heap, mod); +} + /* * \brief Create a module adapter component. * \param[in] drv - component driver pointer. @@ -61,8 +111,6 @@ struct comp_dev *module_adapter_new_ext(const struct comp_driver *drv, void *mod_priv) { int ret; - struct comp_dev *dev; - struct processing_module *mod; struct module_config *dst; const struct module_interface *const interface = drv->adapter_ops; @@ -74,33 +122,16 @@ struct comp_dev *module_adapter_new_ext(const struct comp_driver *drv, return NULL; } - dev = comp_alloc(drv, sizeof(*dev)); - if (!dev) { - comp_cl_err(drv, "failed to allocate memory for comp_dev"); - return NULL; - } - dev->ipc_config = *config; - - /* allocate module information. - * for DP shared modules this struct must be accessible from all cores - * Unfortunately at this point there's no information of components the module - * will be bound to. So we need to allocate shared memory for each DP module - * To be removed when pipeline 2.0 is ready - */ - int flags = config->proc_domain == COMP_PROCESSING_DOMAIN_DP ? - SOF_MEM_FLAG_USER | SOF_MEM_FLAG_COHERENT : SOF_MEM_FLAG_USER; + struct processing_module *mod = module_adapter_mem_alloc(drv, config); - mod = module_driver_heap_rzalloc(drv->user_heap, flags, sizeof(*mod)); - if (!mod) { - comp_err(dev, "failed to allocate memory for module"); - goto err; - } + if (!mod) + return NULL; dst = &mod->priv.cfg; module_set_private_data(mod, mod_priv); - mod->dev = dev; - dev->mod = mod; + + struct comp_dev *dev = mod->dev; list_init(&mod->raw_data_buffers_list); @@ -178,13 +209,10 @@ struct comp_dev *module_adapter_new_ext(const struct comp_driver *drv, comp_dbg(dev, "done"); return dev; + err: -#if CONFIG_IPC_MAJOR_4 - if (mod) - module_driver_heap_free(drv->user_heap, mod->priv.cfg.input_pins); -#endif - module_driver_heap_free(drv->user_heap, mod); - module_driver_heap_free(drv->user_heap, dev); + module_adapter_mem_free(mod); + return NULL; } EXPORT_SYMBOL(module_adapter_new); @@ -1282,13 +1310,8 @@ void module_adapter_free(struct comp_dev *dev) mod_free_all(mod); -#if CONFIG_IPC_MAJOR_4 - module_driver_heap_free(dev->drv->user_heap, mod->priv.cfg.input_pins); -#endif - rfree(mod->stream_params); - module_driver_heap_free(dev->drv->user_heap, mod); - module_driver_heap_free(dev->drv->user_heap, dev); + module_adapter_mem_free(mod); } EXPORT_SYMBOL(module_adapter_free); From 90ef190740a71d4efe8fbfdbf4624b52bf415533 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 14 Oct 2025 15:49:59 +0200 Subject: [PATCH 4/6] platform: library: add k_heap* types and functions Add a definition of struct k_heap and SOF k_heap wrappers sof_heap_alloc() and sof_heap_free() for host native builds. Signed-off-by: Guennadi Liakhovetski --- posix/include/rtos/alloc.h | 8 ++++++++ posix/include/rtos/kernel.h | 4 ++++ src/lib/alloc.c | 11 +++++++++++ src/platform/library/lib/alloc.c | 11 +++++++++++ test/cmocka/src/common_mocks.c | 17 +++++++++++++++++ 5 files changed, 51 insertions(+) diff --git a/posix/include/rtos/alloc.h b/posix/include/rtos/alloc.h index 7dbf070259ff..195c1d64258f 100644 --- a/posix/include/rtos/alloc.h +++ b/posix/include/rtos/alloc.h @@ -131,6 +131,14 @@ void rfree(void *ptr); */ void *rzalloc_core_sys(int core, size_t bytes); +struct k_heap; +static inline void k_heap_init(struct k_heap *heap, void *mem, size_t bytes) +{ +} +void *sof_heap_alloc(struct k_heap *heap, uint32_t flags, size_t bytes, + size_t alignment); +void sof_heap_free(struct k_heap *heap, void *addr); + /** * Calculates length of the null-terminated string. * @param s String. diff --git a/posix/include/rtos/kernel.h b/posix/include/rtos/kernel.h index 5921d86b0012..714fc6672a1d 100644 --- a/posix/include/rtos/kernel.h +++ b/posix/include/rtos/kernel.h @@ -43,4 +43,8 @@ static inline void k_usleep(int32_t us) wait_delay_us(us); } +struct k_heap { + int unused; +}; + #endif /* __POSIX_RTOS_KERNEL_H__ */ diff --git a/src/lib/alloc.c b/src/lib/alloc.c index 7d07677c9a65..a6354fb0420f 100644 --- a/src/lib/alloc.c +++ b/src/lib/alloc.c @@ -71,3 +71,14 @@ int heap_info(int index, struct mm_info *out) return 0; } #endif + +void *sof_heap_alloc(struct k_heap *heap, uint32_t flags, size_t bytes, + size_t alignment) +{ + return malloc(bytes); +} + +void sof_heap_free(struct k_heap *heap, void *addr) +{ + free(addr); +} diff --git a/src/platform/library/lib/alloc.c b/src/platform/library/lib/alloc.c index 1a5b96b68d64..d733b58f8541 100644 --- a/src/platform/library/lib/alloc.c +++ b/src/platform/library/lib/alloc.c @@ -48,6 +48,17 @@ void *rbrealloc_align(void *ptr, uint32_t flags, size_t bytes, return realloc(ptr, bytes); } +void *sof_heap_alloc(struct k_heap *heap, uint32_t flags, size_t bytes, + size_t alignment) +{ + return malloc(bytes); +} + +void sof_heap_free(struct k_heap *heap, void *addr) +{ + free(addr); +} + void heap_trace(struct mm_heap *heap, int size) { #if MALLOC_DEBUG diff --git a/test/cmocka/src/common_mocks.c b/test/cmocka/src/common_mocks.c index fca1d6300656..f34c1f5d82e5 100644 --- a/test/cmocka/src/common_mocks.c +++ b/test/cmocka/src/common_mocks.c @@ -122,6 +122,23 @@ int WEAK mod_free(struct processing_module *mod, const void *ptr) return 0; } +void WEAK *sof_heap_alloc(struct k_heap *heap, uint32_t flags, size_t bytes, + size_t alignment) +{ + (void)heap; + (void)flags; + (void)alignment; + + return malloc(bytes); +} + +void WEAK sof_heap_free(struct k_heap *heap, void *addr) +{ + (void)heap; + + free(addr); +} + int WEAK memcpy_s(void *dest, size_t dest_size, const void *src, size_t count) { From 4fbcceffdef1249e3ee038b404f2b655a77af993 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Mon, 6 Oct 2025 11:53:32 +0200 Subject: [PATCH 5/6] module: add an allocation function with flags Add a new mod_alloc_ext() allocation function with support for allocator flags. Signed-off-by: Guennadi Liakhovetski --- src/audio/module_adapter/module/generic.c | 9 +++++---- .../sof/audio/module_adapter/module/generic.h | 17 ++++++++++++++++- test/cmocka/src/common_mocks.c | 4 +++- 3 files changed, 24 insertions(+), 6 deletions(-) diff --git a/src/audio/module_adapter/module/generic.c b/src/audio/module_adapter/module/generic.c index c4a5110c4b28..e9b5f9f8c20c 100644 --- a/src/audio/module_adapter/module/generic.c +++ b/src/audio/module_adapter/module/generic.c @@ -218,15 +218,16 @@ void *mod_balloc_align(struct processing_module *mod, size_t size, size_t alignm EXPORT_SYMBOL(mod_balloc_align); /** - * Allocates aligned memory block for module. + * Allocates aligned memory block with flags for module. * @param mod Pointer to the module this memory block is allocatd for. + * @param flags Allocator flags. * @param bytes Size in bytes. * @param alignment Alignment in bytes. * @return Pointer to the allocated memory or NULL if failed. * * The allocated memory is automatically freed when the module is unloaded. */ -void *mod_alloc_align(struct processing_module *mod, size_t size, size_t alignment) +void *mod_alloc_ext(struct processing_module *mod, uint32_t flags, size_t size, size_t alignment) { struct module_resources *res = &mod->priv.resources; struct module_resource *container; @@ -245,7 +246,7 @@ void *mod_alloc_align(struct processing_module *mod, size_t size, size_t alignme } /* Allocate memory for module */ - ptr = rmalloc_align(SOF_MEM_FLAG_USER, size, alignment); + ptr = rmalloc_align(flags, size, alignment); if (!ptr) { comp_err(mod->dev, "Failed to alloc %zu bytes %zu alignment for comp %#x.", @@ -265,7 +266,7 @@ void *mod_alloc_align(struct processing_module *mod, size_t size, size_t alignme return ptr; } -EXPORT_SYMBOL(mod_alloc_align); +EXPORT_SYMBOL(mod_alloc_ext); /** * Creates a blob handler and releases it when the module is unloaded diff --git a/src/include/sof/audio/module_adapter/module/generic.h b/src/include/sof/audio/module_adapter/module/generic.h index 7138da3a697a..c1e730893517 100644 --- a/src/include/sof/audio/module_adapter/module/generic.h +++ b/src/include/sof/audio/module_adapter/module/generic.h @@ -189,12 +189,27 @@ struct module_processing_data { int module_load_config(struct comp_dev *dev, const void *cfg, size_t size); int module_init(struct processing_module *mod); void *mod_balloc_align(struct processing_module *mod, size_t size, size_t alignment); +void *mod_alloc_ext(struct processing_module *mod, uint32_t flags, size_t size, size_t alignment); + +/** + * Allocates aligned memory block for module. + * @param mod Pointer to the module this memory block is allocated for. + * @param bytes Size in bytes. + * @param alignment Alignment in bytes. + * @return Pointer to the allocated memory or NULL if failed. + * + * The allocated memory is automatically freed when the module is unloaded. + */ +static inline void *mod_alloc_align(struct processing_module *mod, size_t size, size_t alignment) +{ + return mod_alloc_ext(mod, 0, size, alignment); +} + static inline void *mod_balloc(struct processing_module *mod, size_t size) { return mod_balloc_align(mod, size, 0); } -void *mod_alloc_align(struct processing_module *mod, size_t size, size_t alignment); static inline void *mod_alloc(struct processing_module *mod, size_t size) { return mod_alloc_align(mod, size, 0); diff --git a/test/cmocka/src/common_mocks.c b/test/cmocka/src/common_mocks.c index f34c1f5d82e5..ef996b8f3500 100644 --- a/test/cmocka/src/common_mocks.c +++ b/test/cmocka/src/common_mocks.c @@ -102,10 +102,12 @@ void WEAK *mod_balloc_align(struct processing_module *mod, size_t size, size_t a return ret; } -void WEAK *mod_alloc_align(struct processing_module *mod, size_t size, size_t alignment) +void WEAK *mod_alloc_ext(struct processing_module *mod, uint32_t flags, size_t size, + size_t alignment) { void *ret; (void)mod; + (void)flags; (void)alignment; ret = malloc(size); From aa4d87fe6c8ba106f15e0835f7f807550db46536 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 14 Oct 2025 17:31:07 +0200 Subject: [PATCH 6/6] audio: module-adapter: (cosmetic) fix two typos s/allocatd/allocated/ Signed-off-by: Guennadi Liakhovetski --- src/audio/module_adapter/module/generic.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/audio/module_adapter/module/generic.c b/src/audio/module_adapter/module/generic.c index e9b5f9f8c20c..0094a138a243 100644 --- a/src/audio/module_adapter/module/generic.c +++ b/src/audio/module_adapter/module/generic.c @@ -167,7 +167,7 @@ static void container_put(struct processing_module *mod, struct module_resource /** * Allocates aligned buffer memory block for module. - * @param mod Pointer to the module this memory block is allocatd for. + * @param mod Pointer to the module this memory block is allocated for. * @param bytes Size in bytes. * @param alignment Alignment in bytes. * @return Pointer to the allocated memory or NULL if failed. @@ -219,7 +219,7 @@ EXPORT_SYMBOL(mod_balloc_align); /** * Allocates aligned memory block with flags for module. - * @param mod Pointer to the module this memory block is allocatd for. + * @param mod Pointer to the module this memory block is allocated for. * @param flags Allocator flags. * @param bytes Size in bytes. * @param alignment Alignment in bytes.