Skip to content
Open
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
16 changes: 10 additions & 6 deletions src/audio/pipeline/pipeline-graph.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <sof/ipc/msg.h>
#include <rtos/interrupt.h>
#include <rtos/symbol.h>
#include <rtos/alloc.h>
#include <sof/lib/mm_heap.h>
#include <sof/lib/uuid.h>
#include <sof/compiler_attributes.h>
Expand Down Expand Up @@ -108,8 +109,8 @@ void pipeline_posn_init(struct sof *sof)
}

/* create new pipeline - returns pipeline id or negative error */
struct pipeline *pipeline_new(uint32_t pipeline_id, uint32_t priority, uint32_t comp_id,
struct create_pipeline_params *pparams)
struct pipeline *pipeline_new(struct k_heap *heap, uint32_t pipeline_id, uint32_t priority,
uint32_t comp_id, struct create_pipeline_params *pparams)
{
struct sof_ipc_stream_posn posn;
struct pipeline *p;
Expand All @@ -122,13 +123,16 @@ struct pipeline *pipeline_new(uint32_t pipeline_id, uint32_t priority, uint32_t
heap_trace_all(0);

/* allocate new pipeline */
p = rzalloc(SOF_MEM_FLAG_USER, sizeof(*p));
p = sof_heap_alloc(heap, SOF_MEM_FLAG_USER, sizeof(*p), 0);
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

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

Using an explicit alignment of 0 relies on sof_heap_alloc() default behavior. Since this allocates a struct, it’s safer/clearer to pass an explicit alignment (e.g., __alignof__(*p) / alignof(struct pipeline) or the project’s default alignment constant) to prevent misalignment if a heap implementation changes.

Suggested change
p = sof_heap_alloc(heap, SOF_MEM_FLAG_USER, sizeof(*p), 0);
p = sof_heap_alloc(heap, SOF_MEM_FLAG_USER, sizeof(*p), __alignof__(*p));

Copilot uses AI. Check for mistakes.
if (!p) {
pipe_cl_err("Out of Memory");
return NULL;
}

memset(p, 0, sizeof(*p));
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

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

memset() is newly used here, but this file doesn't appear to include the header that declares it. Add an explicit include for the project’s string/memory header (typically <string.h> or the SOF wrapper) to avoid relying on transitive includes and potential implicit-declaration build failures.

Copilot uses AI. Check for mistakes.

/* init pipeline */
p->heap = heap;
p->comp_id = comp_id;
p->priority = priority;
p->pipeline_id = pipeline_id;
Expand Down Expand Up @@ -161,7 +165,7 @@ struct pipeline *pipeline_new(uint32_t pipeline_id, uint32_t priority, uint32_t

return p;
free:
rfree(p);
sof_heap_free(heap, p);
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

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

On the error path, the code frees with the function parameter heap, while the rest of the lifecycle frees via p->heap. To keep heap ownership consistent (and future-proof if the implementation ever normalizes heap to a default), resolve the effective heap once, assign it to p->heap, and use that same value for all alloc/free paths (including the free: label).

Suggested change
sof_heap_free(heap, p);
sof_heap_free(p->heap, p);

Copilot uses AI. Check for mistakes.
return NULL;
}

Expand Down Expand Up @@ -230,15 +234,15 @@ int pipeline_free(struct pipeline *p)
#if !CONFIG_LIBRARY || UNIT_TEST
schedule_task_free(p->pipe_task);
#endif
rfree(p->pipe_task);
sof_heap_free(p->heap, p->pipe_task);
}

ipc_msg_free(p->msg);

pipeline_posn_offset_put(p->posn_offset);

/* now free the pipeline */
rfree(p);
sof_heap_free(p->heap, p);

/* show heap status */
heap_trace_all(0);
Expand Down
9 changes: 6 additions & 3 deletions src/audio/pipeline/pipeline-schedule.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <sof/audio/buffer.h>
#include <sof/audio/component_ext.h>
#include <sof/audio/pipeline.h>
#include <rtos/alloc.h>
#include <rtos/interrupt.h>
#include <sof/lib/agent.h>
#include <sof/list.h>
Expand Down Expand Up @@ -241,15 +242,17 @@ static struct task *pipeline_task_init(struct pipeline *p, uint32_t type)
{
struct pipeline_task *task = NULL;

task = rzalloc(SOF_MEM_FLAG_USER,
sizeof(*task));
task = sof_heap_alloc(p->heap, SOF_MEM_FLAG_USER,
sizeof(*task), 0);
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

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

Using an explicit alignment of 0 relies on sof_heap_alloc() default behavior. Since this allocates a struct, it’s safer/clearer to pass an explicit alignment (e.g., __alignof__(*task) / alignof(struct pipeline_task) or the project’s default alignment constant) to prevent misalignment if a heap implementation changes.

Suggested change
sizeof(*task), 0);
sizeof(*task), __alignof__(*task));

Copilot uses AI. Check for mistakes.
if (!task)
return NULL;

memset(task, 0, sizeof(*task));
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

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

memset() is newly used here, but this file doesn't appear to include the header that declares it. Add an explicit include for the project’s string/memory header (typically <string.h> or the SOF wrapper) to avoid relying on transitive includes and potential implicit-declaration build failures.

Copilot uses AI. Check for mistakes.

if (schedule_task_init_ll(&task->task, SOF_UUID(pipe_task_uuid), type,
p->priority, pipeline_task,
p, p->core, 0) < 0) {
rfree(task);
sof_heap_free(p->heap, task);
return NULL;
}

Expand Down
9 changes: 6 additions & 3 deletions src/include/sof/audio/pipeline.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ struct comp_buffer;
struct comp_dev;
struct ipc;
struct ipc_msg;
struct k_heap;

/*
* Pipeline status to stop execution of current path, but to keep the
Expand Down Expand Up @@ -52,6 +53,7 @@ struct ipc_msg;
* Audio pipeline.
*/
struct pipeline {
struct k_heap *heap; /**< heap used for allocating this pipeline */
uint32_t comp_id; /**< component id for pipeline */
uint32_t pipeline_id; /**< pipeline id */
uint32_t sched_id; /**< Scheduling component id */
Expand Down Expand Up @@ -152,14 +154,15 @@ struct create_pipeline_params {

/**
* \brief Creates a new pipeline.
* \param[in] heap Heap to allocate the pipeline on, or NULL for default.
* \param[in] pipeline_id Pipeline ID number.
* \param[in] priority Pipeline scheduling priority.
* \param[in] comp_id Pipeline component ID number.
* \param[in] pparams Pipeline parameters from IPC payload, maybe NULL.
* \return New pipeline pointer or NULL.
*/
struct pipeline *pipeline_new(uint32_t pipeline_id, uint32_t priority, uint32_t comp_id,
struct create_pipeline_params *pparams);
struct pipeline *pipeline_new(struct k_heap *heap, uint32_t pipeline_id, uint32_t priority,
uint32_t comp_id, struct create_pipeline_params *pparams);

/**
* \brief Free's a pipeline.
Expand Down Expand Up @@ -266,7 +269,7 @@ int pipeline_params(struct pipeline *p, struct comp_dev *cd,
struct sof_ipc_pcm_params *params);

/**
* \brief Creates a new pipeline.
* \brief Prepares pipeline for processing.
* \param[in] p pipeline.
* \param[in,out] cd Pipeline component device.
* \return 0 on success.
Expand Down
2 changes: 1 addition & 1 deletion src/ipc/ipc3/helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -395,7 +395,7 @@ int ipc_pipeline_new(struct ipc *ipc, ipc_pipe_new *_pipe_desc)
}

/* create the pipeline */
pipe = pipeline_new(pipe_desc->pipeline_id, pipe_desc->priority,
pipe = pipeline_new(NULL, pipe_desc->pipeline_id, pipe_desc->priority,
pipe_desc->comp_id, NULL);
if (!pipe) {
tr_err(&ipc_tr, "pipeline_new() failed");
Expand Down
4 changes: 2 additions & 2 deletions src/ipc/ipc4/helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -352,8 +352,8 @@ __cold static int ipc4_create_pipeline(struct ipc4_pipeline_create *pipe_desc,
}

/* create the pipeline */
pipe = pipeline_new(pipe_desc->primary.r.instance_id, pipe_desc->primary.r.ppl_priority, 0,
pparams);
pipe = pipeline_new(NULL, pipe_desc->primary.r.instance_id,
pipe_desc->primary.r.ppl_priority, 0, pparams);
if (!pipe) {
tr_err(&ipc_tr, "ipc: pipeline_new() failed");
return IPC4_OUT_OF_MEMORY;
Expand Down
3 changes: 2 additions & 1 deletion test/cmocka/src/audio/pipeline/pipeline_new.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ static void test_audio_pipeline_pipeline_new_creation(void **state)
struct pipeline_new_setup_data *test_data = *state;

/*Testing component*/
struct pipeline *result = pipeline_new(test_data->pipe_id,
struct pipeline *result = pipeline_new(NULL,
test_data->pipe_id,
test_data->priority,
test_data->comp_id,
NULL);
Expand Down
35 changes: 35 additions & 0 deletions zephyr/test/userspace/test_ll_task.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <sof/schedule/schedule.h>
#include <sof/schedule/ll_schedule.h>
#include <sof/schedule/ll_schedule_domain.h>
#include <sof/audio/pipeline.h>
#include <rtos/task.h>
#include <rtos/userspace_helper.h>
#include <ipc4/fw_reg.h>
Expand Down Expand Up @@ -94,6 +95,40 @@ ZTEST(userspace_ll, ll_task_test)
ll_task_test();
}

static void pipeline_check(void)
{
struct pipeline *p;
struct k_heap *heap;
uint32_t pipeline_id = 1;
uint32_t priority = 5;
uint32_t comp_id = 10;
int ret;

heap = zephyr_ll_user_heap();
zassert_not_null(heap, "user heap not found");

/* Create pipeline on user heap */
p = pipeline_new(heap, pipeline_id, priority, comp_id, NULL);
zassert_not_null(p, "pipeline creation failed");

/* Verify heap assignment */
zassert_equal(p->heap, heap, "pipeline heap not equal to user heap");

/* Verify pipeline properties */
zassert_equal(p->pipeline_id, pipeline_id, "pipeline id mismatch");
zassert_equal(p->priority, priority, "priority mismatch");
zassert_equal(p->comp_id, comp_id, "comp id mismatch");

/* Free pipeline */
ret = pipeline_free(p);
zassert_equal(ret, 0, "pipeline free failed");
}

ZTEST(userspace_ll, pipeline_check)
{
pipeline_check();
}

ZTEST_SUITE(userspace_ll, NULL, NULL, NULL, NULL, NULL);

/**
Expand Down
Loading