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 da0353d892ab..5fb8dc990218 100644 --- a/src/audio/module_adapter/module_adapter.c +++ b/src/audio/module_adapter/module_adapter.c @@ -1291,10 +1291,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 */