- Backport upstream fix patches, including the deadlock fix for aplay/arecord (boo#1031525): 0001-ucm-Add-ATTRIBUTE_UNUSED-for-unused-parameters-of-ex.patch 0002-ucm-parser-needs-limits.h.patch 0003-pcm-direct-allow-users-to-configure-different-period.patch 0004-pcm-dshare-enable-silence.patch 0005-pcm-rate-fix-the-hw_ptr-update-until-the-boundary-av.patch 0006-plugin-dynamically-update-avail_min-on-slave.patch 0007-rate-dynamic-update-avail_min-on-slave.patch 0008-topology-fix-unused-const-variable-warning.patch 0009-seq-improve-documentation-about-new-get-pid-card-fun.patch 0010-pcm-direct-returning-semop-error-code-for-semaphore-.patch 0011-pcm-direct-Fix-for-sync-issue-on-xrun-recover.patch 0012-pcm-direct-check-state-before-enter-poll-on-timer.patch 0013-pcm-direct-don-t-return-bogus-buffer-levels-in-xrun-.patch 0014-conf-ucm-broxton-add-broxton-rt298-conf-files.patch 0015-pcm-direct-Fix-deadlock-in-poll_descriptors.patch 0016-ucm-Assure-the-user-input-card-name-not-to-exceed-ma.patch 0017-ucm-Load-device-specific-configuration-file-based-on.patch 0018-ucm-Add-command-get-_file-to-get-the-config-file-nam.patch 0019-topology-Fix-incorrect-license-in-source-comments.patch 0020-conf-cards-add-support-for-pistachio-card.patch 0021-pcm-multi-Drop-the-fixed-slave_map-in-snd_pcm_multi_.patch 0022-conf-Add-card-config-for-Intel-HDMI-DP-LPE-audio.patch 0023-pcm-Avoid-lock-for-snd_pcm_nonblock.patch 0024-pcm-Disable-locking-in-async-mode.patch 0025-pcm-dmix-Allow-disabling-x86-optimizations.patch 0026-pcm-dmix_rewind-corrupts-application-pointer-fix.patch 0027-pcm-direct-fix-race-on-clearing-timer-events.patch 0028-pcm-file-Enable-file-writing-for-capture-path.patch OBS-URL: https://build.opensuse.org/request/show/483406 OBS-URL: https://build.opensuse.org/package/show/multimedia:libs/alsa?expand=0&rev=210
98 lines
3.3 KiB
Diff
98 lines
3.3 KiB
Diff
From 9219034301a3bf3d8de57ac5672bbc1c53f18049 Mon Sep 17 00:00:00 2001
|
|
From: Andreas Pape <apape@de.adit-jv.com>
|
|
Date: Fri, 17 Feb 2017 12:45:56 +0530
|
|
Subject: [PATCH 27/43] pcm: direct: fix race on clearing timer events
|
|
|
|
snd_timer handling is racy: plugins clear timer queue if avail_min
|
|
is not reached to force a sleep on timer. The race can happen if
|
|
the expected event arrives in between the avail check and the
|
|
clearing of pending events. If this race happens, the user will
|
|
unnecessarily wait for one more timer event. On low latency/realtime
|
|
streams this can lead to xruns and must be avoided.
|
|
|
|
As a fix we recheck avail after having cleared poll events.
|
|
|
|
Signed-off-by: Andreas Pape <apape@de.adit-jv.com>
|
|
Signed-off-by: Jiada Wang <jiada_wang@mentor.com>
|
|
Signed-off-by: Mounesh Sutar <sutar.mounesh@gmail.com>
|
|
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
|
---
|
|
src/pcm/pcm_direct.c | 23 +++++++++++++++++++----
|
|
src/pcm/pcm_direct.h | 2 +-
|
|
2 files changed, 20 insertions(+), 5 deletions(-)
|
|
|
|
--- a/src/pcm/pcm_direct.c
|
|
+++ b/src/pcm/pcm_direct.c
|
|
@@ -515,10 +515,12 @@ int snd_pcm_direct_async(snd_pcm_t *pcm,
|
|
}
|
|
|
|
/* empty the timer read queue */
|
|
-void snd_pcm_direct_clear_timer_queue(snd_pcm_direct_t *dmix)
|
|
+int snd_pcm_direct_clear_timer_queue(snd_pcm_direct_t *dmix)
|
|
{
|
|
+ int changed = 0;
|
|
if (dmix->timer_need_poll) {
|
|
while (poll(&dmix->timer_fd, 1, 0) > 0) {
|
|
+ changed++;
|
|
/* we don't need the value */
|
|
if (dmix->tread) {
|
|
snd_timer_tread_t rbuf[4];
|
|
@@ -533,15 +535,17 @@ void snd_pcm_direct_clear_timer_queue(sn
|
|
snd_timer_tread_t rbuf[4];
|
|
int len;
|
|
while ((len = snd_timer_read(dmix->timer, rbuf,
|
|
- sizeof(rbuf))) > 0 &&
|
|
+ sizeof(rbuf))) > 0
|
|
+ && (++changed) &&
|
|
len != sizeof(rbuf[0]))
|
|
;
|
|
} else {
|
|
snd_timer_read_t rbuf;
|
|
while (snd_timer_read(dmix->timer, &rbuf, sizeof(rbuf)) > 0)
|
|
- ;
|
|
+ changed++;
|
|
}
|
|
}
|
|
+ return changed;
|
|
}
|
|
|
|
int snd_pcm_direct_timer_stop(snd_pcm_direct_t *dmix)
|
|
@@ -693,6 +697,8 @@ int snd_pcm_direct_poll_revents(snd_pcm_
|
|
int empty = 0;
|
|
|
|
assert(pfds && nfds == 1 && revents);
|
|
+
|
|
+timer_changed:
|
|
events = pfds[0].revents;
|
|
if (events & POLLIN) {
|
|
snd_pcm_uframes_t avail;
|
|
@@ -720,7 +726,16 @@ int snd_pcm_direct_poll_revents(snd_pcm_
|
|
break;
|
|
default:
|
|
if (empty) {
|
|
- snd_pcm_direct_clear_timer_queue(dmix);
|
|
+ /* here we have a race condition:
|
|
+ * if period event arrived after the avail_update call
|
|
+ * above we might clear this event with the following
|
|
+ * clear_timer_queue.
|
|
+ * There is no way to do this in atomic manner, so we
|
|
+ * need to recheck avail_update if we successfully
|
|
+ * cleared a poll event.
|
|
+ */
|
|
+ if (snd_pcm_direct_clear_timer_queue(dmix))
|
|
+ goto timer_changed;
|
|
events &= ~(POLLOUT|POLLIN);
|
|
/* additional check */
|
|
switch (__snd_pcm_state(pcm)) {
|
|
--- a/src/pcm/pcm_direct.h
|
|
+++ b/src/pcm/pcm_direct.h
|
|
@@ -322,7 +322,7 @@ int snd_pcm_direct_munmap(snd_pcm_t *pcm
|
|
int snd_pcm_direct_prepare(snd_pcm_t *pcm);
|
|
int snd_pcm_direct_resume(snd_pcm_t *pcm);
|
|
int snd_pcm_direct_timer_stop(snd_pcm_direct_t *dmix);
|
|
-void snd_pcm_direct_clear_timer_queue(snd_pcm_direct_t *dmix);
|
|
+int snd_pcm_direct_clear_timer_queue(snd_pcm_direct_t *dmix);
|
|
int snd_pcm_direct_set_timer_params(snd_pcm_direct_t *dmix);
|
|
int snd_pcm_direct_open_secondary_client(snd_pcm_t **spcmp, snd_pcm_direct_t *dmix, const char *client_name);
|
|
|