Skip to content

Commit 1e59ce2

Browse files
committed
pipeline: protect component connections with a mutex
In userspace LL builds, use a mutex to protect component connections. This code should work in kernel builds as well, but start with an incremental change that only affects LL builds, in which mutex use is mandatory. Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
1 parent f1400dc commit 1e59ce2

3 files changed

Lines changed: 34 additions & 8 deletions

File tree

src/audio/buffers/comp_buffer.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -565,7 +565,8 @@ static inline struct list_item *buffer_comp_list(struct comp_buffer *buffer,
565565
}
566566

567567
/*
568-
* Locking: must be called with interrupts disabled! Serialized IPCs protect us
568+
* Locking: must be called with interrupts disabled (or sys_mutex held for
569+
* userspace LL builds)! Serialized IPCs protect us
569570
* from racing attach / detach calls, but the scheduler can interrupt the IPC
570571
* thread and begin using the buffer for streaming. FIXME: this is still a
571572
* problem with different cores.
@@ -578,7 +579,8 @@ void buffer_attach(struct comp_buffer *buffer, struct list_item *head, int dir)
578579
}
579580

580581
/*
581-
* Locking: must be called with interrupts disabled! See buffer_attach() above
582+
* Locking: must be called with interrupts disabled (or sys_mutex held for
583+
* userspace LL builds)! See buffer_attach() above
582584
* for details
583585
*/
584586
void buffer_detach(struct comp_buffer *buffer, struct list_item *head, int dir)

src/audio/pipeline/pipeline-graph.c

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -178,45 +178,61 @@ static void buffer_set_comp(struct comp_buffer *buffer, struct comp_dev *comp,
178178
comp_buffer_set_sink_component(buffer, comp);
179179
}
180180

181+
#ifdef CONFIG_SOF_USERSPACE_LL
182+
#define PPL_LOCK_DECLARE
183+
#define PPL_LOCK() do { \
184+
int ret = sys_mutex_lock(&comp->list_mutex, K_FOREVER); \
185+
assert(ret == 0); \
186+
} while (0)
187+
#define PPL_UNLOCK() do { \
188+
int ret = sys_mutex_unlock(&comp->list_mutex); \
189+
assert(ret == 0); \
190+
} while (0)
191+
#else
192+
#define PPL_LOCK_DECLARE uint32_t flags
193+
#define PPL_LOCK() irq_local_disable(flags)
194+
#define PPL_UNLOCK() irq_local_enable(flags)
195+
#endif
196+
181197
int pipeline_connect(struct comp_dev *comp, struct comp_buffer *buffer,
182198
int dir)
183199
{
184200
struct list_item *comp_list;
185-
uint32_t flags;
201+
PPL_LOCK_DECLARE;
186202

187203
if (dir == PPL_CONN_DIR_COMP_TO_BUFFER)
188204
comp_info(comp, "connect buffer %d as sink", buf_get_id(buffer));
189205
else
190206
comp_info(comp, "connect buffer %d as source", buf_get_id(buffer));
191207

192-
irq_local_disable(flags);
208+
PPL_LOCK();
193209

194210
comp_list = comp_buffer_list(comp, dir);
195211
buffer_attach(buffer, comp_list, dir);
196212
buffer_set_comp(buffer, comp, dir);
197213

198-
irq_local_enable(flags);
214+
PPL_UNLOCK();
199215

200216
return 0;
201217
}
202218

203219
void pipeline_disconnect(struct comp_dev *comp, struct comp_buffer *buffer, int dir)
204220
{
205221
struct list_item *comp_list;
206-
uint32_t flags;
222+
PPL_LOCK_DECLARE;
207223

208224
if (dir == PPL_CONN_DIR_COMP_TO_BUFFER)
209225
comp_dbg(comp, "disconnect buffer %d as sink", buf_get_id(buffer));
210226
else
211227
comp_dbg(comp, "disconnect buffer %d as source", buf_get_id(buffer));
212228

213-
irq_local_disable(flags);
229+
PPL_LOCK();
214230

215231
comp_list = comp_buffer_list(comp, dir);
216232
buffer_detach(buffer, comp_list, dir);
217233
buffer_set_comp(buffer, NULL, dir);
218234

219-
irq_local_enable(flags);
235+
PPL_UNLOCK();
220236
}
221237

222238
/* pipelines must be inactive */

src/include/sof/audio/component.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include <sof/audio/pipeline.h>
2222
#include <sof/debug/telemetry/telemetry.h>
2323
#include <rtos/idc.h>
24+
#include <rtos/mutex.h>
2425
#include <rtos/userspace_helper.h>
2526
#include <sof/lib/dai.h>
2627
#include <sof/schedule/schedule.h>
@@ -686,6 +687,10 @@ struct comp_dev {
686687
struct list_item bsource_list; /**< list of source buffers */
687688
struct list_item bsink_list; /**< list of sink buffers */
688689

690+
#ifdef CONFIG_SOF_USERSPACE_LL
691+
struct sys_mutex list_mutex; /**< protect lists of source/sinks */
692+
#endif
693+
689694
/* performance data*/
690695
struct comp_perf_data perf_data;
691696
/* Input Buffer Size for pin 0, add array for other pins if needed */
@@ -870,6 +875,9 @@ static inline void comp_init(const struct comp_driver *drv,
870875
dev->state = COMP_STATE_INIT;
871876
list_init(&dev->bsink_list);
872877
list_init(&dev->bsource_list);
878+
#ifdef CONFIG_SOF_USERSPACE_LL
879+
sys_mutex_init(&dev->list_mutex);
880+
#endif
873881
memcpy_s(&dev->tctx, sizeof(dev->tctx),
874882
trace_comp_drv_get_tr_ctx(dev->drv), sizeof(struct tr_ctx));
875883
}

0 commit comments

Comments
 (0)