mirror of
https://gitlab.freedesktop.org/pipewire/pipewire
synced 2024-10-14 20:02:38 +00:00
alsa: fix race when updating the eventfd
The eventfd is read/written from/to the data thread and the main thread concurrently with the update_active() function. Use an atomic compare and swap to make this update atomic and avoid an inconsistency between the active boolean and the eventfd. This could result in the eventfd being unsignaled while the active flag was true and the application receiving a timeout and XRun in its poll loop. Fixes #3711
This commit is contained in:
parent
232f4f01e4
commit
2b11efdf3b
|
@ -56,9 +56,10 @@ typedef struct {
|
|||
unsigned int draining:1;
|
||||
unsigned int xrun_detected:1;
|
||||
unsigned int hw_params_changed:1;
|
||||
unsigned int active:1;
|
||||
unsigned int negotiated:1;
|
||||
|
||||
bool active;
|
||||
|
||||
snd_pcm_uframes_t hw_ptr;
|
||||
snd_pcm_uframes_t boundary;
|
||||
snd_pcm_uframes_t min_avail;
|
||||
|
@ -93,8 +94,9 @@ static int update_active(snd_pcm_ioplug_t *io)
|
|||
{
|
||||
snd_pcm_pipewire_t *pw = io->private_data;
|
||||
snd_pcm_sframes_t avail;
|
||||
bool active;
|
||||
bool active, old;
|
||||
|
||||
retry:
|
||||
avail = snd_pcm_ioplug_avail(io, pw->hw_ptr, io->appl_ptr);
|
||||
|
||||
if (pw->error > 0) {
|
||||
|
@ -112,7 +114,8 @@ static int update_active(snd_pcm_ioplug_t *io)
|
|||
else {
|
||||
active = false;
|
||||
}
|
||||
if (pw->active != active) {
|
||||
old = SPA_ATOMIC_LOAD(pw->active);
|
||||
if (old != active) {
|
||||
uint64_t val;
|
||||
|
||||
pw_log_trace("%p: avail:%lu min-avail:%lu state:%s hw:%lu appl:%lu active:%d->%d state:%s",
|
||||
|
@ -120,11 +123,13 @@ static int update_active(snd_pcm_ioplug_t *io)
|
|||
pw->hw_ptr, io->appl_ptr, pw->active, active,
|
||||
snd_pcm_state_name(io->state));
|
||||
|
||||
pw->active = active;
|
||||
if (active)
|
||||
spa_system_eventfd_write(pw->system, io->poll_fd, 1);
|
||||
else
|
||||
spa_system_eventfd_read(pw->system, io->poll_fd, &val);
|
||||
|
||||
if (!SPA_ATOMIC_CAS(pw->active, old, active))
|
||||
goto retry;
|
||||
}
|
||||
return active;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue