diff --git a/posix/include/rtos/mutex.h b/posix/include/rtos/mutex.h index 19b360bdaea5..f82b4169d73c 100644 --- a/posix/include/rtos/mutex.h +++ b/posix/include/rtos/mutex.h @@ -16,6 +16,7 @@ #include #define K_FOREVER ((k_timeout_t) { .ticks = 0xffffffff }) +#define K_MUTEX_DEFINE(name) struct k_mutex name struct k_mutex { struct k_spinlock lock; diff --git a/src/audio/module_adapter/module/generic.c b/src/audio/module_adapter/module/generic.c index ee1b2df92829..37071a2448e3 100644 --- a/src/audio/module_adapter/module/generic.c +++ b/src/audio/module_adapter/module/generic.c @@ -28,6 +28,15 @@ LOG_MODULE_DECLARE(module_adapter, CONFIG_SOF_LOG_LEVEL); +/* + * A single lock shared by all module resource pools. The resource API is only + * ever entered from supervisor context (the z_impl_* syscall bodies), so the + * lock does not need to live in the per-module, user-writable struct - a static + * kernel object serialises all pools. Contention is negligible because resource + * bookkeeping only happens at module setup/teardown, not on the processing path. + */ +static K_MUTEX_DEFINE(mod_res_lock); + int module_load_config(struct comp_dev *dev, const void *cfg, size_t size) { int ret; @@ -79,7 +88,6 @@ void mod_resource_init(struct processing_module *mod) struct module_resources *res = &mod->priv.resources; /* Init memory list */ - k_mutex_init(&res->lock); list_init(&res->objpool.list); res->objpool.heap = res->alloc->heap; res->objpool.vreg = res->alloc->vreg; @@ -179,18 +187,18 @@ void *z_impl_mod_balloc_align(struct processing_module *mod, size_t size, size_t struct module_resources *res = &mod->priv.resources; struct module_resource *container; - k_mutex_lock(&res->lock, K_FOREVER); + k_mutex_lock(&mod_res_lock, K_FOREVER); container = container_get(mod); if (!container) { - k_mutex_unlock(&res->lock); + k_mutex_unlock(&mod_res_lock); return NULL; } if (!size) { comp_err(mod->dev, "requested allocation of 0 bytes."); container_put(mod, container); - k_mutex_unlock(&res->lock); + k_mutex_unlock(&mod_res_lock); return NULL; } @@ -202,7 +210,7 @@ void *z_impl_mod_balloc_align(struct processing_module *mod, size_t size, size_t comp_err(mod->dev, "Failed to alloc %zu bytes %zu alignment for comp %#x.", size, alignment, dev_comp_id(mod->dev)); container_put(mod, container); - k_mutex_unlock(&res->lock); + k_mutex_unlock(&mod_res_lock); return NULL; } /* Store reference to allocated memory */ @@ -214,7 +222,7 @@ void *z_impl_mod_balloc_align(struct processing_module *mod, size_t size, size_t if (res->heap_usage > res->heap_high_water_mark) res->heap_high_water_mark = res->heap_usage; - k_mutex_unlock(&res->lock); + k_mutex_unlock(&mod_res_lock); return ptr; } EXPORT_SYMBOL(z_impl_mod_balloc_align); @@ -235,18 +243,18 @@ void *z_impl_mod_alloc_ext(struct processing_module *mod, uint32_t flags, size_t struct module_resources *res = &mod->priv.resources; struct module_resource *container; - k_mutex_lock(&res->lock, K_FOREVER); + k_mutex_lock(&mod_res_lock, K_FOREVER); container = container_get(mod); if (!container) { - k_mutex_unlock(&res->lock); + k_mutex_unlock(&mod_res_lock); return NULL; } if (!size) { comp_err(mod->dev, "requested allocation of 0 bytes."); container_put(mod, container); - k_mutex_unlock(&res->lock); + k_mutex_unlock(&mod_res_lock); return NULL; } @@ -257,7 +265,7 @@ void *z_impl_mod_alloc_ext(struct processing_module *mod, uint32_t flags, size_t comp_err(mod->dev, "Failed to alloc %zu bytes %zu alignment for comp %#x.", size, alignment, dev_comp_id(mod->dev)); container_put(mod, container); - k_mutex_unlock(&res->lock); + k_mutex_unlock(&mod_res_lock); return NULL; } /* Store reference to allocated memory */ @@ -269,7 +277,7 @@ void *z_impl_mod_alloc_ext(struct processing_module *mod, uint32_t flags, size_t if (res->heap_usage > res->heap_high_water_mark) res->heap_high_water_mark = res->heap_usage; - k_mutex_unlock(&res->lock); + k_mutex_unlock(&mod_res_lock); return ptr; } EXPORT_SYMBOL(z_impl_mod_alloc_ext); @@ -284,22 +292,21 @@ EXPORT_SYMBOL(z_impl_mod_alloc_ext); #if CONFIG_COMP_BLOB struct comp_data_blob_handler *z_impl_mod_data_blob_handler_new(struct processing_module *mod) { - struct module_resources *res = &mod->priv.resources; struct comp_data_blob_handler *bhp; struct module_resource *container; - k_mutex_lock(&res->lock, K_FOREVER); + k_mutex_lock(&mod_res_lock, K_FOREVER); container = container_get(mod); if (!container) { - k_mutex_unlock(&res->lock); + k_mutex_unlock(&mod_res_lock); return NULL; } bhp = comp_data_blob_handler_new_ext(mod->dev, false, NULL, NULL); if (!bhp) { container_put(mod, container); - k_mutex_unlock(&res->lock); + k_mutex_unlock(&mod_res_lock); return NULL; } @@ -307,7 +314,7 @@ struct comp_data_blob_handler *z_impl_mod_data_blob_handler_new(struct processin container->size = 0; container->type = MOD_RES_BLOB_HANDLER; - k_mutex_unlock(&res->lock); + k_mutex_unlock(&mod_res_lock); return bhp; } EXPORT_SYMBOL(z_impl_mod_data_blob_handler_new); @@ -328,18 +335,18 @@ const void *z_impl_mod_fast_get(struct processing_module *mod, const void * cons struct module_resource *container; const void *ptr; - k_mutex_lock(&res->lock, K_FOREVER); + k_mutex_lock(&mod_res_lock, K_FOREVER); container = container_get(mod); if (!container) { - k_mutex_unlock(&res->lock); + k_mutex_unlock(&mod_res_lock); return NULL; } ptr = fast_get(res->alloc, dram_ptr, size); if (!ptr) { container_put(mod, container); - k_mutex_unlock(&res->lock); + k_mutex_unlock(&mod_res_lock); return NULL; } @@ -347,7 +354,7 @@ const void *z_impl_mod_fast_get(struct processing_module *mod, const void * cons container->size = 0; container->type = MOD_RES_FAST_GET; - k_mutex_unlock(&res->lock); + k_mutex_unlock(&mod_res_lock); return ptr; } EXPORT_SYMBOL(z_impl_mod_fast_get); @@ -425,10 +432,10 @@ int z_impl_mod_free(struct processing_module *mod, const void *ptr) /* Find which container holds this memory */ struct mod_res_cb_arg cb_arg = {mod, ptr}; - k_mutex_lock(&res->lock, K_FOREVER); + k_mutex_lock(&mod_res_lock, K_FOREVER); int ret = objpool_iterate(&res->objpool, mod_res_free, &cb_arg); - k_mutex_unlock(&res->lock); + k_mutex_unlock(&mod_res_lock); if (ret < 0) comp_err(mod->dev, "error: could not find memory pointed by %p", ptr); @@ -501,6 +508,20 @@ int z_vrfy_mod_free(struct processing_module *mod, const void *ptr) } #include +void z_vrfy_mod_free_all(struct processing_module *mod) +{ + size_t h_size = 0; + uintptr_t h_start; + + K_OOPS(K_SYSCALL_MEMORY_WRITE(mod, sizeof(*mod))); + mod_heap_info(mod, &h_size, &h_start); + if (h_size) + K_OOPS(K_SYSCALL_MEMORY_WRITE(h_start, h_size)); + + z_impl_mod_free_all(mod); +} +#include + #if CONFIG_COMP_BLOB struct comp_data_blob_handler *z_vrfy_mod_data_blob_handler_new(struct processing_module *mod) { @@ -734,21 +755,22 @@ int module_reset(struct processing_module *mod) * * This function is called automatically when the module is unloaded. */ -void mod_free_all(struct processing_module *mod) +void z_impl_mod_free_all(struct processing_module *mod) { struct module_resources *res = &mod->priv.resources; /* Free all contents found in used containers */ struct mod_res_cb_arg cb_arg = {mod, NULL}; - k_mutex_lock(&res->lock, K_FOREVER); + k_mutex_lock(&mod_res_lock, K_FOREVER); objpool_iterate(&res->objpool, mod_res_free, &cb_arg); objpool_prune(&res->objpool); - k_mutex_unlock(&res->lock); + k_mutex_unlock(&mod_res_lock); /* Make sure resource lists and accounting are reset */ mod_resource_init(mod); } +EXPORT_SYMBOL(z_impl_mod_free_all); int module_free(struct processing_module *mod) { diff --git a/src/include/sof/audio/module_adapter/module/generic.h b/src/include/sof/audio/module_adapter/module/generic.h index 6740593a7cf1..70fb602d1aca 100644 --- a/src/include/sof/audio/module_adapter/module/generic.h +++ b/src/include/sof/audio/module_adapter/module/generic.h @@ -125,7 +125,6 @@ struct module_param { * when the module unloads. */ struct module_resources { - struct k_mutex lock; struct objpool_head objpool; size_t heap_usage; size_t heap_high_water_mark; @@ -197,12 +196,15 @@ void mod_heap_info(struct processing_module *mod, size_t *size, uintptr_t *start __syscall void *mod_alloc_ext(struct processing_module *mod, uint32_t flags, size_t size, size_t alignment); __syscall int mod_free(struct processing_module *mod, const void *ptr); +__syscall void mod_free_all(struct processing_module *mod); #else void *z_impl_mod_alloc_ext(struct processing_module *mod, uint32_t flags, size_t size, size_t alignment); int z_impl_mod_free(struct processing_module *mod, const void *ptr); +void z_impl_mod_free_all(struct processing_module *mod); #define mod_alloc_ext z_impl_mod_alloc_ext #define mod_free z_impl_mod_free +#define mod_free_all z_impl_mod_free_all #endif /** @@ -259,7 +261,6 @@ const void *z_impl_mod_fast_get(struct processing_module *mod, const void * cons #endif 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, struct sof_sink **sinks, int num_of_sinks);