Skip to content

Commit

Permalink
ipc4: Add preeption guard to bind/unbind
Browse files Browse the repository at this point in the history
This is a workaround to protect bind/unbind operations to be preempted
by LL scheduler.

Signed-off-by: Serhiy Katsyuba <[email protected]>
  • Loading branch information
serhiy-katsyuba-intel committed Sep 15, 2023
1 parent e4f2396 commit e377686
Showing 1 changed file with 16 additions and 0 deletions.
16 changes: 16 additions & 0 deletions src/ipc/ipc4/helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,14 @@ int ipc_comp_connect(struct ipc *ipc, ipc_pipe_comp_connect *_connect)
source_set_ibs(audio_stream_get_source(&buffer->stream), source_src_cfg.obs);
sink_set_obs(audio_stream_get_sink(&buffer->stream), sink_src_cfg.ibs);

/* k_sched_lock() does not prevent current thread to be preempted if the thread
* calls something like sleep(). So just in case let's also use irq_local_disable()
* to guard two com_buffer_connect() calls. Interrupts should be re-enabled again for
* comp_bind_remote() to work. Let's pray nobody calls sleep() in .bind() handler.
* This is intendent to be a temporary workaround and should be replaced with some
* proper robust guard solution.
*/
k_sched_lock();
irq_local_disable(flags);

ret = comp_buffer_connect(source, source->ipc_config.core, buffer,
Expand Down Expand Up @@ -429,6 +437,8 @@ int ipc_comp_connect(struct ipc *ipc, ipc_pipe_comp_connect *_connect)
source->direction_set = true;
}

k_sched_unlock();

return IPC4_SUCCESS;

e_sink_bind:
Expand All @@ -440,6 +450,7 @@ int ipc_comp_connect(struct ipc *ipc, ipc_pipe_comp_connect *_connect)
pipeline_disconnect(source, buffer, PPL_CONN_DIR_COMP_TO_BUFFER);
free:
irq_local_enable(flags);
k_sched_unlock();
buffer_free(buffer);
return IPC4_INVALID_RESOURCE_STATE;
}
Expand Down Expand Up @@ -495,15 +506,20 @@ int ipc_comp_disconnect(struct ipc *ipc, ipc_pipe_comp_connect *_connect)
if (!buffer)
return IPC4_INVALID_RESOURCE_ID;

k_sched_lock();
irq_local_disable(flags);

pipeline_disconnect(src, buffer, PPL_CONN_DIR_COMP_TO_BUFFER);
pipeline_disconnect(sink, buffer, PPL_CONN_DIR_BUFFER_TO_COMP);

irq_local_enable(flags);

/* comp_unbind() may call comp_unbind_remote() and so IDC interrupt should be enabled */
ret = comp_unbind(src, bu);
ret1 = comp_unbind(sink, bu);

k_sched_unlock();

buffer_free(buffer);

if (ret || ret1)
Expand Down

0 comments on commit e377686

Please sign in to comment.