From 1dad57f47b5e49a277543f0b6b9a3b1b507b99c9 Mon Sep 17 00:00:00 2001 From: Jyri Sarha Date: Mon, 11 Aug 2025 01:30:13 +0300 Subject: [PATCH 01/18] modules: Allocate memory containers in chunks Do not allocate module memory containers one by one, but allocate them in chunks. The bookkeeping of allocated resources is done using containers that are allocated from heap. This effectively doubles the amount of heap allocations. This is not very efficient especially since the containers are only 20 bytes in size. This commit changes the allocation of containers so that they are always allocated in chunks of 16 containers, or what is selected with MODULE_MEMORY_API_CONTAINER_CHUNK_SIZE Kconfig option. The unused containers are not freed when the associated resource is freed. Instead the unused containers are kept in free containers list. All the containers are freed when mod_free_all() is called, for instance when the module unloads. Signed-off-by: Jyri Sarha --- src/audio/module_adapter/Kconfig | 10 +++ src/audio/module_adapter/module/generic.c | 89 ++++++++++++++----- src/audio/module_adapter/module_adapter.c | 3 +- src/include/module/module/base.h | 2 +- .../sof/audio/module_adapter/module/generic.h | 14 ++- 5 files changed, 92 insertions(+), 26 deletions(-) diff --git a/src/audio/module_adapter/Kconfig b/src/audio/module_adapter/Kconfig index bb9081812271..ad7f879d7049 100644 --- a/src/audio/module_adapter/Kconfig +++ b/src/audio/module_adapter/Kconfig @@ -3,6 +3,16 @@ menu "Processing modules" visible if COMP_MODULE_ADAPTER + config MODULE_MEMORY_API_CONTAINER_CHUNK_SIZE + int "Number of memory containers to allocate at once" + default 16 + help + The per module resource containers are allocated in + chunks. The unused containers are kept in free + list. When the free list is empty the amount of + containers to allocate at once is selected by this + config option. + config CADENCE_CODEC bool "Cadence codec" default n diff --git a/src/audio/module_adapter/module/generic.c b/src/audio/module_adapter/module/generic.c index 03a345552f71..b78f27059e13 100644 --- a/src/audio/module_adapter/module/generic.c +++ b/src/audio/module_adapter/module/generic.c @@ -92,7 +92,9 @@ int module_init(struct processing_module *mod) } /* Init memory list */ - list_init(&md->memory.mem_list); + list_init(&md->resources.mem_list); + list_init(&md->resources.free_cont_list); + list_init(&md->resources.cont_chunk_list); /* Now we can proceed with module specific initialization */ ret = interface->init(mod); @@ -110,6 +112,42 @@ int module_init(struct processing_module *mod) return 0; } +struct container_chunk { + struct list_item chunk_list; + struct module_memory containers[CONFIG_MODULE_MEMORY_API_CONTAINER_CHUNK_SIZE]; +}; + +static struct module_memory *container_get(struct processing_module *mod) +{ + struct module_resources *res = &mod->priv.resources; + struct module_memory *container; + + if (list_is_empty(&res->free_cont_list)) { + struct container_chunk *chunk = rzalloc(SOF_MEM_FLAG_USER, sizeof(*chunk)); + int i; + + if (!chunk) { + comp_err(mod->dev, "allocating more containers failed"); + return NULL; + } + + list_item_append(&chunk->chunk_list, &res->cont_chunk_list); + for (i = 0; i < ARRAY_SIZE(chunk->containers); i++) + list_item_append(&chunk->containers[i].mem_list, &res->free_cont_list); + } + + container = list_first_item(&res->free_cont_list, struct module_memory, mem_list); + list_item_del(&container->mem_list); + return container; +} + +static void container_put(struct processing_module *mod, struct module_memory *container) +{ + struct module_resources *res = &mod->priv.resources; + + list_item_append(&container->mem_list, &res->free_cont_list); +} + /** * Allocates aligned memory block for module. * @param mod Pointer to the module this memory block is allocatd for. @@ -121,20 +159,16 @@ int module_init(struct processing_module *mod) */ void *mod_alloc_align(struct processing_module *mod, uint32_t size, uint32_t alignment) { - struct comp_dev *dev = mod->dev; - struct module_memory *container; + struct module_memory *container = container_get(mod); + struct module_resources *res = &mod->priv.resources; void *ptr; - if (!size) { - comp_err(dev, "mod_alloc: requested allocation of 0 bytes."); + if (!container) return NULL; - } - /* Allocate memory container */ - container = rzalloc(SOF_MEM_FLAG_USER, - sizeof(struct module_memory)); - if (!container) { - comp_err(dev, "mod_alloc: failed to allocate memory container."); + if (!size) { + comp_err(mod->dev, "mod_alloc: requested allocation of 0 bytes."); + container_put(mod, container); return NULL; } @@ -145,15 +179,15 @@ void *mod_alloc_align(struct processing_module *mod, uint32_t size, uint32_t ali ptr = rballoc(SOF_MEM_FLAG_USER, size); if (!ptr) { - comp_err(dev, "mod_alloc: failed to allocate memory for comp %x.", - dev_comp_id(dev)); - rfree(container); + comp_err(mod->dev, "mod_alloc: failed to allocate memory for comp %x.", + dev_comp_id(mod->dev)); + container_put(mod, container); return NULL; } /* Store reference to allocated memory */ container->ptr = ptr; container->size = size; - list_item_prepend(&container->mem_list, &mod->priv.memory.mem_list); + list_item_prepend(&container->mem_list, &res->mem_list); return ptr; } @@ -200,6 +234,7 @@ EXPORT_SYMBOL(mod_zalloc); */ int mod_free(struct processing_module *mod, void *ptr) { + struct module_resources *res = &mod->priv.resources; struct module_memory *mem; struct list_item *mem_list; struct list_item *_mem_list; @@ -208,12 +243,12 @@ int mod_free(struct processing_module *mod, void *ptr) return 0; /* Find which container keeps this memory */ - list_for_item_safe(mem_list, _mem_list, &mod->priv.memory.mem_list) { + list_for_item_safe(mem_list, _mem_list, &res->mem_list) { mem = container_of(mem_list, struct module_memory, mem_list); if (mem->ptr == ptr) { rfree(mem->ptr); list_item_del(&mem->mem_list); - rfree(mem); + container_put(mod, mem); return 0; } } @@ -403,16 +438,24 @@ int module_reset(struct processing_module *mod) */ void mod_free_all(struct processing_module *mod) { - struct module_memory *mem; - struct list_item *mem_list; - struct list_item *_mem_list; + struct module_resources *res = &mod->priv.resources; + struct list_item *list; + struct list_item *_list; /* Find which container keeps this memory */ - list_for_item_safe(mem_list, _mem_list, &mod->priv.memory.mem_list) { - mem = container_of(mem_list, struct module_memory, mem_list); + list_for_item_safe(list, _list, &res->mem_list) { + struct module_memory *mem = container_of(list, struct module_memory, mem_list); + rfree(mem->ptr); list_item_del(&mem->mem_list); - rfree(mem); + } + + list_for_item_safe(list, _list, &res->cont_chunk_list) { + struct container_chunk *chunk = + container_of(list, struct container_chunk, chunk_list); + + list_item_del(&chunk->chunk_list); + rfree(chunk); } } EXPORT_SYMBOL(mod_free_all); diff --git a/src/audio/module_adapter/module_adapter.c b/src/audio/module_adapter/module_adapter.c index 8b649cfe18c3..0b42a5ae278d 100644 --- a/src/audio/module_adapter/module_adapter.c +++ b/src/audio/module_adapter/module_adapter.c @@ -1292,10 +1292,11 @@ EXPORT_SYMBOL(module_adapter_free); size_t module_adapter_heap_usage(struct processing_module *mod) { + struct module_resources *res = &mod->priv.resources; struct list_item *mem_list, *_mem_list; size_t size = 0; - list_for_item_safe(mem_list, _mem_list, &mod->priv.memory.mem_list) { + list_for_item_safe(mem_list, _mem_list, &res->mem_list) { struct module_memory *mem = container_of(mem_list, struct module_memory, mem_list); size += mem->size; diff --git a/src/include/module/module/base.h b/src/include/module/module/base.h index 2371d77124f5..881e74a2d108 100644 --- a/src/include/module/module/base.h +++ b/src/include/module/module/base.h @@ -59,7 +59,7 @@ struct module_data { enum module_state state; size_t new_cfg_size; /**< size of new module config data */ void *runtime_params; - struct module_memory memory; /**< memory allocated by module */ + struct module_resources resources; /**< resources allocated by module */ struct module_processing_data mpd; /**< shared data comp <-> module */ #endif /* SOF_MODULE_PRIVATE */ }; diff --git a/src/include/sof/audio/module_adapter/module/generic.h b/src/include/sof/audio/module_adapter/module/generic.h index 1001c4ba450c..c63f98dbd9c2 100644 --- a/src/include/sof/audio/module_adapter/module/generic.h +++ b/src/include/sof/audio/module_adapter/module/generic.h @@ -117,7 +117,19 @@ struct module_param { /** * \struct module_memory - * \brief module memory block - used for every memory allocated by module + * \brief module resources block - used for module allocation records + * The allocations are recorded so that they can be automatically freed + * when the module unloads. + */ +struct module_resources { + struct list_item mem_list; /**< Allocad memory containers */ + struct list_item free_cont_list; /**< Unused memory containers */ + struct list_item cont_chunk_list; /**< Memory container chunks */ +}; + +/** + * \struct module_memory + * \brief module memory container - used for every memory allocated by module */ struct module_memory { void *ptr; /**< A pointr to particular memory block */ From e4ddd219165ef4b97010b54a2c91d554e5af2d04 Mon Sep 17 00:00:00 2001 From: Jyri Sarha Date: Tue, 12 Aug 2025 00:16:13 +0300 Subject: [PATCH 02/18] modules: Add high water mark to module_adapter_heap_usage() Add heap usage high water mark to module_adapter_heap_usage() and shell's "sof module_heap_usage" command. Signed-off-by: Jyri Sarha --- src/audio/module_adapter/module/generic.c | 7 +++++++ src/audio/module_adapter/module_adapter.c | 13 ++++--------- .../sof/audio/module_adapter/module/generic.h | 4 +++- zephyr/sof_shell.c | 8 +++++--- 4 files changed, 19 insertions(+), 13 deletions(-) diff --git a/src/audio/module_adapter/module/generic.c b/src/audio/module_adapter/module/generic.c index b78f27059e13..27892af025b1 100644 --- a/src/audio/module_adapter/module/generic.c +++ b/src/audio/module_adapter/module/generic.c @@ -95,6 +95,8 @@ int module_init(struct processing_module *mod) list_init(&md->resources.mem_list); list_init(&md->resources.free_cont_list); list_init(&md->resources.cont_chunk_list); + md->resources.heap_usage = 0; + md->resources.heap_high_water_mark = 0; /* Now we can proceed with module specific initialization */ ret = interface->init(mod); @@ -189,6 +191,10 @@ void *mod_alloc_align(struct processing_module *mod, uint32_t size, uint32_t ali container->size = size; list_item_prepend(&container->mem_list, &res->mem_list); + res->heap_usage += size; + if (res->heap_usage > res->heap_high_water_mark) + res->heap_high_water_mark = res->heap_usage; + return ptr; } EXPORT_SYMBOL(mod_alloc_align); @@ -247,6 +253,7 @@ int mod_free(struct processing_module *mod, void *ptr) mem = container_of(mem_list, struct module_memory, mem_list); if (mem->ptr == ptr) { rfree(mem->ptr); + res->heap_usage -= mem->size; list_item_del(&mem->mem_list); container_put(mod, mem); return 0; diff --git a/src/audio/module_adapter/module_adapter.c b/src/audio/module_adapter/module_adapter.c index 0b42a5ae278d..32ef202579eb 100644 --- a/src/audio/module_adapter/module_adapter.c +++ b/src/audio/module_adapter/module_adapter.c @@ -1290,19 +1290,14 @@ void module_adapter_free(struct comp_dev *dev) } EXPORT_SYMBOL(module_adapter_free); -size_t module_adapter_heap_usage(struct processing_module *mod) +size_t module_adapter_heap_usage(struct processing_module *mod, size_t *hwm) { struct module_resources *res = &mod->priv.resources; - struct list_item *mem_list, *_mem_list; - size_t size = 0; - list_for_item_safe(mem_list, _mem_list, &res->mem_list) { - struct module_memory *mem = container_of(mem_list, struct module_memory, mem_list); + if (hwm) + *hwm = res->heap_high_water_mark; - size += mem->size; - } - - return size; + return res->heap_usage; } EXPORT_SYMBOL(module_adapter_heap_usage); diff --git a/src/include/sof/audio/module_adapter/module/generic.h b/src/include/sof/audio/module_adapter/module/generic.h index c63f98dbd9c2..eeac83cc438d 100644 --- a/src/include/sof/audio/module_adapter/module/generic.h +++ b/src/include/sof/audio/module_adapter/module/generic.h @@ -125,6 +125,8 @@ struct module_resources { struct list_item mem_list; /**< Allocad memory containers */ struct list_item free_cont_list; /**< Unused memory containers */ struct list_item cont_chunk_list; /**< Memory container chunks */ + size_t heap_usage; + size_t heap_high_water_mark; }; /** @@ -235,7 +237,7 @@ int module_adapter_trigger(struct comp_dev *dev, int cmd); void module_adapter_free(struct comp_dev *dev); int module_adapter_reset(struct comp_dev *dev); -size_t module_adapter_heap_usage(struct processing_module *mod); +size_t module_adapter_heap_usage(struct processing_module *mod, size_t *hwm); #if CONFIG_IPC_MAJOR_3 static inline diff --git a/zephyr/sof_shell.c b/zephyr/sof_shell.c index 60785c4eb5c4..f10a2c9275b5 100644 --- a/zephyr/sof_shell.c +++ b/zephyr/sof_shell.c @@ -55,13 +55,15 @@ static int cmd_sof_module_heap_usage(const struct shell *sh, } list_for_item_safe(clist, _clist, &ipc->comp_list) { + size_t usage, hwm; + icd = container_of(clist, struct ipc_comp_dev, list); if (icd->type != COMP_TYPE_COMPONENT) continue; - shell_print(sh, "comp id 0x%08x\t%8zu bytes\t(%zu max)", icd->id, - module_adapter_heap_usage(comp_mod(icd->cd)), - comp_mod(icd->cd)->priv.cfg.heap_bytes); + usage = module_adapter_heap_usage(comp_mod(icd->cd), &hwm); + shell_print(sh, "comp id 0x%08x%9zu usage%9zu hwm %9zu max\tbytes", + icd->id, usage, hwm, comp_mod(icd->cd)->priv.cfg.heap_bytes); } return 0; } From 8447750c14284dc7e6a3094960bb4b828acb54e8 Mon Sep 17 00:00:00 2001 From: Jyri Sarha Date: Thu, 14 Aug 2025 15:23:08 +0300 Subject: [PATCH 03/18] cmocka: Fix mixer test before it breaks due to blob handler dependency Add src/audio/data_blob.c to mixer cmocka test sources to fix the dependency problem from adding comp_data_blob_handler_new_ext() to audio/module_adapter/module/generic.c. Signed-off-by: Jyri Sarha --- test/cmocka/src/audio/mixer/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/test/cmocka/src/audio/mixer/CMakeLists.txt b/test/cmocka/src/audio/mixer/CMakeLists.txt index 723cb091ff61..ea8cad0bd79e 100644 --- a/test/cmocka/src/audio/mixer/CMakeLists.txt +++ b/test/cmocka/src/audio/mixer/CMakeLists.txt @@ -25,6 +25,7 @@ cmocka_test(mixer ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-schedule.c ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-stream.c ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-xrun.c + ${PROJECT_SOURCE_DIR}/src/audio/data_blob.c ${PROJECT_SOURCE_DIR}/src/module/audio/source_api.c ${PROJECT_SOURCE_DIR}/src/module/audio/sink_api.c ${PROJECT_SOURCE_DIR}/src/math/numbers.c From 4f9bc352695a7344ee06af633b99a58ba95c46f1 Mon Sep 17 00:00:00 2001 From: Jyri Sarha Date: Tue, 12 Aug 2025 15:02:40 +0300 Subject: [PATCH 04/18] modules: Add mod_data_blob_handler_new() to module API Add mod_data_blob_handler_new() to module API. The function is otherwise the same as comp_data_blob_handler_new(), but it takes a module pointer as the first argument, and the blob handler is automatically freed when the module unloads. The handler allocated with mod_data_blob_handler_new() should not be freed with comp_data_blob_handler_free(), mod_data_blob_handler_free() should be used. Signed-off-by: Jyri Sarha --- src/audio/module_adapter/module/generic.c | 59 +++++++++++++++++-- .../sof/audio/module_adapter/module/generic.h | 11 +++- 2 files changed, 63 insertions(+), 7 deletions(-) diff --git a/src/audio/module_adapter/module/generic.c b/src/audio/module_adapter/module/generic.c index 27892af025b1..63ff8a473344 100644 --- a/src/audio/module_adapter/module/generic.c +++ b/src/audio/module_adapter/module/generic.c @@ -14,6 +14,7 @@ #include #include +#include LOG_MODULE_DECLARE(module_adapter, CONFIG_SOF_LOG_LEVEL); @@ -189,6 +190,7 @@ void *mod_alloc_align(struct processing_module *mod, uint32_t size, uint32_t ali /* Store reference to allocated memory */ container->ptr = ptr; container->size = size; + container->free = NULL; list_item_prepend(&container->mem_list, &res->mem_list); res->heap_usage += size; @@ -233,12 +235,46 @@ void *mod_zalloc(struct processing_module *mod, uint32_t size) } EXPORT_SYMBOL(mod_zalloc); +/** + * Creates a blob handler and releases it when the module is unloaded + * @param mod Pointer to module this memory block is allocated for. + * @return Pointer to the created data blob handler + * + * Like comp_data_blob_handler_new() but the handler is automatically freed. + */ +#if CONFIG_COMP_BLOB +struct comp_data_blob_handler * +mod_data_blob_handler_new(struct processing_module *mod) +{ + struct module_resources *res = &mod->priv.resources; + struct module_memory *container = container_get(mod); + struct comp_data_blob_handler *dbh; + + if (!container) + return NULL; + + dbh = comp_data_blob_handler_new_ext(mod->dev, false, NULL, NULL); + if (!dbh) { + container_put(mod, container); + return NULL; + } + + container->ptr = dbh; + container->size = 0; + container->free = (void (*)(void *))comp_data_blob_handler_free; + list_item_prepend(&container->mem_list, &res->mem_list); + + return dbh; +} +EXPORT_SYMBOL(mod_data_blob_handler_new); +#endif + /** * Frees the memory block removes it from module's book keeping. * @param mod Pointer to module this memory block was allocated for. * @param ptr Pointer to the memory block. */ -int mod_free(struct processing_module *mod, void *ptr) +int mod_free(struct processing_module *mod, const void *ptr) { struct module_resources *res = &mod->priv.resources; struct module_memory *mem; @@ -252,8 +288,12 @@ int mod_free(struct processing_module *mod, void *ptr) list_for_item_safe(mem_list, _mem_list, &res->mem_list) { mem = container_of(mem_list, struct module_memory, mem_list); if (mem->ptr == ptr) { - rfree(mem->ptr); - res->heap_usage -= mem->size; + if (mem->free) { + mem->free(mem->ptr); + } else { + rfree(mem->ptr); + res->heap_usage -= mem->size; + } list_item_del(&mem->mem_list); container_put(mod, mem); return 0; @@ -267,6 +307,14 @@ int mod_free(struct processing_module *mod, void *ptr) } EXPORT_SYMBOL(mod_free); +#if CONFIG_COMP_BLOB +void mod_data_blob_handler_free(struct processing_module *mod, struct comp_data_blob_handler *dbh) +{ + mod_free(mod, (void *)dbh); +} +EXPORT_SYMBOL(mod_data_blob_handler_free); +#endif + int module_prepare(struct processing_module *mod, struct sof_source **sources, int num_of_sources, struct sof_sink **sinks, int num_of_sinks) @@ -453,7 +501,10 @@ void mod_free_all(struct processing_module *mod) list_for_item_safe(list, _list, &res->mem_list) { struct module_memory *mem = container_of(list, struct module_memory, mem_list); - rfree(mem->ptr); + if (mem->free) + mem->free(mem->ptr); + else + rfree(mem->ptr); list_item_del(&mem->mem_list); } diff --git a/src/include/sof/audio/module_adapter/module/generic.h b/src/include/sof/audio/module_adapter/module/generic.h index eeac83cc438d..731265a6b9b5 100644 --- a/src/include/sof/audio/module_adapter/module/generic.h +++ b/src/include/sof/audio/module_adapter/module/generic.h @@ -134,9 +134,10 @@ struct module_resources { * \brief module memory container - used for every memory allocated by module */ struct module_memory { - void *ptr; /**< A pointr to particular memory block */ + void *ptr; /**< A pointer to particular memory block */ struct list_item mem_list; /**< list of memory allocated by module */ - size_t size; + size_t size; /**< Size of allocated heap memory, 0 if not from heap */ + void (*free)(void *buf); /**< Pointer to free function for non heap allocations */ }; /** @@ -171,7 +172,11 @@ int module_init(struct processing_module *mod); void *mod_alloc_align(struct processing_module *mod, uint32_t size, uint32_t alignment); void *mod_alloc(struct processing_module *mod, uint32_t size); void *mod_zalloc(struct processing_module *mod, uint32_t size); -int mod_free(struct processing_module *mod, void *ptr); +int mod_free(struct processing_module *mod, const void *ptr); +#if CONFIG_COMP_BLOB +struct comp_data_blob_handler *mod_data_blob_handler_new(struct processing_module *mod); +void mod_data_blob_handler_free(struct processing_module *mod, struct comp_data_blob_handler *dbh); +#endif void mod_free_all(struct processing_module *mod); int module_prepare(struct processing_module *mod, struct sof_source **sources, int num_of_sources, From c817e8090c2dc550103e9b3a289e2fd6507dcb8b Mon Sep 17 00:00:00 2001 From: Jyri Sarha Date: Tue, 12 Aug 2025 17:59:24 +0300 Subject: [PATCH 05/18] modules: Add mod_fast_get() and mod_fast_put() Add module API versions of fast_get() and fast_put(). The SRAM copies reserved with mod_fast_get() are released automatically when the module unloads, and those SRAM copies should not be freed with the regular fast_put(). Signed-off-by: Jyri Sarha --- src/audio/module_adapter/module/generic.c | 42 +++++++++++++++++++ .../sof/audio/module_adapter/module/generic.h | 4 ++ 2 files changed, 46 insertions(+) diff --git a/src/audio/module_adapter/module/generic.c b/src/audio/module_adapter/module/generic.c index 63ff8a473344..1c9a94a73f96 100644 --- a/src/audio/module_adapter/module/generic.c +++ b/src/audio/module_adapter/module/generic.c @@ -15,6 +15,7 @@ #include #include +#include LOG_MODULE_DECLARE(module_adapter, CONFIG_SOF_LOG_LEVEL); @@ -269,6 +270,39 @@ mod_data_blob_handler_new(struct processing_module *mod) EXPORT_SYMBOL(mod_data_blob_handler_new); #endif +/** + * Make a module associated shared SRAM copy of DRAM read-only data. + * @param mod Pointer to module this copy is allocated for. + * @return Pointer to the SRAM copy. + * + * Like fast_get() but the handler is automatically freed. + */ +#if CONFIG_FAST_GET +const void *mod_fast_get(struct processing_module *mod, const void * const dram_ptr, size_t size) +{ + struct module_resources *res = &mod->priv.resources; + struct module_memory *container = container_get(mod); + const void *ptr; + + if (!container) + return NULL; + + ptr = fast_get(dram_ptr, size); + if (!ptr) { + container_put(mod, container); + return NULL; + } + + container->ptr = (void *)ptr; + container->size = 0; + container->free = (void (*)(void *))fast_put; + list_item_prepend(&container->mem_list, &res->mem_list); + + return ptr; +} +EXPORT_SYMBOL(mod_fast_get); +#endif + /** * Frees the memory block removes it from module's book keeping. * @param mod Pointer to module this memory block was allocated for. @@ -315,6 +349,14 @@ void mod_data_blob_handler_free(struct processing_module *mod, struct comp_data_ EXPORT_SYMBOL(mod_data_blob_handler_free); #endif +#if CONFIG_FAST_GET +void mod_fast_put(struct processing_module *mod, const void *sram_ptr) +{ + mod_free(mod, sram_ptr); +} +EXPORT_SYMBOL(mod_fast_put); +#endif + int module_prepare(struct processing_module *mod, struct sof_source **sources, int num_of_sources, struct sof_sink **sinks, int num_of_sinks) diff --git a/src/include/sof/audio/module_adapter/module/generic.h b/src/include/sof/audio/module_adapter/module/generic.h index 731265a6b9b5..6934967abb96 100644 --- a/src/include/sof/audio/module_adapter/module/generic.h +++ b/src/include/sof/audio/module_adapter/module/generic.h @@ -177,6 +177,10 @@ int mod_free(struct processing_module *mod, const void *ptr); struct comp_data_blob_handler *mod_data_blob_handler_new(struct processing_module *mod); void mod_data_blob_handler_free(struct processing_module *mod, struct comp_data_blob_handler *dbh); #endif +#if CONFIG_FAST_GET +const void *mod_fast_get(struct processing_module *mod, const void * const dram_ptr, size_t size); +void mod_fast_put(struct processing_module *mod, const void *sram_ptr); +#endif void mod_free_all(struct processing_module *mod); int module_prepare(struct processing_module *mod, struct sof_source **sources, int num_of_sources, From 4a0db410e2e3733699a7934df49e7cd706f5ef43 Mon Sep 17 00:00:00 2001 From: Jyri Sarha Date: Fri, 15 Aug 2025 12:18:44 +0300 Subject: [PATCH 06/18] modules: Add safeguard to mod_alloc() and friends Add safeguard to mod_alloc() and friends that checks that they are always called from the same thread (e.g. no locking needed). The checking code has to be also behind defined(__ZEPHYR__) to keep cmocka tests working. Signed-off-by: Jyri Sarha --- src/audio/module_adapter/Kconfig | 11 +++++++++++ src/audio/module_adapter/module/generic.c | 17 ++++++++++++++++- .../sof/audio/module_adapter/module/generic.h | 8 ++++++++ 3 files changed, 35 insertions(+), 1 deletion(-) diff --git a/src/audio/module_adapter/Kconfig b/src/audio/module_adapter/Kconfig index ad7f879d7049..3c762c73f7f8 100644 --- a/src/audio/module_adapter/Kconfig +++ b/src/audio/module_adapter/Kconfig @@ -13,6 +13,17 @@ menu "Processing modules" containers to allocate at once is selected by this config option. + config MODULE_MEMORY_API_DEBUG + bool "Turn on memory API thread safety checks" + default y if DEBUG + help + The Module Memory API structures are not protected + by locks. This is because the initialization, + allocation, and freeing of resources should always + be done in the same thread. This option adds an + assert to make sure no other thread makes such + operations. + config CADENCE_CODEC bool "Cadence codec" default n diff --git a/src/audio/module_adapter/module/generic.c b/src/audio/module_adapter/module/generic.c index 1c9a94a73f96..f910fb5be0f3 100644 --- a/src/audio/module_adapter/module/generic.c +++ b/src/audio/module_adapter/module/generic.c @@ -17,6 +17,14 @@ #include #include +/* The __ZEPHYR__ condition is to keep cmocka tests working */ +#if CONFIG_MODULE_MEMORY_API_DEBUG && defined(__ZEPHYR__) +#define MEM_API_CHECK_THREAD(res) __ASSERT((res)->rsrc_mngr == k_current_get(), \ + "Module memory API operation from wrong thread") +#else +#define MEM_API_CHECK_THREAD(res) +#endif + LOG_MODULE_DECLARE(module_adapter, CONFIG_SOF_LOG_LEVEL); int module_load_config(struct comp_dev *dev, const void *cfg, size_t size) @@ -99,7 +107,9 @@ int module_init(struct processing_module *mod) list_init(&md->resources.cont_chunk_list); md->resources.heap_usage = 0; md->resources.heap_high_water_mark = 0; - +#if CONFIG_MODULE_MEMORY_API_DEBUG && defined(__ZEPHYR__) + md->resources.rsrc_mngr = k_current_get(); +#endif /* Now we can proceed with module specific initialization */ ret = interface->init(mod); if (ret) { @@ -167,6 +177,7 @@ void *mod_alloc_align(struct processing_module *mod, uint32_t size, uint32_t ali struct module_resources *res = &mod->priv.resources; void *ptr; + MEM_API_CHECK_THREAD(res); if (!container) return NULL; @@ -251,6 +262,7 @@ mod_data_blob_handler_new(struct processing_module *mod) struct module_memory *container = container_get(mod); struct comp_data_blob_handler *dbh; + MEM_API_CHECK_THREAD(res); if (!container) return NULL; @@ -284,6 +296,7 @@ const void *mod_fast_get(struct processing_module *mod, const void * const dram_ struct module_memory *container = container_get(mod); const void *ptr; + MEM_API_CHECK_THREAD(res); if (!container) return NULL; @@ -315,6 +328,7 @@ int mod_free(struct processing_module *mod, const void *ptr) struct list_item *mem_list; struct list_item *_mem_list; + MEM_API_CHECK_THREAD(res); if (!ptr) return 0; @@ -539,6 +553,7 @@ void mod_free_all(struct processing_module *mod) struct list_item *list; struct list_item *_list; + MEM_API_CHECK_THREAD(res); /* Find which container keeps this memory */ list_for_item_safe(list, _list, &res->mem_list) { struct module_memory *mem = container_of(list, struct module_memory, mem_list); diff --git a/src/include/sof/audio/module_adapter/module/generic.h b/src/include/sof/audio/module_adapter/module/generic.h index 6934967abb96..1916ef3e040b 100644 --- a/src/include/sof/audio/module_adapter/module/generic.h +++ b/src/include/sof/audio/module_adapter/module/generic.h @@ -19,6 +19,11 @@ #include #include "module_interface.h" +/* The __ZEPHYR__ condition is to keep cmocka tests working */ +#if CONFIG_MODULE_MEMORY_API_DEBUG && defined(__ZEPHYR__) +#include +#endif + /* * helpers to determine processing type * Needed till all the modules use PROCESSING_MODE_SINK_SOURCE @@ -127,6 +132,9 @@ struct module_resources { struct list_item cont_chunk_list; /**< Memory container chunks */ size_t heap_usage; size_t heap_high_water_mark; +#if CONFIG_MODULE_MEMORY_API_DEBUG && defined(__ZEPHYR__) + k_tid_t rsrc_mngr; +#endif }; /** From 08244ae41679601035bd2d2a72511a077300c343 Mon Sep 17 00:00:00 2001 From: Jyri Sarha Date: Wed, 13 Aug 2025 00:37:08 +0300 Subject: [PATCH 07/18] Audio: SRC: Take mod_fast_get() and mod_fast_put() into use Take mod_fast_get() and mod_fast_put() into use. Signed-off-by: Jyri Sarha --- src/audio/src/src_common.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/src/audio/src/src_common.c b/src/audio/src/src_common.c index f96b3bc6e358..6331a6b9180e 100644 --- a/src/audio/src/src_common.c +++ b/src/audio/src/src_common.c @@ -627,12 +627,11 @@ int src_allocate_copy_stages(struct processing_module *mod, struct src_param *pr return -EINVAL; } - stage_dst[0].coefs = fast_get(stage_src1->coefs, coef_size[0]); - stage_dst[1].coefs = fast_get(stage_src2->coefs, coef_size[1]); + stage_dst[0].coefs = mod_fast_get(mod, stage_src1->coefs, coef_size[0]); + stage_dst[1].coefs = mod_fast_get(mod, stage_src2->coefs, coef_size[1]); if (!stage_dst[0].coefs || !stage_dst[1].coefs) { comp_err(mod->dev, "failed to allocate coefficients"); - fast_put(stage_dst[0].coefs); return -ENOMEM; } @@ -708,12 +707,5 @@ __cold int src_free(struct processing_module *mod) comp_info(mod->dev, "src_free()"); -#if CONFIG_FAST_GET - struct comp_data *cd = module_get_private_data(mod); - if (cd->param.stage1) { - fast_put(cd->param.stage1->coefs); - fast_put(cd->param.stage2->coefs); - } -#endif return 0; } From c62c0919a1d0bd9389b0b655ed3eb5bf4516b401 Mon Sep 17 00:00:00 2001 From: Jyri Sarha Date: Thu, 7 Aug 2025 13:06:20 +0300 Subject: [PATCH 08/18] Audio: Aria: All memory allocations through module API Allocate all memory through module API mod_alloc() and friends and remove all redundant rfree() calls from module unload functions and init error branches. Signed-off-by: Jyri Sarha --- src/audio/aria/aria.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/audio/aria/aria.c b/src/audio/aria/aria.c index 2f558eb2d6d9..006edf9533dd 100644 --- a/src/audio/aria/aria.c +++ b/src/audio/aria/aria.c @@ -9,7 +9,6 @@ #include #include #include -#include #include #include #include @@ -126,7 +125,7 @@ static int aria_init(struct processing_module *mod) list_init(&dev->bsource_list); list_init(&dev->bsink_list); - cd = rzalloc(SOF_MEM_FLAG_USER, sizeof(*cd)); + cd = mod_zalloc(mod, sizeof(*cd)); if (!cd) { return -ENOMEM; } @@ -145,10 +144,9 @@ static int aria_init(struct processing_module *mod) } mod_data->private = cd; - buf = rballoc(SOF_MEM_FLAG_USER, req_mem); + buf = mod_alloc(mod, req_mem); if (!buf) { - rfree(cd); comp_err(dev, "allocation failed for size %d", req_mem); return -ENOMEM; } @@ -158,10 +156,6 @@ static int aria_init(struct processing_module *mod) static int aria_free(struct processing_module *mod) { - struct aria_data *cd = module_get_private_data(mod); - - rfree(cd->data_addr); - rfree(cd); return 0; } From 3b03ab06558eabbde9835616f3b89525fbf1b557 Mon Sep 17 00:00:00 2001 From: Jyri Sarha Date: Thu, 7 Aug 2025 15:38:01 +0300 Subject: [PATCH 09/18] Audio: ASRC: Memory, blob, and fast_get allocs to module API Allocate all memory, blob handlers, and fast_get() buffers through module API mod_alloc() and friends and remove all redundant rfree(), comp_data_blob_handler_free(), and fast_put() calls from module unload functions and init error branches. Signed-off-by: Jyri Sarha --- src/audio/asrc/asrc.c | 47 +++++++++++---------------- src/audio/asrc/asrc_farrow.c | 62 ++++++++++++++++++++---------------- src/audio/asrc/asrc_farrow.h | 8 ++--- src/audio/asrc/asrc_ipc3.c | 1 - src/audio/asrc/asrc_ipc4.c | 1 - 5 files changed, 57 insertions(+), 62 deletions(-) diff --git a/src/audio/asrc/asrc.c b/src/audio/asrc/asrc.c index 2d77a04c380f..7a7e2c24400b 100644 --- a/src/audio/asrc/asrc.c +++ b/src/audio/asrc/asrc.c @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include @@ -217,7 +216,7 @@ static int asrc_init(struct processing_module *mod) return -EINVAL; } - cd = rzalloc(SOF_MEM_FLAG_USER, sizeof(*cd)); + cd = mod_alloc(mod, sizeof(*cd)); if (!cd) return -ENOMEM; @@ -242,7 +241,7 @@ static int asrc_init(struct processing_module *mod) return 0; } -static int asrc_initialize_buffers(struct asrc_farrow *src_obj) +static int asrc_initialize_buffers(struct processing_module *mod, struct asrc_farrow *src_obj) { int32_t *buf_32; int16_t *buf_16; @@ -261,7 +260,7 @@ static int asrc_initialize_buffers(struct asrc_farrow *src_obj) buffer_size = src_obj->buffer_length * sizeof(int32_t); for (ch = 0; ch < src_obj->num_channels; ch++) { - buf_32 = rzalloc(SOF_MEM_FLAG_USER, buffer_size); + buf_32 = mod_zalloc(mod, buffer_size); if (!buf_32) return -ENOMEM; @@ -272,7 +271,7 @@ static int asrc_initialize_buffers(struct asrc_farrow *src_obj) buffer_size = src_obj->buffer_length * sizeof(int16_t); for (ch = 0; ch < src_obj->num_channels; ch++) { - buf_16 = rzalloc(SOF_MEM_FLAG_USER, buffer_size); + buf_16 = mod_zalloc(mod, buffer_size); if (!buf_16) return -ENOMEM; @@ -284,7 +283,7 @@ static int asrc_initialize_buffers(struct asrc_farrow *src_obj) return 0; } -static void asrc_release_buffers(struct asrc_farrow *src_obj) +static void asrc_release_buffers(struct processing_module *mod, struct asrc_farrow *src_obj) { int32_t *buf_32; int16_t *buf_16; @@ -299,7 +298,7 @@ static void asrc_release_buffers(struct asrc_farrow *src_obj) if (buf_32) { src_obj->ring_buffers32[ch] = NULL; - rfree(buf_32); + mod_free(mod, buf_32); } } else @@ -308,23 +307,17 @@ static void asrc_release_buffers(struct asrc_farrow *src_obj) if (buf_16) { src_obj->ring_buffers16[ch] = NULL; - rfree(buf_16); + mod_free(mod, buf_16); } } } static int asrc_free(struct processing_module *mod) { - struct comp_data *cd = module_get_private_data(mod); struct comp_dev *dev = mod->dev; comp_dbg(dev, "asrc_free()"); - rfree(cd->buf); - asrc_release_buffers(cd->asrc_obj); - asrc_free_polyphase_filter(cd->asrc_obj); - rfree(cd->asrc_obj); - rfree(cd); return 0; } @@ -614,8 +607,7 @@ static int asrc_prepare(struct processing_module *mod, cd->buf_size = (cd->source_frames_max + cd->sink_frames_max) * frame_bytes; - cd->buf = rzalloc(SOF_MEM_FLAG_USER, - cd->buf_size); + cd->buf = mod_zalloc(mod, cd->buf_size); if (!cd->buf) { cd->buf_size = 0; comp_err(dev, "asrc_prepare(), allocation fail for size %d", @@ -632,7 +624,7 @@ static int asrc_prepare(struct processing_module *mod, /* Get required size and allocate memory for ASRC */ sample_bits = sample_bytes * 8; - ret = asrc_get_required_size(dev, &cd->asrc_size, + ret = asrc_get_required_size(mod, &cd->asrc_size, audio_stream_get_channels(&sourceb->stream), sample_bits); if (ret) { @@ -640,8 +632,7 @@ static int asrc_prepare(struct processing_module *mod, goto err_free_buf; } - cd->asrc_obj = rzalloc(SOF_MEM_FLAG_USER, - cd->asrc_size); + cd->asrc_obj = mod_zalloc(mod, cd->asrc_size); if (!cd->asrc_obj) { comp_err(dev, "asrc_prepare(), allocation fail for size %d", cd->asrc_size); @@ -659,7 +650,7 @@ static int asrc_prepare(struct processing_module *mod, fs_sec = cd->source_rate; } - ret = asrc_initialise(dev, cd->asrc_obj, audio_stream_get_channels(&sourceb->stream), + ret = asrc_initialise(mod, cd->asrc_obj, audio_stream_get_channels(&sourceb->stream), fs_prim, fs_sec, ASRC_IOF_INTERLEAVED, ASRC_IOF_INTERLEAVED, ASRC_BM_LINEAR, cd->frames, sample_bits, @@ -670,7 +661,7 @@ static int asrc_prepare(struct processing_module *mod, } /* Allocate ring buffers */ - ret = asrc_initialize_buffers(cd->asrc_obj); + ret = asrc_initialize_buffers(mod, cd->asrc_obj); /* check for errors */ if (ret) { @@ -698,12 +689,12 @@ static int asrc_prepare(struct processing_module *mod, return 0; err_free_asrc: - asrc_release_buffers(cd->asrc_obj); - rfree(cd->asrc_obj); + asrc_release_buffers(mod, cd->asrc_obj); + mod_free(mod, cd->asrc_obj); cd->asrc_obj = NULL; err_free_buf: - rfree(cd->buf); + mod_free(mod, cd->buf); cd->buf = NULL; err: @@ -865,10 +856,10 @@ static int asrc_reset(struct processing_module *mod) asrc_dai_stop_timestamp(cd); /* Free the allocations those were done in prepare() */ - asrc_release_buffers(cd->asrc_obj); - asrc_free_polyphase_filter(cd->asrc_obj); - rfree(cd->asrc_obj); - rfree(cd->buf); + asrc_release_buffers(mod, cd->asrc_obj); + asrc_free_polyphase_filter(mod, cd->asrc_obj); + mod_free(mod, cd->asrc_obj); + mod_free(mod, cd->buf); cd->asrc_obj = NULL; cd->buf = NULL; diff --git a/src/audio/asrc/asrc_farrow.c b/src/audio/asrc/asrc_farrow.c index 987a11408af0..e840a8082a3b 100644 --- a/src/audio/asrc/asrc_farrow.c +++ b/src/audio/asrc/asrc_farrow.c @@ -11,9 +11,9 @@ #include #include #include -#include #include #include +#include #include "asrc_farrow.h" LOG_MODULE_DECLARE(asrc, CONFIG_SOF_LOG_LEVEL); @@ -243,7 +243,7 @@ static const struct asrc_filter_params c_filter_params[CR_NUM] = { * Initialise the pointers to the filters, set the number of filters * and their length */ -static enum asrc_error_code initialise_filter(struct comp_dev *dev, +static enum asrc_error_code initialise_filter(struct processing_module *mod, struct asrc_farrow *src_obj); /* @@ -268,11 +268,12 @@ static enum asrc_error_code initialise_filter(struct comp_dev *dev, * Pointers to each channels data. Buffers are allocated externally. */ -enum asrc_error_code asrc_get_required_size(struct comp_dev *dev, +enum asrc_error_code asrc_get_required_size(struct processing_module *mod, int *required_size, int num_channels, int bit_depth) { + struct comp_dev *dev = mod->dev; int size; /* check for parameter errors */ @@ -318,7 +319,7 @@ enum asrc_error_code asrc_get_required_size(struct comp_dev *dev, return ASRC_EC_OK; } -enum asrc_error_code asrc_initialise(struct comp_dev *dev, +enum asrc_error_code asrc_initialise(struct processing_module *mod, struct asrc_farrow *src_obj, int num_channels, int32_t fs_prim, @@ -331,6 +332,7 @@ enum asrc_error_code asrc_initialise(struct comp_dev *dev, enum asrc_control_mode control_mode, enum asrc_operation_mode operation_mode) { + struct comp_dev *dev = mod->dev; enum asrc_error_code error_code; /* check for parameter errors */ @@ -410,7 +412,7 @@ enum asrc_error_code asrc_initialise(struct comp_dev *dev, * also sets the pointer to the corresponding * calc_impulse_response_nX function. */ - error_code = initialise_filter(dev, src_obj); + error_code = initialise_filter(mod, src_obj); /* check for errors */ if (error_code != ASRC_EC_OK) { @@ -438,10 +440,12 @@ enum asrc_error_code asrc_initialise(struct comp_dev *dev, return ASRC_EC_OK; } -enum asrc_error_code asrc_set_fs_ratio(struct comp_dev *dev, +enum asrc_error_code asrc_set_fs_ratio(struct processing_module *mod, struct asrc_farrow *src_obj, int32_t fs_prim, int32_t fs_sec) { + struct comp_dev *dev = mod->dev; + /* Check for parameter errors */ if (!src_obj) { comp_err(dev, "asrc_set_fs_ratio(), null src_obj"); @@ -490,7 +494,7 @@ enum asrc_error_code asrc_set_fs_ratio(struct comp_dev *dev, /* See initialise_asrc(...) for further information * Update the filters accordingly */ - enum asrc_error_code error_code = initialise_filter(dev, src_obj); + enum asrc_error_code error_code = initialise_filter(mod, src_obj); /* check for errors */ if (error_code != ASRC_EC_OK) { comp_err(dev, "asrc_set_fs_ratio(), failed filter initialise"); @@ -554,28 +558,29 @@ enum asrc_error_code asrc_set_output_format(struct comp_dev *dev, return ASRC_EC_OK; } -static const int32_t *__get_polyphase_filter(const int32_t *filter, size_t size) +static const int32_t *__get_polyphase_filter(struct processing_module *mod, + const int32_t *filter, size_t size) { #if CONFIG_FAST_GET - return fast_get(filter, size); + return mod_fast_get(mod, filter, size); #else return filter; #endif } -#define get_polyphase_filter(f) __get_polyphase_filter(f, sizeof(f)) +#define get_polyphase_filter(m, f) __get_polyphase_filter(m, f, sizeof(f)) -static void put_polyphase_filter(const int32_t *filter) +static void put_polyphase_filter(struct processing_module *mod, const int32_t *filter) { #if CONFIG_FAST_GET - fast_put(filter); + mod_fast_put(mod, filter); #endif } -void asrc_free_polyphase_filter(struct asrc_farrow *src_obj) +void asrc_free_polyphase_filter(struct processing_module *mod, struct asrc_farrow *src_obj) { if (src_obj && src_obj->polyphase_filters) { - put_polyphase_filter(src_obj->polyphase_filters); + put_polyphase_filter(mod, src_obj->polyphase_filters); src_obj->polyphase_filters = NULL; } } @@ -583,9 +588,10 @@ void asrc_free_polyphase_filter(struct asrc_farrow *src_obj) /* * FILTER FUNCTIONS */ -static enum asrc_error_code initialise_filter(struct comp_dev *dev, +static enum asrc_error_code initialise_filter(struct processing_module *mod, struct asrc_farrow *src_obj) { + struct comp_dev *dev = mod->dev; int fs_in; int fs_out; @@ -606,7 +612,7 @@ static enum asrc_error_code initialise_filter(struct comp_dev *dev, /* Reset coefficients for possible exit with error. */ src_obj->filter_length = 0; src_obj->num_filters = 0; - asrc_free_polyphase_filter(src_obj); + asrc_free_polyphase_filter(mod, src_obj); if (fs_in == 0 || fs_out == 0) { /* Avoid possible divisions by zero. */ @@ -622,7 +628,7 @@ static enum asrc_error_code initialise_filter(struct comp_dev *dev, c_filter_params[CR_48000TO48000].filter_length; src_obj->num_filters = c_filter_params[CR_48000TO48000].num_filters; - src_obj->polyphase_filters = get_polyphase_filter(coeff48000to48000); + src_obj->polyphase_filters = get_polyphase_filter(mod, coeff48000to48000); } else if (fs_in <= fs_out) { /* All upsampling use cases can share the same set of * filter coefficients. @@ -631,7 +637,7 @@ static enum asrc_error_code initialise_filter(struct comp_dev *dev, c_filter_params[CR_44100TO48000].filter_length; src_obj->num_filters = c_filter_params[CR_44100TO48000].num_filters; - src_obj->polyphase_filters = get_polyphase_filter(coeff44100to48000); + src_obj->polyphase_filters = get_polyphase_filter(mod, coeff44100to48000); } else if (fs_in == 48000) { switch (fs_out) { #if (CONFIG_ASRC_SUPPORT_CONVERSION_48000_TO_08000) @@ -640,7 +646,7 @@ static enum asrc_error_code initialise_filter(struct comp_dev *dev, c_filter_params[CR_48000TO08000].filter_length; src_obj->num_filters = c_filter_params[CR_48000TO08000].num_filters; - src_obj->polyphase_filters = get_polyphase_filter(coeff48000to08000); + src_obj->polyphase_filters = get_polyphase_filter(mod, coeff48000to08000); break; #endif #if (CONFIG_ASRC_SUPPORT_CONVERSION_48000_TO_11025) @@ -649,7 +655,7 @@ static enum asrc_error_code initialise_filter(struct comp_dev *dev, c_filter_params[CR_48000TO11025].filter_length; src_obj->num_filters = c_filter_params[CR_48000TO11025].num_filters; - src_obj->polyphase_filters = get_polyphase_filter(coeff48000to11025); + src_obj->polyphase_filters = get_polyphase_filter(mod, coeff48000to11025); break; #endif #if (CONFIG_ASRC_SUPPORT_CONVERSION_48000_TO_12000) @@ -658,7 +664,7 @@ static enum asrc_error_code initialise_filter(struct comp_dev *dev, c_filter_params[CR_48000TO12000].filter_length; src_obj->num_filters = c_filter_params[CR_48000TO12000].num_filters; - src_obj->polyphase_filters = get_polyphase_filter(coeff48000to12000); + src_obj->polyphase_filters = get_polyphase_filter(mod, coeff48000to12000); break; #endif #if (CONFIG_ASRC_SUPPORT_CONVERSION_48000_TO_16000) @@ -667,7 +673,7 @@ static enum asrc_error_code initialise_filter(struct comp_dev *dev, c_filter_params[CR_48000TO16000].filter_length; src_obj->num_filters = c_filter_params[CR_48000TO16000].num_filters; - src_obj->polyphase_filters = get_polyphase_filter(coeff48000to16000); + src_obj->polyphase_filters = get_polyphase_filter(mod, coeff48000to16000); break; #endif #if (CONFIG_ASRC_SUPPORT_CONVERSION_48000_TO_22050) @@ -676,7 +682,7 @@ static enum asrc_error_code initialise_filter(struct comp_dev *dev, c_filter_params[CR_48000TO22050].filter_length; src_obj->num_filters = c_filter_params[CR_48000TO22050].num_filters; - src_obj->polyphase_filters = get_polyphase_filter(coeff48000to22050); + src_obj->polyphase_filters = get_polyphase_filter(mod, coeff48000to22050); break; #endif #if (CONFIG_ASRC_SUPPORT_CONVERSION_48000_TO_24000) @@ -685,7 +691,7 @@ static enum asrc_error_code initialise_filter(struct comp_dev *dev, c_filter_params[CR_48000TO24000].filter_length; src_obj->num_filters = c_filter_params[CR_48000TO24000].num_filters; - src_obj->polyphase_filters = get_polyphase_filter(coeff48000to24000); + src_obj->polyphase_filters = get_polyphase_filter(mod, coeff48000to24000); break; #endif #if (CONFIG_ASRC_SUPPORT_CONVERSION_48000_TO_32000) @@ -694,7 +700,7 @@ static enum asrc_error_code initialise_filter(struct comp_dev *dev, c_filter_params[CR_48000TO32000].filter_length; src_obj->num_filters = c_filter_params[CR_48000TO32000].num_filters; - src_obj->polyphase_filters = get_polyphase_filter(coeff48000to32000); + src_obj->polyphase_filters = get_polyphase_filter(mod, coeff48000to32000); break; #endif #if (CONFIG_ASRC_SUPPORT_CONVERSION_48000_TO_44100) @@ -703,7 +709,7 @@ static enum asrc_error_code initialise_filter(struct comp_dev *dev, c_filter_params[CR_48000TO44100].filter_length; src_obj->num_filters = c_filter_params[CR_48000TO44100].num_filters; - src_obj->polyphase_filters = get_polyphase_filter(coeff48000to44100); + src_obj->polyphase_filters = get_polyphase_filter(mod, coeff48000to44100); break; #endif default: @@ -719,7 +725,7 @@ static enum asrc_error_code initialise_filter(struct comp_dev *dev, c_filter_params[CR_24000TO08000].filter_length; src_obj->num_filters = c_filter_params[CR_24000TO08000].num_filters; - src_obj->polyphase_filters = get_polyphase_filter(coeff24000to08000); + src_obj->polyphase_filters = get_polyphase_filter(mod, coeff24000to08000); break; #endif #if (CONFIG_ASRC_SUPPORT_CONVERSION_24000_TO_16000) @@ -728,7 +734,7 @@ static enum asrc_error_code initialise_filter(struct comp_dev *dev, c_filter_params[CR_24000TO16000].filter_length; src_obj->num_filters = c_filter_params[CR_24000TO16000].num_filters; - src_obj->polyphase_filters = get_polyphase_filter(coeff24000to16000); + src_obj->polyphase_filters = get_polyphase_filter(mod, coeff24000to16000); break; #endif default: diff --git a/src/audio/asrc/asrc_farrow.h b/src/audio/asrc/asrc_farrow.h index 766ead172d58..48e564c2d1e1 100644 --- a/src/audio/asrc/asrc_farrow.h +++ b/src/audio/asrc/asrc_farrow.h @@ -231,7 +231,7 @@ struct asrc_farrow { * @param[in] bit_depth The wordlength that will be used for representing * the PCM samples, must be 16 or 32. */ -enum asrc_error_code asrc_get_required_size(struct comp_dev *dev, +enum asrc_error_code asrc_get_required_size(struct processing_module *mod, int *required_size, int num_channels, int bit_depth); @@ -268,7 +268,7 @@ enum asrc_error_code asrc_get_required_size(struct comp_dev *dev, * @param[in] operation_mode Choose 'push' or 'pull', depending on the mode * you want your ASRC to operate in. */ -enum asrc_error_code asrc_initialise(struct comp_dev *dev, +enum asrc_error_code asrc_initialise(struct processing_module *mod, struct asrc_farrow *src_obj, int num_channels, int32_t fs_prim, @@ -286,7 +286,7 @@ enum asrc_error_code asrc_initialise(struct comp_dev *dev, * * @param[in] src_obj Pointer to the ias_src_farrow. */ -void asrc_free_polyphase_filter(struct asrc_farrow *src_obj); +void asrc_free_polyphase_filter(struct processing_module *mod, struct asrc_farrow *src_obj); /* * @brief Process the sample rate converter for one frame; the frame @@ -591,7 +591,7 @@ enum asrc_error_code asrc_update_fs_ratio(struct comp_dev *dev, * @param[in] fs_prim Primary sampling rate. * @param[in] fs_sec Secondary sampling rate. */ -enum asrc_error_code asrc_set_fs_ratio(struct comp_dev *dev, +enum asrc_error_code asrc_set_fs_ratio(struct processing_module *mod, struct asrc_farrow *src_obj, int32_t fs_prim, int32_t fs_sec); diff --git a/src/audio/asrc/asrc_ipc3.c b/src/audio/asrc/asrc_ipc3.c index 30dfbecddc6b..ca917318d7e5 100644 --- a/src/audio/asrc/asrc_ipc3.c +++ b/src/audio/asrc/asrc_ipc3.c @@ -4,7 +4,6 @@ #include #include -#include #include #include #include diff --git a/src/audio/asrc/asrc_ipc4.c b/src/audio/asrc/asrc_ipc4.c index 3e5d8bf7818f..1047799f207b 100644 --- a/src/audio/asrc/asrc_ipc4.c +++ b/src/audio/asrc/asrc_ipc4.c @@ -4,7 +4,6 @@ #include #include -#include #include #include #include From 083facf076b2c403e150d4749bbf2d4b1d5f6976 Mon Sep 17 00:00:00 2001 From: Jyri Sarha Date: Thu, 7 Aug 2025 23:02:32 +0300 Subject: [PATCH 10/18] Audio: Copier: All memory allocations through module API Allocate all memory through module API mod_alloc() and friends and remove all redundant rfree() calls from module unload functions and init error branches. NOTE: copier_dai.c and copier_host.c still have their shared memory allocated through the old API. This is to be fixed once we have decided on how the shared memory allocations should work in user-space. Signed-off-by: Jyri Sarha --- src/audio/copier/copier.c | 56 +++++++++++++-------------------------- 1 file changed, 19 insertions(+), 37 deletions(-) diff --git a/src/audio/copier/copier.c b/src/audio/copier/copier.c index 9aab0858a305..c4a1b1097429 100644 --- a/src/audio/copier/copier.c +++ b/src/audio/copier/copier.c @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include @@ -82,13 +81,12 @@ static void mic_privacy_event(void *arg, enum notify_id type, void *data) } } -static int mic_privacy_configure(struct comp_dev *dev, struct copier_data *cd) +static int mic_privacy_configure(struct processing_module *mod, struct copier_data *cd) { struct mic_privacy_data *mic_priv_data; int ret; - mic_priv_data = rzalloc(SOF_MEM_FLAG_USER, - sizeof(struct mic_privacy_data)); + mic_priv_data = mod_zalloc(mod, sizeof(struct mic_privacy_data)); if (!mic_priv_data) return -ENOMEM; @@ -100,7 +98,7 @@ static int mic_privacy_configure(struct comp_dev *dev, struct copier_data *cd) uint32_t zeroing_wait_time = (mic_privacy_get_dma_zeroing_wait_time() * 1000) / ADSP_RTC_FREQUENCY; - ret = copier_gain_set_params(dev, &mic_priv_data->mic_priv_gain_params, + ret = copier_gain_set_params(mod->dev, &mic_priv_data->mic_priv_gain_params, zeroing_wait_time, SOF_DAI_INTEL_NONE); if (ret != 0) { rfree(mic_priv_data); @@ -144,7 +142,7 @@ __cold static int copier_init(struct processing_module *mod) assert_can_be_cold(); - cd = rzalloc(SOF_MEM_FLAG_USER, sizeof(*cd)); + cd = mod_zalloc(mod, sizeof(*cd)); if (!cd) return -ENOMEM; @@ -154,10 +152,8 @@ __cold static int copier_init(struct processing_module *mod) * store it, it's only used during IPC processing, besides we haven't * allocated space for it, so don't "fix" this! */ - if (memcpy_s(&cd->config, sizeof(cd->config), copier, sizeof(*copier)) < 0) { - ret = -EINVAL; - goto error_cd; - } + if (memcpy_s(&cd->config, sizeof(cd->config), copier, sizeof(*copier)) < 0) + return -EINVAL; /* Allocate memory and store gateway_cfg in runtime. Gateway cfg has to * be kept even after copier is created e.g. during SET_PIPELINE_STATE @@ -166,18 +162,15 @@ __cold static int copier_init(struct processing_module *mod) */ if (copier->gtw_cfg.config_length) { gtw_cfg_size = copier->gtw_cfg.config_length << 2; - gtw_cfg = rmalloc(SOF_MEM_FLAG_USER, - gtw_cfg_size); - if (!gtw_cfg) { - ret = -ENOMEM; - goto error_cd; - } + gtw_cfg = mod_alloc(mod, gtw_cfg_size); + if (!gtw_cfg) + return -ENOMEM; ret = memcpy_s(gtw_cfg, gtw_cfg_size, &copier->gtw_cfg.config_data, gtw_cfg_size); if (ret) { comp_err(dev, "Unable to copy gateway config from copier blob"); - goto error; + return ret; } cd->gtw_cfg = gtw_cfg; @@ -191,8 +184,7 @@ __cold static int copier_init(struct processing_module *mod) IPC_COMP_IGNORE_REMOTE); if (!ipc_pipe) { comp_err(dev, "pipeline %d is not existed", config->pipeline_id); - ret = -EPIPE; - goto error; + return -EPIPE; } dev->pipeline = ipc_pipe->pipeline; @@ -208,15 +200,15 @@ __cold static int copier_init(struct processing_module *mod) ret = copier_host_create(dev, cd, copier, ipc_pipe->pipeline); if (ret < 0) { comp_err(dev, "unable to create host"); - goto error; + return ret; } #if CONFIG_INTEL_ADSP_MIC_PRIVACY if (cd->direction == SOF_IPC_STREAM_CAPTURE && node_id.f.dma_type == ipc4_hda_host_output_class) { - ret = mic_privacy_configure(dev, cd); + ret = mic_privacy_configure(mod, cd); if (ret < 0) { comp_err(dev, "unable to configure mic privacy"); - goto error; + return ret; } } #endif @@ -231,14 +223,14 @@ __cold static int copier_init(struct processing_module *mod) ret = copier_dai_create(dev, cd, copier, ipc_pipe->pipeline); if (ret < 0) { comp_err(dev, "unable to create dai"); - goto error; + return ret; } #if CONFIG_INTEL_ADSP_MIC_PRIVACY if (cd->direction == SOF_IPC_STREAM_CAPTURE) { - ret = mic_privacy_configure(dev, cd); + ret = mic_privacy_configure(mod, cd); if (ret < 0) { comp_err(dev, "unable to configure mic privacy"); - goto error; + return ret; } } #endif @@ -249,14 +241,13 @@ __cold static int copier_init(struct processing_module *mod) ret = copier_ipcgtw_create(dev, cd, copier, ipc_pipe->pipeline); if (ret < 0) { comp_err(dev, "unable to create IPC gateway"); - goto error; + return ret; } break; #endif default: comp_err(dev, "unsupported dma type %x", (uint32_t)node_id.f.dma_type); - ret = -EINVAL; - goto error; + return -EINVAL; }; dev->direction_set = true; @@ -270,11 +261,6 @@ __cold static int copier_init(struct processing_module *mod) dev->direction = cd->direction; dev->state = COMP_STATE_READY; return 0; -error: - rfree(gtw_cfg); -error_cd: - rfree(cd); - return ret; } __cold static int copier_free(struct processing_module *mod) @@ -303,10 +289,6 @@ __cold static int copier_free(struct processing_module *mod) break; } - if (cd) - rfree(cd->gtw_cfg); - rfree(cd); - return 0; } From 710c8f8c62de9e34924c21aab5803f1d1a0a6536 Mon Sep 17 00:00:00 2001 From: Jyri Sarha Date: Mon, 11 Aug 2025 18:21:35 +0300 Subject: [PATCH 11/18] Audio: crossover: All memory allocations through module API Allocate all memory through module API mod_alloc() and friends and remove all redundant rfree() calls from module unload functions and init error branches. Signed-off-by: Jyri Sarha --- src/audio/crossover/crossover.c | 53 ++++++++----------- src/audio/multiband_drc/multiband_drc.c | 2 +- .../module/crossover/crossover_common.h | 18 ++++--- 3 files changed, 34 insertions(+), 39 deletions(-) diff --git a/src/audio/crossover/crossover.c b/src/audio/crossover/crossover.c index 7ae8dd47c6a2..a1e3f996bc36 100644 --- a/src/audio/crossover/crossover.c +++ b/src/audio/crossover/crossover.c @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include @@ -47,12 +46,13 @@ DECLARE_TR_CTX(crossover_tr, SOF_UUID(crossover_uuid), LOG_LEVEL_INFO); * \brief Reset the state (coefficients and delay) of the crossover filter * across all channels */ -static void crossover_reset_state(struct comp_data *cd) +static void crossover_reset_state(struct processing_module *mod, + struct comp_data *cd) { int i; for (i = 0; i < PLATFORM_MAX_CHANNELS; i++) - crossover_reset_state_ch(&cd->state[i]); + crossover_reset_state_ch(mod, &cd->state[i]); } /** @@ -156,7 +156,8 @@ static int crossover_assign_sinks(struct processing_module *mod, * high/low pass filter. * \param[out] lr4 initialized struct */ -static int crossover_init_coef_lr4(struct sof_eq_iir_biquad *coef, +static int crossover_init_coef_lr4(struct processing_module *mod, + struct sof_eq_iir_biquad *coef, struct iir_state_df1 *lr4) { int ret; @@ -169,8 +170,7 @@ static int crossover_init_coef_lr4(struct sof_eq_iir_biquad *coef, * in series due to identity. To maintain the structure of * iir_state_df1, it requires two copies of coefficients in a row. */ - lr4->coef = rzalloc(SOF_MEM_FLAG_USER, - sizeof(struct sof_eq_iir_biquad) * 2); + lr4->coef = mod_zalloc(mod, sizeof(struct sof_eq_iir_biquad) * 2); if (!lr4->coef) return -ENOMEM; @@ -189,8 +189,7 @@ static int crossover_init_coef_lr4(struct sof_eq_iir_biquad *coef, * delay[0..1] -> state for first biquad * delay[2..3] -> state for second biquad */ - lr4->delay = rzalloc(SOF_MEM_FLAG_USER, - sizeof(uint64_t) * CROSSOVER_NUM_DELAYS_LR4); + lr4->delay = mod_zalloc(mod, sizeof(uint64_t) * CROSSOVER_NUM_DELAYS_LR4); if (!lr4->delay) return -ENOMEM; @@ -203,7 +202,8 @@ static int crossover_init_coef_lr4(struct sof_eq_iir_biquad *coef, /** * \brief Initializes the crossover coefficients for one channel */ -int crossover_init_coef_ch(struct sof_eq_iir_biquad *coef, +int crossover_init_coef_ch(struct processing_module *mod, + struct sof_eq_iir_biquad *coef, struct crossover_state *ch_state, int32_t num_sinks) { @@ -214,12 +214,12 @@ int crossover_init_coef_ch(struct sof_eq_iir_biquad *coef, for (i = 0; i < num_lr4s; i++) { /* Get the low pass coefficients */ - err = crossover_init_coef_lr4(&coef[j], + err = crossover_init_coef_lr4(mod, &coef[j], &ch_state->lowpass[i]); if (err < 0) return -EINVAL; /* Get the high pass coefficients */ - err = crossover_init_coef_lr4(&coef[j + 1], + err = crossover_init_coef_lr4(mod, &coef[j + 1], &ch_state->highpass[i]); if (err < 0) return -EINVAL; @@ -259,13 +259,13 @@ static int crossover_init_coef(struct processing_module *mod, int nch) /* Collect the coef array and assign it to every channel */ crossover = config->coef; for (ch = 0; ch < nch; ch++) { - err = crossover_init_coef_ch(crossover, &cd->state[ch], + err = crossover_init_coef_ch(mod, crossover, &cd->state[ch], config->num_sinks); /* Free all previously allocated blocks in case of an error */ if (err < 0) { comp_err(mod->dev, "crossover_init_coef(), could not assign coefficients to ch %d", ch); - crossover_reset_state(cd); + crossover_reset_state(mod, cd); return err; } } @@ -282,7 +282,7 @@ static int crossover_setup(struct processing_module *mod, int nch) int ret = 0; /* Reset any previous state */ - crossover_reset_state(cd); + crossover_reset_state(mod, cd); /* Assign LR4 coefficients from config */ ret = crossover_init_coef(mod, nch); @@ -312,40 +312,34 @@ static int crossover_init(struct processing_module *mod) return -ENOMEM; } - cd = rzalloc(SOF_MEM_FLAG_USER, sizeof(*cd)); + cd = mod_zalloc(mod, sizeof(*cd)); if (!cd) return -ENOMEM; md->private = cd; /* Handler for configuration data */ - cd->model_handler = comp_data_blob_handler_new(dev); + cd->model_handler = mod_data_blob_handler_new(mod); if (!cd->model_handler) { comp_err(dev, "comp_data_blob_handler_new() failed."); - ret = -ENOMEM; - goto cd_fail; + return -ENOMEM; } /* Get configuration data and reset Crossover state */ ret = comp_init_data_blob(cd->model_handler, bs, ipc_crossover->data); if (ret < 0) { comp_err(dev, "comp_init_data_blob() failed."); - goto cd_fail; + return ret; } ret = crossover_output_pin_init(mod); if (ret < 0) { comp_err(dev, "crossover_init_output_pins() failed."); - goto cd_fail; + return ret; } - crossover_reset_state(cd); + crossover_reset_state(mod, cd); return 0; - -cd_fail: - comp_data_blob_handler_free(cd->model_handler); - rfree(cd); - return ret; } /** @@ -357,11 +351,8 @@ static int crossover_free(struct processing_module *mod) comp_info(mod->dev, "crossover_free()"); - comp_data_blob_handler_free(cd->model_handler); - - crossover_reset_state(cd); + crossover_reset_state(mod, cd); - rfree(cd); return 0; } @@ -616,7 +607,7 @@ static int crossover_reset(struct processing_module *mod) comp_info(mod->dev, "crossover_reset()"); - crossover_reset_state(cd); + crossover_reset_state(mod, cd); cd->crossover_process = NULL; cd->crossover_split = NULL; diff --git a/src/audio/multiband_drc/multiband_drc.c b/src/audio/multiband_drc/multiband_drc.c index 74cdb0ebcdd4..2291d93716bb 100644 --- a/src/audio/multiband_drc/multiband_drc.c +++ b/src/audio/multiband_drc/multiband_drc.c @@ -142,7 +142,7 @@ static int multiband_drc_init_coef(struct processing_module *mod, int16_t nch, u /* Crossover: collect the coef array and assign it to every channel */ crossover = config->crossover_coef; for (ch = 0; ch < nch; ch++) { - ret = crossover_init_coef_ch(crossover, &state->crossover[ch], + ret = crossover_init_coef_ch(mod, crossover, &state->crossover[ch], config->num_bands); /* Free all previously allocated blocks in case of an error */ if (ret < 0) { diff --git a/src/include/module/crossover/crossover_common.h b/src/include/module/crossover/crossover_common.h index 28c6e8aa7775..d238ff7c1008 100644 --- a/src/include/module/crossover/crossover_common.h +++ b/src/include/module/crossover/crossover_common.h @@ -8,6 +8,7 @@ #ifndef __SOF_CROSSOVER_COMMON_H__ #define __SOF_CROSSOVER_COMMON_H__ +#include #include #include @@ -39,17 +40,19 @@ typedef void (*crossover_split)(int32_t in, int32_t out[], extern const crossover_split crossover_split_fnmap[]; /* crossover init function */ -int crossover_init_coef_ch(struct sof_eq_iir_biquad *coef, +int crossover_init_coef_ch(struct processing_module *mod, + struct sof_eq_iir_biquad *coef, struct crossover_state *ch_state, int32_t num_sinks); /** * \brief Reset the state of an LR4 filter. */ -static inline void crossover_reset_state_lr4(struct iir_state_df1 *lr4) +static inline void crossover_reset_state_lr4(struct processing_module *mod, + struct iir_state_df1 *lr4) { - rfree(lr4->coef); - rfree(lr4->delay); + mod_free(mod, lr4->coef); + mod_free(mod, lr4->delay); lr4->coef = NULL; lr4->delay = NULL; @@ -59,13 +62,14 @@ static inline void crossover_reset_state_lr4(struct iir_state_df1 *lr4) * \brief Reset the state (coefficients and delay) of the crossover filter * of a single channel. */ -static inline void crossover_reset_state_ch(struct crossover_state *ch_state) +static inline void crossover_reset_state_ch(struct processing_module *mod, + struct crossover_state *ch_state) { int i; for (i = 0; i < CROSSOVER_MAX_LR4; i++) { - crossover_reset_state_lr4(&ch_state->lowpass[i]); - crossover_reset_state_lr4(&ch_state->highpass[i]); + crossover_reset_state_lr4(mod, &ch_state->lowpass[i]); + crossover_reset_state_lr4(mod, &ch_state->highpass[i]); } } From 44d79a4640c51cd8263cfdba274a1dc60e43001d Mon Sep 17 00:00:00 2001 From: Jyri Sarha Date: Wed, 13 Aug 2025 16:10:33 +0300 Subject: [PATCH 12/18] Audio: multiband_drc: Memory, blob, and fast_get allocs to module API Allocate all memory, blob handlers, and fast_get() buffers through module API mod_alloc() and friends and remove all redundant rfree(), comp_data_blob_handler_free(), and fast_put() calls from module unload functions and init error branches. Signed-off-by: Jyri Sarha --- src/audio/multiband_drc/multiband_drc.c | 61 ++++++++++--------------- src/audio/multiband_drc/multiband_drc.h | 7 +-- 2 files changed, 27 insertions(+), 41 deletions(-) diff --git a/src/audio/multiband_drc/multiband_drc.c b/src/audio/multiband_drc/multiband_drc.c index 2291d93716bb..1c77fc846606 100644 --- a/src/audio/multiband_drc/multiband_drc.c +++ b/src/audio/multiband_drc/multiband_drc.c @@ -42,17 +42,18 @@ SOF_DEFINE_REG_UUID(multiband_drc); DECLARE_TR_CTX(multiband_drc_tr, SOF_UUID(multiband_drc_uuid), LOG_LEVEL_INFO); /* Called from multiband_drc_setup() from multiband_drc_process(), so cannot be __cold */ -static void multiband_drc_reset_state(struct multiband_drc_state *state) +static void multiband_drc_reset_state(struct processing_module *mod, + struct multiband_drc_state *state) { int i; /* Reset emphasis eq-iir state */ for (i = 0; i < PLATFORM_MAX_CHANNELS; i++) - multiband_drc_iir_reset_state_ch(&state->emphasis[i]); + multiband_drc_iir_reset_state_ch(mod, &state->emphasis[i]); /* Reset crossover state */ for (i = 0; i < PLATFORM_MAX_CHANNELS; i++) - crossover_reset_state_ch(&state->crossover[i]); + crossover_reset_state_ch(mod, &state->crossover[i]); /* Reset drc kernel state */ for (i = 0; i < SOF_MULTIBAND_DRC_MAX_BANDS; i++) @@ -60,10 +61,11 @@ static void multiband_drc_reset_state(struct multiband_drc_state *state) /* Reset deemphasis eq-iir state */ for (i = 0; i < PLATFORM_MAX_CHANNELS; i++) - multiband_drc_iir_reset_state_ch(&state->deemphasis[i]); + multiband_drc_iir_reset_state_ch(mod, &state->deemphasis[i]); } -static int multiband_drc_eq_init_coef_ch(struct sof_eq_iir_biquad *coef, +static int multiband_drc_eq_init_coef_ch(struct processing_module *mod, + struct sof_eq_iir_biquad *coef, struct iir_state_df1 *eq) { int ret; @@ -72,8 +74,7 @@ static int multiband_drc_eq_init_coef_ch(struct sof_eq_iir_biquad *coef, if (SOF_EMP_DEEMP_BIQUADS != SOF_IIR_DF1_4TH_NUM_BIQUADS) return -EINVAL; - eq->coef = rzalloc(SOF_MEM_FLAG_USER, - sizeof(struct sof_eq_iir_biquad) * SOF_EMP_DEEMP_BIQUADS); + eq->coef = mod_zalloc(mod, sizeof(struct sof_eq_iir_biquad) * SOF_EMP_DEEMP_BIQUADS); if (!eq->coef) return -ENOMEM; @@ -86,8 +87,7 @@ static int multiband_drc_eq_init_coef_ch(struct sof_eq_iir_biquad *coef, * delay[0..1] -> state for first biquad * delay[2..3] -> state for second biquad */ - eq->delay = rzalloc(SOF_MEM_FLAG_USER, - sizeof(uint64_t) * CROSSOVER_NUM_DELAYS_LR4); + eq->delay = mod_zalloc(mod, sizeof(uint64_t) * CROSSOVER_NUM_DELAYS_LR4); if (!eq->delay) return -ENOMEM; @@ -148,7 +148,7 @@ static int multiband_drc_init_coef(struct processing_module *mod, int16_t nch, u if (ret < 0) { comp_err(dev, "multiband_drc_init_coef(), could not assign coeffs to ch %d", ch); - goto err; + return ret; } } @@ -157,12 +157,12 @@ static int multiband_drc_init_coef(struct processing_module *mod, int16_t nch, u /* Emphasis: collect the coef array and assign it to every channel */ emphasis = config->emp_coef; for (ch = 0; ch < nch; ch++) { - ret = multiband_drc_eq_init_coef_ch(emphasis, &state->emphasis[ch]); + ret = multiband_drc_eq_init_coef_ch(mod, emphasis, &state->emphasis[ch]); /* Free all previously allocated blocks in case of an error */ if (ret < 0) { comp_err(dev, "multiband_drc_init_coef(), could not assign coeffs to ch %d", ch); - goto err; + return ret; } } @@ -171,12 +171,12 @@ static int multiband_drc_init_coef(struct processing_module *mod, int16_t nch, u /* Deemphasis: collect the coef array and assign it to every channel */ deemphasis = config->deemp_coef; for (ch = 0; ch < nch; ch++) { - ret = multiband_drc_eq_init_coef_ch(deemphasis, &state->deemphasis[ch]); + ret = multiband_drc_eq_init_coef_ch(mod, deemphasis, &state->deemphasis[ch]); /* Free all previously allocated blocks in case of an error */ if (ret < 0) { comp_err(dev, "multiband_drc_init_coef(), could not assign coeffs to ch %d", ch); - goto err; + return ret; } } @@ -188,22 +188,18 @@ static int multiband_drc_init_coef(struct processing_module *mod, int16_t nch, u if (ret < 0) { comp_err(dev, "multiband_drc_init_coef(), could not init pre delay buffers"); - goto err; + return ret; } ret = drc_set_pre_delay_time(&state->drc[i], cd->config->drc_coef[i].pre_delay_time, rate); if (ret < 0) { comp_err(dev, "multiband_drc_init_coef(), could not set pre delay time"); - goto err; + return ret; } } return 0; - -err: - multiband_drc_reset_state(state); - return ret; } /* Called from multiband_drc_process(), so cannot be __cold */ @@ -213,7 +209,7 @@ static int multiband_drc_setup(struct processing_module *mod, int16_t channels, struct multiband_drc_comp_data *cd = module_get_private_data(mod); /* Reset any previous state */ - multiband_drc_reset_state(&cd->state); + multiband_drc_reset_state(mod, &cd->state); /* Setup Crossover, Emphasis EQ, Deemphasis EQ, and DRC */ return multiband_drc_init_coef(mod, channels, rate); @@ -243,7 +239,7 @@ static int multiband_drc_init(struct processing_module *mod) return -EINVAL; } - cd = rzalloc(SOF_MEM_FLAG_USER, sizeof(*cd)); + cd = mod_zalloc(mod, sizeof(*cd)); if (!cd) return -ENOMEM; @@ -258,40 +254,29 @@ static int multiband_drc_init(struct processing_module *mod) multiband_drc_process_enable(&cd->process_enabled); /* Handler for configuration data */ - cd->model_handler = comp_data_blob_handler_new(dev); + cd->model_handler = mod_data_blob_handler_new(mod); if (!cd->model_handler) { comp_err(dev, "comp_data_blob_handler_new() failed."); - ret = -ENOMEM; - goto cd_fail; + return -ENOMEM; } /* Get configuration data and reset DRC state */ ret = comp_init_data_blob(cd->model_handler, bs, cfg->data); if (ret < 0) { comp_err(dev, "comp_init_data_blob() failed."); - goto cd_fail; + return ret; } - multiband_drc_reset_state(&cd->state); + multiband_drc_reset_state(mod, &cd->state); return 0; - -cd_fail: - comp_data_blob_handler_free(cd->model_handler); - rfree(cd); - return ret; } __cold static int multiband_drc_free(struct processing_module *mod) { - struct multiband_drc_comp_data *cd = module_get_private_data(mod); - assert_can_be_cold(); comp_info(mod->dev, "multiband_drc_free()"); - comp_data_blob_handler_free(cd->model_handler); - - rfree(cd); return 0; } @@ -415,7 +400,7 @@ static int multiband_drc_reset(struct processing_module *mod) comp_info(mod->dev, "multiband_drc_reset()"); - multiband_drc_reset_state(&cd->state); + multiband_drc_reset_state(mod, &cd->state); cd->source_format = 0; cd->multiband_drc_func = NULL; diff --git a/src/audio/multiband_drc/multiband_drc.h b/src/audio/multiband_drc/multiband_drc.h index 20f939877209..6a99fda55cef 100644 --- a/src/audio/multiband_drc/multiband_drc.h +++ b/src/audio/multiband_drc/multiband_drc.h @@ -89,10 +89,11 @@ static inline multiband_drc_func multiband_drc_find_proc_func_pass(enum sof_ipc_ return NULL; } -static inline void multiband_drc_iir_reset_state_ch(struct iir_state_df1 *iir) +static inline void multiband_drc_iir_reset_state_ch(struct processing_module *mod, + struct iir_state_df1 *iir) { - rfree(iir->coef); - rfree(iir->delay); + mod_free(mod, iir->coef); + mod_free(mod, iir->delay); iir->coef = NULL; iir->delay = NULL; From e201af704e44d21f85f88114a44abbd10fe8264e Mon Sep 17 00:00:00 2001 From: Jyri Sarha Date: Wed, 13 Aug 2025 17:02:48 +0300 Subject: [PATCH 13/18] Audio: DRC: Memory, blob, and fast_get allocs to module API Allocate all memory, blob handlers, and fast_get() buffers through module API mod_alloc() and friends and remove all redundant rfree(), comp_data_blob_handler_free(), and fast_put() calls from module unload functions and init error branches. Signed-off-by: Jyri Sarha --- src/audio/drc/drc.c | 43 ++++++++++--------------- src/audio/drc/drc_algorithm.h | 5 +-- src/audio/multiband_drc/multiband_drc.c | 5 +-- 3 files changed, 23 insertions(+), 30 deletions(-) diff --git a/src/audio/drc/drc.c b/src/audio/drc/drc.c index 5a6397291eda..105d26ebbbba 100644 --- a/src/audio/drc/drc.c +++ b/src/audio/drc/drc.c @@ -20,7 +20,6 @@ #include #include #include -#include #include #include #include @@ -43,11 +42,11 @@ extern const struct sof_uuid drc_uuid; extern struct tr_ctx drc_tr; /* Called from drc_setup() from drc_process(), so cannot be __cold */ -void drc_reset_state(struct drc_state *state) +void drc_reset_state(struct processing_module *mod, struct drc_state *state) { int i; - rfree(state->pre_delay_buffers[0]); + mod_free(mod, state->pre_delay_buffers[0]); for (i = 0; i < PLATFORM_MAX_CHANNELS; ++i) { state->pre_delay_buffers[i] = NULL; } @@ -67,7 +66,8 @@ void drc_reset_state(struct drc_state *state) state->max_attack_compression_diff_db = INT32_MIN; } -int drc_init_pre_delay_buffers(struct drc_state *state, +int drc_init_pre_delay_buffers(struct processing_module *mod, + struct drc_state *state, size_t sample_bytes, int channels) { @@ -76,7 +76,7 @@ int drc_init_pre_delay_buffers(struct drc_state *state, int i; /* Allocate pre-delay (lookahead) buffers */ - state->pre_delay_buffers[0] = rballoc(SOF_MEM_FLAG_USER, bytes_total); + state->pre_delay_buffers[0] = mod_alloc(mod, bytes_total); if (!state->pre_delay_buffers[0]) return -ENOMEM; @@ -121,16 +121,17 @@ int drc_set_pre_delay_time(struct drc_state *state, } /* Called from drc_process(), so cannot be __cold */ -static int drc_setup(struct drc_comp_data *cd, uint16_t channels, uint32_t rate) +static int drc_setup(struct processing_module *mod, uint16_t channels, uint32_t rate) { + struct drc_comp_data *cd = module_get_private_data(mod); uint32_t sample_bytes = get_sample_bytes(cd->source_format); int ret; /* Reset any previous state */ - drc_reset_state(&cd->state); + drc_reset_state(mod, &cd->state); /* Allocate pre-delay buffers */ - ret = drc_init_pre_delay_buffers(&cd->state, (size_t)sample_bytes, (int)channels); + ret = drc_init_pre_delay_buffers(mod, &cd->state, (size_t)sample_bytes, (int)channels); if (ret < 0) return ret; @@ -164,28 +165,27 @@ __cold static int drc_init(struct processing_module *mod) return -EINVAL; } - cd = rzalloc(SOF_MEM_FLAG_USER, sizeof(*cd)); + cd = mod_zalloc(mod, sizeof(*cd)); if (!cd) return -ENOMEM; md->private = cd; /* Handler for configuration data */ - cd->model_handler = comp_data_blob_handler_new(dev); + cd->model_handler = mod_data_blob_handler_new(mod); if (!cd->model_handler) { comp_err(dev, "comp_data_blob_handler_new() failed."); - ret = -ENOMEM; - goto cd_fail; + return -ENOMEM; } /* Get configuration data and reset DRC state */ ret = comp_init_data_blob(cd->model_handler, bs, cfg->data); if (ret < 0) { comp_err(dev, "comp_init_data_blob() failed."); - goto cd_fail; + return ret; } - drc_reset_state(&cd->state); + drc_reset_state(mod, &cd->state); /* Initialize DRC to enabled. If defined by topology, a control may set * enabled to false before prepare() or during streaming with the switch @@ -194,21 +194,12 @@ __cold static int drc_init(struct processing_module *mod) cd->enabled = true; cd->enable_switch = true; return 0; - -cd_fail: - comp_data_blob_handler_free(cd->model_handler); - rfree(cd); - return ret; } __cold static int drc_free(struct processing_module *mod) { - struct drc_comp_data *cd = module_get_private_data(mod); - assert_can_be_cold(); - comp_data_blob_handler_free(cd->model_handler); - rfree(cd); return 0; } @@ -284,7 +275,7 @@ static int drc_process(struct processing_module *mod, /* Check for changed configuration */ if (comp_is_new_data_blob_available(cd->model_handler)) { cd->config = comp_get_data_blob(cd->model_handler, NULL, NULL); - ret = drc_setup(cd, audio_stream_get_channels(source), + ret = drc_setup(mod, audio_stream_get_channels(source), audio_stream_get_rate(source)); if (ret < 0) { comp_err(dev, "drc_copy(), failed DRC setup"); @@ -370,7 +361,7 @@ static int drc_prepare(struct processing_module *mod, comp_info(dev, "drc_prepare(), source_format=%d", cd->source_format); cd->config = comp_get_data_blob(cd->model_handler, NULL, NULL); if (cd->config) { - ret = drc_setup(cd, channels, rate); + ret = drc_setup(mod, channels, rate); if (ret < 0) { comp_err(dev, "drc_prepare() error: drc_setup failed."); return ret; @@ -403,7 +394,7 @@ static int drc_reset(struct processing_module *mod) { struct drc_comp_data *cd = module_get_private_data(mod); - drc_reset_state(&cd->state); + drc_reset_state(mod, &cd->state); return 0; } diff --git a/src/audio/drc/drc_algorithm.h b/src/audio/drc/drc_algorithm.h index c0a942b09622..8d9d759eb3a8 100644 --- a/src/audio/drc/drc_algorithm.h +++ b/src/audio/drc/drc_algorithm.h @@ -14,10 +14,11 @@ #include "drc.h" /* drc reset function */ -void drc_reset_state(struct drc_state *state); +void drc_reset_state(struct processing_module *mod, struct drc_state *state); /* drc init functions */ -int drc_init_pre_delay_buffers(struct drc_state *state, +int drc_init_pre_delay_buffers(struct processing_module *mod, + struct drc_state *state, size_t sample_bytes, int channels); int drc_set_pre_delay_time(struct drc_state *state, diff --git a/src/audio/multiband_drc/multiband_drc.c b/src/audio/multiband_drc/multiband_drc.c index 1c77fc846606..97030ec83a15 100644 --- a/src/audio/multiband_drc/multiband_drc.c +++ b/src/audio/multiband_drc/multiband_drc.c @@ -57,7 +57,7 @@ static void multiband_drc_reset_state(struct processing_module *mod, /* Reset drc kernel state */ for (i = 0; i < SOF_MULTIBAND_DRC_MAX_BANDS; i++) - drc_reset_state(&state->drc[i]); + drc_reset_state(mod, &state->drc[i]); /* Reset deemphasis eq-iir state */ for (i = 0; i < PLATFORM_MAX_CHANNELS; i++) @@ -184,7 +184,8 @@ static int multiband_drc_init_coef(struct processing_module *mod, int16_t nch, u for (i = 0; i < num_bands; i++) { comp_info(dev, "multiband_drc_init_coef(), initializing drc band %d", i); - ret = drc_init_pre_delay_buffers(&state->drc[i], (size_t)sample_bytes, (int)nch); + ret = drc_init_pre_delay_buffers(mod, &state->drc[i], + (size_t)sample_bytes, (int)nch); if (ret < 0) { comp_err(dev, "multiband_drc_init_coef(), could not init pre delay buffers"); From 310b58fad573c96d142fc20ae754ded5d4cec6e7 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Thu, 21 Aug 2025 14:44:42 +0200 Subject: [PATCH 14/18] component: split a function into two Split comp_alloc() into two parts - allocation and initialisation to be able to re-use the initialisation code with a different allocation method. Signed-off-by: Guennadi Liakhovetski --- src/include/sof/audio/component.h | 32 +++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/src/include/sof/audio/component.h b/src/include/sof/audio/component.h index 7f71af8f8025..da9edc490fc7 100644 --- a/src/include/sof/audio/component.h +++ b/src/include/sof/audio/component.h @@ -847,6 +847,24 @@ static inline enum sof_comp_type dev_comp_type(const struct comp_dev *dev) return dev->ipc_config.type; } +/** + * Initialize common part of a component device + * @param drv Parent component driver. + * @param dev Device. + * @param bytes Size of the component device in bytes. + */ +static inline void comp_init(const struct comp_driver *drv, + struct comp_dev *dev, size_t bytes) +{ + dev->size = bytes; + dev->drv = drv; + dev->state = COMP_STATE_INIT; + list_init(&dev->bsink_list); + list_init(&dev->bsource_list); + memcpy_s(&dev->tctx, sizeof(struct tr_ctx), + trace_comp_drv_get_tr_ctx(dev->drv), sizeof(struct tr_ctx)); +} + /** * Allocates memory for the component device and initializes common part. * @param drv Parent component driver. @@ -856,22 +874,16 @@ static inline enum sof_comp_type dev_comp_type(const struct comp_dev *dev) static inline struct comp_dev *comp_alloc(const struct comp_driver *drv, size_t bytes) { - struct comp_dev *dev = NULL; - /* * Use uncached address everywhere to access components to rule out * multi-core failures. TODO: verify if cached alias may be used in some cases */ - dev = rzalloc(SOF_MEM_FLAG_USER | SOF_MEM_FLAG_COHERENT, bytes); + struct comp_dev *dev = rzalloc(SOF_MEM_FLAG_USER | SOF_MEM_FLAG_COHERENT, bytes); + if (!dev) return NULL; - dev->size = bytes; - dev->drv = drv; - dev->state = COMP_STATE_INIT; - list_init(&dev->bsink_list); - list_init(&dev->bsource_list); - memcpy_s(&dev->tctx, sizeof(struct tr_ctx), - trace_comp_drv_get_tr_ctx(dev->drv), sizeof(struct tr_ctx)); + + comp_init(drv, dev, bytes); return dev; } From 23802efcd816ff080f682b68b96301a7db9f8b91 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Fri, 22 Aug 2025 13:42:08 +0200 Subject: [PATCH 15/18] 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 | 26 +++++++++++++++++++++++++- 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/zephyr/include/rtos/alloc.h b/zephyr/include/rtos/alloc.h index 600852418693..818759434726 100644 --- a/zephyr/include/rtos/alloc.h +++ b/zephyr/include/rtos/alloc.h @@ -106,6 +106,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 baf93ed159f1..4ade4bcd2f4e 100644 --- a/zephyr/lib/alloc.c +++ b/zephyr/lib/alloc.c @@ -353,7 +353,7 @@ static void __sparse_cache *heap_alloc_aligned_cached(struct k_heap *h, */ #ifdef CONFIG_SOF_ZEPHYR_HEAP_CACHED min_align = MAX(PLATFORM_DCACHE_ALIGN, min_align); - bytes = ALIGN_UP(bytes, min_align); + bytes = ALIGN_UP(bytes, PLATFORM_DCACHE_ALIGN); #endif ptr = (__sparse_force void __sparse_cache *)heap_alloc_aligned(h, min_align, bytes); @@ -533,6 +533,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); From c25c6e3384e739838225463a20da55ec455e6062 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Fri, 22 Aug 2025 13:48:13 +0200 Subject: [PATCH 16/18] module-adapter: allocate control objects on an own heap We want to be able to serve all module memory allocations from a private heap. This commit creates such a heap for DP scheduled modules and moves struct comp_dev and struct processing_module to it. Signed-off-by: Guennadi Liakhovetski --- src/audio/module_adapter/module_adapter.c | 72 +++++++++++++++---- .../sof/audio/module_adapter/module/generic.h | 2 + 2 files changed, 61 insertions(+), 13 deletions(-) diff --git a/src/audio/module_adapter/module_adapter.c b/src/audio/module_adapter/module_adapter.c index 32ef202579eb..6b99894b139e 100644 --- a/src/audio/module_adapter/module_adapter.c +++ b/src/audio/module_adapter/module_adapter.c @@ -74,12 +74,32 @@ 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, "module_adapter_new(), failed to allocate memory for comp_dev"); - return NULL; + uint8_t *mod_heap_mem; + struct k_heap *mod_heap; + int flags; + + if (config->proc_domain == COMP_PROCESSING_DOMAIN_DP) { + const size_t heap_size = 8 * 1024; + + /* Keep uncached to match the default SOF heap! */ + mod_heap_mem = rballoc_align(SOF_MEM_FLAG_USER | SOF_MEM_FLAG_COHERENT, + heap_size, 4096); + if (!mod_heap_mem) + return NULL; + + const size_t heap_pref_size = ALIGN_UP(sizeof(*mod_heap), 8); + void *mod_heap_buf = mod_heap_mem + heap_pref_size; + + mod_heap = (struct k_heap *)mod_heap_mem; + k_heap_init(mod_heap, mod_heap_buf, heap_size - heap_pref_size); + + flags = SOF_MEM_FLAG_COHERENT; + } else { + mod_heap_mem = NULL; + mod_heap = NULL; + + flags = 0; } - dev->ipc_config = *config; /* allocate module information. * for DP shared modules this struct must be accessible from all cores @@ -87,15 +107,32 @@ struct comp_dev *module_adapter_new_ext(const struct comp_driver *drv, * 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; - mod = rzalloc(flags, sizeof(*mod)); + mod = sof_heap_alloc(mod_heap, flags, sizeof(*mod), 0); if (!mod) { - comp_err(dev, "module_adapter_new(), failed to allocate memory for module"); + comp_cl_err(drv, "module_adapter_new(), failed to allocate memory for module"); + goto emod; + } + + memset(mod, 0, sizeof(*mod)); + mod->priv.resources.heap = mod_heap; + mod->priv.resources.heap_mem = mod_heap_mem; + + /* + * comp_alloc() always allocated dev uncached. Would be difficult to optimize. Only + * if the whole currently active topology is running on the primary core, then it + * can be cached. Effectively it can be only cached in single-core configurations. + */ + dev = sof_heap_alloc(mod_heap, SOF_MEM_FLAG_COHERENT, sizeof(*dev), 0); + if (!dev) { + comp_cl_err(drv, "module_adapter_new(), failed to allocate memory for comp_dev"); goto err; } + memset(dev, 0, sizeof(*dev)); + comp_init(drv, dev, sizeof(*dev)); + dev->ipc_config = *config; + dst = &mod->priv.cfg; module_set_private_data(mod, mod_priv); @@ -159,13 +196,17 @@ struct comp_dev *module_adapter_new_ext(const struct comp_driver *drv, comp_dbg(dev, "module_adapter_new() done"); return dev; + err: #if CONFIG_IPC_MAJOR_4 if (mod) rfree(mod->priv.cfg.input_pins); #endif - rfree(mod); - rfree(dev); + sof_heap_free(mod_heap, dev); + sof_heap_free(mod_heap, mod); +emod: + rfree(mod_heap_mem); + return NULL; } EXPORT_SYMBOL(module_adapter_new); @@ -1285,8 +1326,13 @@ void module_adapter_free(struct comp_dev *dev) #endif rfree(mod->stream_params); - rfree(mod); - rfree(dev); + + struct k_heap *mod_heap = mod->priv.resources.heap; + void *mem = mod->priv.resources.heap_mem; + + sof_heap_free(mod_heap, mod); + sof_heap_free(mod_heap, dev); + rfree(mem); } EXPORT_SYMBOL(module_adapter_free); diff --git a/src/include/sof/audio/module_adapter/module/generic.h b/src/include/sof/audio/module_adapter/module/generic.h index 1916ef3e040b..74b841bacb04 100644 --- a/src/include/sof/audio/module_adapter/module/generic.h +++ b/src/include/sof/audio/module_adapter/module/generic.h @@ -132,6 +132,8 @@ struct module_resources { struct list_item cont_chunk_list; /**< Memory container chunks */ size_t heap_usage; size_t heap_high_water_mark; + struct k_heap *heap; + void *heap_mem; #if CONFIG_MODULE_MEMORY_API_DEBUG && defined(__ZEPHYR__) k_tid_t rsrc_mngr; #endif From d95b3d923d3c80de8ee8bf2457c6210fd7223d47 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Fri, 22 Aug 2025 09:59:05 +0200 Subject: [PATCH 17/18] module-adapter: move mod_alloc() allocations to the module heap Move mod_alloc() allocations, including the container pool, to the module local heap. Signed-off-by: Guennadi Liakhovetski --- src/audio/module_adapter/module/generic.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/audio/module_adapter/module/generic.c b/src/audio/module_adapter/module/generic.c index f910fb5be0f3..d2113968e41a 100644 --- a/src/audio/module_adapter/module/generic.c +++ b/src/audio/module_adapter/module/generic.c @@ -134,10 +134,11 @@ struct container_chunk { static struct module_memory *container_get(struct processing_module *mod) { struct module_resources *res = &mod->priv.resources; + struct k_heap *mod_heap = res->heap; struct module_memory *container; if (list_is_empty(&res->free_cont_list)) { - struct container_chunk *chunk = rzalloc(SOF_MEM_FLAG_USER, sizeof(*chunk)); + struct container_chunk *chunk = sof_heap_alloc(mod_heap, 0, sizeof(*chunk), 0); int i; if (!chunk) { @@ -145,6 +146,8 @@ static struct module_memory *container_get(struct processing_module *mod) return NULL; } + memset(chunk, 0, sizeof(*chunk)); + list_item_append(&chunk->chunk_list, &res->cont_chunk_list); for (i = 0; i < ARRAY_SIZE(chunk->containers); i++) list_item_append(&chunk->containers[i].mem_list, &res->free_cont_list); @@ -175,6 +178,7 @@ void *mod_alloc_align(struct processing_module *mod, uint32_t size, uint32_t ali { struct module_memory *container = container_get(mod); struct module_resources *res = &mod->priv.resources; + struct k_heap *mod_heap = res->heap; void *ptr; MEM_API_CHECK_THREAD(res); @@ -188,11 +192,7 @@ void *mod_alloc_align(struct processing_module *mod, uint32_t size, uint32_t ali } /* Allocate memory for module */ - if (alignment) - ptr = rballoc_align(SOF_MEM_FLAG_USER, size, alignment); - else - ptr = rballoc(SOF_MEM_FLAG_USER, size); - + ptr = sof_heap_alloc(mod_heap, 0, size, alignment); if (!ptr) { comp_err(mod->dev, "mod_alloc: failed to allocate memory for comp %x.", dev_comp_id(mod->dev)); @@ -324,6 +324,7 @@ EXPORT_SYMBOL(mod_fast_get); int mod_free(struct processing_module *mod, const void *ptr) { struct module_resources *res = &mod->priv.resources; + struct k_heap *mod_heap = res->heap; struct module_memory *mem; struct list_item *mem_list; struct list_item *_mem_list; @@ -339,7 +340,7 @@ int mod_free(struct processing_module *mod, const void *ptr) if (mem->free) { mem->free(mem->ptr); } else { - rfree(mem->ptr); + sof_heap_free(mod_heap, mem->ptr); res->heap_usage -= mem->size; } list_item_del(&mem->mem_list); @@ -550,6 +551,7 @@ int module_reset(struct processing_module *mod) void mod_free_all(struct processing_module *mod) { struct module_resources *res = &mod->priv.resources; + struct k_heap *mod_heap = res->heap; struct list_item *list; struct list_item *_list; @@ -561,7 +563,7 @@ void mod_free_all(struct processing_module *mod) if (mem->free) mem->free(mem->ptr); else - rfree(mem->ptr); + sof_heap_free(mod_heap, mem->ptr); list_item_del(&mem->mem_list); } @@ -570,7 +572,7 @@ void mod_free_all(struct processing_module *mod) container_of(list, struct container_chunk, chunk_list); list_item_del(&chunk->chunk_list); - rfree(chunk); + sof_heap_free(mod_heap, chunk); } } EXPORT_SYMBOL(mod_free_all); From 3e114aca9f380a09912a5be17f1907e74df30220 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Fri, 22 Aug 2025 10:03:21 +0200 Subject: [PATCH 18/18] module-adapter: move stream parameters to the module heap Stream parameters are only used by respective modules, move them to the module's own heap. Signed-off-by: Guennadi Liakhovetski --- src/audio/module_adapter/module_adapter.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/audio/module_adapter/module_adapter.c b/src/audio/module_adapter/module_adapter.c index 6b99894b139e..0fa88fa3d658 100644 --- a/src/audio/module_adapter/module_adapter.c +++ b/src/audio/module_adapter/module_adapter.c @@ -562,6 +562,7 @@ int module_adapter_params(struct comp_dev *dev, struct sof_ipc_stream_params *pa { int ret; struct processing_module *mod = comp_mod(dev); + struct k_heap *mod_heap = mod->priv.resources.heap; module_adapter_set_params(mod, params); @@ -572,11 +573,11 @@ int module_adapter_params(struct comp_dev *dev, struct sof_ipc_stream_params *pa } /* allocate stream_params each time */ - if (mod->stream_params) - rfree(mod->stream_params); + sof_heap_free(mod_heap, mod->stream_params); - mod->stream_params = rzalloc(SOF_MEM_FLAG_USER, - sizeof(*mod->stream_params) + params->ext_data_length); + mod->stream_params = sof_heap_alloc(mod_heap, 0, + sizeof(*mod->stream_params) + params->ext_data_length, + 0); if (!mod->stream_params) return -ENOMEM; @@ -1252,6 +1253,7 @@ int module_adapter_reset(struct comp_dev *dev) { int ret, i; struct processing_module *mod = comp_mod(dev); + struct k_heap *mod_heap = mod->priv.resources.heap; struct list_item *blist; comp_dbg(dev, "resetting"); @@ -1287,7 +1289,7 @@ int module_adapter_reset(struct comp_dev *dev) buffer_zero(buffer); } - rfree(mod->stream_params); + sof_heap_free(mod_heap, mod->stream_params); mod->stream_params = NULL; comp_dbg(dev, "done"); @@ -1325,11 +1327,10 @@ void module_adapter_free(struct comp_dev *dev) rfree(mod->priv.cfg.input_pins); #endif - rfree(mod->stream_params); - struct k_heap *mod_heap = mod->priv.resources.heap; void *mem = mod->priv.resources.heap_mem; + sof_heap_free(mod_heap, mod->stream_params); sof_heap_free(mod_heap, mod); sof_heap_free(mod_heap, dev); rfree(mem);