Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions posix/include/rtos/alloc.h
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,14 @@ void rfree(void *ptr);
*/
void *rzalloc_core_sys(int core, size_t bytes);

struct k_heap;
static inline void k_heap_init(struct k_heap *heap, void *mem, size_t bytes)
{
}
void *sof_heap_alloc(struct k_heap *heap, uint32_t flags, size_t bytes,
size_t alignment);
void sof_heap_free(struct k_heap *heap, void *addr);

/**
* Calculates length of the null-terminated string.
* @param s String.
Expand Down
4 changes: 4 additions & 0 deletions posix/include/rtos/kernel.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,8 @@ static inline void k_usleep(int32_t us)
wait_delay_us(us);
}

struct k_heap {
int unused;
};

#endif /* __POSIX_RTOS_KERNEL_H__ */
13 changes: 7 additions & 6 deletions src/audio/module_adapter/module/generic.c
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ static void container_put(struct processing_module *mod, struct module_resource

/**
* Allocates aligned buffer memory block for module.
* @param mod Pointer to the module this memory block is allocatd for.
* @param mod Pointer to the module this memory block is allocated for.
* @param bytes Size in bytes.
* @param alignment Alignment in bytes.
* @return Pointer to the allocated memory or NULL if failed.
Expand Down Expand Up @@ -218,15 +218,16 @@ void *mod_balloc_align(struct processing_module *mod, size_t size, size_t alignm
EXPORT_SYMBOL(mod_balloc_align);

/**
* Allocates aligned memory block for module.
* @param mod Pointer to the module this memory block is allocatd for.
* Allocates aligned memory block with flags for module.
* @param mod Pointer to the module this memory block is allocated for.
* @param flags Allocator flags.
* @param bytes Size in bytes.
* @param alignment Alignment in bytes.
* @return Pointer to the allocated memory or NULL if failed.
*
* The allocated memory is automatically freed when the module is unloaded.
*/
void *mod_alloc_align(struct processing_module *mod, size_t size, size_t alignment)
void *mod_alloc_ext(struct processing_module *mod, uint32_t flags, size_t size, size_t alignment)
{
struct module_resources *res = &mod->priv.resources;
struct module_resource *container;
Expand All @@ -245,7 +246,7 @@ void *mod_alloc_align(struct processing_module *mod, size_t size, size_t alignme
}

/* Allocate memory for module */
ptr = rmalloc_align(SOF_MEM_FLAG_USER, size, alignment);
ptr = rmalloc_align(flags, size, alignment);

if (!ptr) {
comp_err(mod->dev, "Failed to alloc %zu bytes %zu alignment for comp %#x.",
Expand All @@ -265,7 +266,7 @@ void *mod_alloc_align(struct processing_module *mod, size_t size, size_t alignme

return ptr;
}
EXPORT_SYMBOL(mod_alloc_align);
EXPORT_SYMBOL(mod_alloc_ext);

/**
* Creates a blob handler and releases it when the module is unloaded
Expand Down
95 changes: 59 additions & 36 deletions src/audio/module_adapter/module_adapter.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,56 @@ struct comp_dev *module_adapter_new(const struct comp_driver *drv,
return module_adapter_new_ext(drv, config, spec, NULL);
}

static struct processing_module *module_adapter_mem_alloc(const struct comp_driver *drv,
const struct comp_ipc_config *config)
{
struct comp_dev *dev = comp_alloc(drv, sizeof(*dev));

if (!dev) {
comp_cl_err(drv, "failed to allocate memory for comp_dev");
return NULL;
}

/* allocate module information.
* for DP shared modules this struct must be accessible from all cores
* Unfortunately at this point there's no information of components the module
* will be bound to. So we need to allocate shared memory for each DP module
* To be removed when pipeline 2.0 is ready
*/
int flags = config->proc_domain == COMP_PROCESSING_DOMAIN_DP ?
SOF_MEM_FLAG_USER | SOF_MEM_FLAG_COHERENT : SOF_MEM_FLAG_USER;

struct processing_module *mod = module_driver_heap_rzalloc(drv->user_heap, flags,
sizeof(*mod));

if (!mod) {
comp_err(dev, "failed to allocate memory for module");
goto err;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you consider moving the code from the 'err' label to this location?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm usually all for "early returns," i.e. for

if (fail)
    return;

instead of

    if (fail)
        goto err;
...
    return 0;
err:
    return -EINVAL;

but if there's some cleanup to be done in (all) error cases, I usually prefer a goto. When there's only one error case - well, that's a grey zone for me... But since we're likely to extend this function in the future, I'd rather keep it this way.

}

dev->ipc_config = *config;
mod->dev = dev;
dev->mod = mod;

return mod;

err:
module_driver_heap_free(drv->user_heap, dev);

return NULL;
}

static void module_adapter_mem_free(struct processing_module *mod)
{
const struct comp_driver *drv = mod->dev->drv;

#if CONFIG_IPC_MAJOR_4
module_driver_heap_free(drv->user_heap, mod->priv.cfg.input_pins);
#endif
module_driver_heap_free(drv->user_heap, mod->dev);
module_driver_heap_free(drv->user_heap, mod);
}

/*
* \brief Create a module adapter component.
* \param[in] drv - component driver pointer.
Expand All @@ -61,8 +111,6 @@ struct comp_dev *module_adapter_new_ext(const struct comp_driver *drv,
void *mod_priv)
{
int ret;
struct comp_dev *dev;
struct processing_module *mod;
struct module_config *dst;
const struct module_interface *const interface = drv->adapter_ops;

Expand All @@ -74,33 +122,16 @@ struct comp_dev *module_adapter_new_ext(const struct comp_driver *drv,
return NULL;
}

dev = comp_alloc(drv, sizeof(*dev));
if (!dev) {
comp_cl_err(drv, "failed to allocate memory for comp_dev");
return NULL;
}
dev->ipc_config = *config;
struct processing_module *mod = module_adapter_mem_alloc(drv, config);

/* allocate module information.
* for DP shared modules this struct must be accessible from all cores
* Unfortunately at this point there's no information of components the module
* will be bound to. So we need to allocate shared memory for each DP module
* To be removed when pipeline 2.0 is ready
*/
int flags = config->proc_domain == COMP_PROCESSING_DOMAIN_DP ?
SOF_MEM_FLAG_USER | SOF_MEM_FLAG_COHERENT : SOF_MEM_FLAG_USER;

mod = module_driver_heap_rzalloc(drv->user_heap, flags, sizeof(*mod));
if (!mod) {
comp_err(dev, "failed to allocate memory for module");
goto err;
}
if (!mod)
return NULL;

dst = &mod->priv.cfg;

module_set_private_data(mod, mod_priv);
mod->dev = dev;
dev->mod = mod;

struct comp_dev *dev = mod->dev;

list_init(&mod->raw_data_buffers_list);

Expand Down Expand Up @@ -178,13 +209,10 @@ struct comp_dev *module_adapter_new_ext(const struct comp_driver *drv,

comp_dbg(dev, "done");
return dev;

err:
#if CONFIG_IPC_MAJOR_4
if (mod)
rfree(mod->priv.cfg.input_pins);
#endif
rfree(mod);
rfree(dev);
module_adapter_mem_free(mod);

return NULL;
}
EXPORT_SYMBOL(module_adapter_new);
Expand Down Expand Up @@ -1282,13 +1310,8 @@ void module_adapter_free(struct comp_dev *dev)

mod_free_all(mod);

#if CONFIG_IPC_MAJOR_4
rfree(mod->priv.cfg.input_pins);
#endif

rfree(mod->stream_params);
rfree(mod);
rfree(dev);
module_adapter_mem_free(mod);
}
EXPORT_SYMBOL(module_adapter_free);

Expand Down
17 changes: 16 additions & 1 deletion src/include/sof/audio/module_adapter/module/generic.h
Original file line number Diff line number Diff line change
Expand Up @@ -189,12 +189,27 @@ struct module_processing_data {
int module_load_config(struct comp_dev *dev, const void *cfg, size_t size);
int module_init(struct processing_module *mod);
void *mod_balloc_align(struct processing_module *mod, size_t size, size_t alignment);
void *mod_alloc_ext(struct processing_module *mod, uint32_t flags, size_t size, size_t alignment);

/**
* Allocates aligned memory block for module.
* @param mod Pointer to the module this memory block is allocated for.
* @param bytes Size in bytes.
* @param alignment Alignment in bytes.
* @return Pointer to the allocated memory or NULL if failed.
*
* The allocated memory is automatically freed when the module is unloaded.
*/
static inline void *mod_alloc_align(struct processing_module *mod, size_t size, size_t alignment)
{
return mod_alloc_ext(mod, 0, size, alignment);
}

static inline void *mod_balloc(struct processing_module *mod, size_t size)
{
return mod_balloc_align(mod, size, 0);
}

void *mod_alloc_align(struct processing_module *mod, size_t size, size_t alignment);
static inline void *mod_alloc(struct processing_module *mod, size_t size)
{
return mod_alloc_align(mod, size, 0);
Expand Down
11 changes: 11 additions & 0 deletions src/lib/alloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,3 +71,14 @@ int heap_info(int index, struct mm_info *out)
return 0;
}
#endif

void *sof_heap_alloc(struct k_heap *heap, uint32_t flags, size_t bytes,
size_t alignment)
{
return malloc(bytes);
Copy link

Copilot AI Nov 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The alignment parameter is not used in this implementation. While this is a stub implementation, it should either align the allocated memory or document why alignment is not respected. Consider using aligned_alloc() or documenting this limitation.

Suggested change
return malloc(bytes);
return aligned_alloc(alignment, bytes);

Copilot uses AI. Check for mistakes.
}

void sof_heap_free(struct k_heap *heap, void *addr)
{
free(addr);
}
11 changes: 11 additions & 0 deletions src/platform/library/lib/alloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,17 @@ void *rbrealloc_align(void *ptr, uint32_t flags, size_t bytes,
return realloc(ptr, bytes);
}

void *sof_heap_alloc(struct k_heap *heap, uint32_t flags, size_t bytes,
size_t alignment)
{
return malloc(bytes);
Copy link

Copilot AI Nov 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The alignment parameter is not used in this implementation. While this is a stub implementation, it should either align the allocated memory or document why alignment is not respected. Consider using aligned_alloc() or documenting this limitation.

Suggested change
return malloc(bytes);
/* Use aligned_alloc to respect the alignment parameter.
* Note: aligned_alloc requires that bytes is a multiple of alignment.
*/
if (alignment && (bytes % alignment != 0)) {
bytes = ((bytes + alignment - 1) / alignment) * alignment;
}
return aligned_alloc(alignment ? alignment : sizeof(void *), bytes);

Copilot uses AI. Check for mistakes.
}

void sof_heap_free(struct k_heap *heap, void *addr)
{
free(addr);
}

void heap_trace(struct mm_heap *heap, int size)
{
#if MALLOC_DEBUG
Expand Down
21 changes: 20 additions & 1 deletion test/cmocka/src/common_mocks.c
Original file line number Diff line number Diff line change
Expand Up @@ -102,10 +102,12 @@ void WEAK *mod_balloc_align(struct processing_module *mod, size_t size, size_t a
return ret;
}

void WEAK *mod_alloc_align(struct processing_module *mod, size_t size, size_t alignment)
void WEAK *mod_alloc_ext(struct processing_module *mod, uint32_t flags, size_t size,
size_t alignment)
{
void *ret;
(void)mod;
(void)flags;
(void)alignment;

ret = malloc(size);
Expand All @@ -122,6 +124,23 @@ int WEAK mod_free(struct processing_module *mod, const void *ptr)
return 0;
}

void WEAK *sof_heap_alloc(struct k_heap *heap, uint32_t flags, size_t bytes,
size_t alignment)
{
(void)heap;
(void)flags;
(void)alignment;

return malloc(bytes);
}
Comment on lines +127 to +135
Copy link

Copilot AI Nov 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The alignment parameter is marked as unused but is not respected by the underlying malloc() call. This could lead to misaligned memory in tests. Consider using aligned_alloc() to honor the alignment requirement or documenting that alignment is not supported in test mocks.

Copilot uses AI. Check for mistakes.

void WEAK sof_heap_free(struct k_heap *heap, void *addr)
{
(void)heap;

free(addr);
}

int WEAK memcpy_s(void *dest, size_t dest_size,
const void *src, size_t count)
{
Expand Down
4 changes: 4 additions & 0 deletions zephyr/include/rtos/alloc.h
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,10 @@ void rfree(void *ptr);
*/
void l3_heap_save(void);

void *sof_heap_alloc(struct k_heap *heap, uint32_t flags, size_t bytes,
size_t alignment);
void sof_heap_free(struct k_heap *heap, void *addr);

/* TODO: remove - debug only - only needed for linking */
static inline void heap_trace_all(int force) {}

Expand Down
24 changes: 24 additions & 0 deletions zephyr/lib/alloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -609,6 +609,30 @@ void rfree(void *ptr)
}
EXPORT_SYMBOL(rfree);

/*
* To match the fall-back SOF main heap all private heaps should also be in the
* uncached address range.
*/
void *sof_heap_alloc(struct k_heap *heap, uint32_t flags, size_t bytes,
size_t alignment)
{
if (!heap)
heap = &sof_heap;

if (flags & SOF_MEM_FLAG_COHERENT)
return heap_alloc_aligned(heap, alignment, bytes);

return (__sparse_force void *)heap_alloc_aligned_cached(heap, alignment, bytes);
}

void sof_heap_free(struct k_heap *heap, void *addr)
{
if (!heap)
heap = &sof_heap;

heap_free(heap, addr);
}

static int heap_init(void)
{
sys_heap_init(&sof_heap.heap, heapmem, HEAPMEM_SIZE - SHARED_BUFFER_HEAP_MEM_SIZE);
Expand Down
Loading