diff --git a/pipewire-alsa/alsa-plugins/pcm_pipewire.c b/pipewire-alsa/alsa-plugins/pcm_pipewire.c index b9797191c..1e6cac79f 100644 --- a/pipewire-alsa/alsa-plugins/pcm_pipewire.c +++ b/pipewire-alsa/alsa-plugins/pcm_pipewire.c @@ -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; }