CRAS: alsa-plugin - remove snd_pcm_cras_delay
PCM functions became thread-safe in 1.1.2. Some functions like
snd_pcm_delay and snd_pcm_sw_params_current will hold a lock.
snd_pcm_cras_delay is called by snd_pcm_delay, but
snd_pcm_cras_delay calls snd_pcm_sw_params_current. This causes
a deadlock.
There are several options that are not good:
(1) Define --disable-thread-safety in alsa-lib. This will be
inconsistent with upstream alsa-lib.
(2) Set snd_pcm_t.need_lock=0. need_lock is in pcm_local.h
and it's not easy to build with it. Also, need_lock means
the plugin is thread safe and doesn't need locking in
alsa-lib. Our plugin is not thread safe.
(3) Not to call snd_pcm_sw_params_current in snd_pcm_cras_delay.
Calling snd_pcm_sw_params_current in .start introduces a
similar deadlock. Also it's more accurate to get the latest
boundary in .delay.
I don't see a good solution. Let's remove snd_pcm_cras_delay.
BUG=chromium:779936
TEST=Run loopback_latency -n 4000 and it does not hang.
Change-Id: I69b143aee2e95f8ef8f1a2c0f1604064255d0017
Reviewed-on: https://chromium-review.googlesource.com/758796
Commit-Ready: Wu-Cheng Li <wuchengli@chromium.org>
Tested-by: Wu-Cheng Li <wuchengli@chromium.org>
Reviewed-by: Cheng-Yi Chiang <cychiang@chromium.org>
Reviewed-by: Dylan Reid <dgreid@chromium.org>
diff --git a/cras/src/alsa_plugin/pcm_cras.c b/cras/src/alsa_plugin/pcm_cras.c
index 93b61a3..5591a11 100644
--- a/cras/src/alsa_plugin/pcm_cras.c
+++ b/cras/src/alsa_plugin/pcm_cras.c
@@ -228,29 +228,6 @@
return cras_client_connect(pcm_cras->client);
}
-/* Get the pcm boundary value. */
-static int get_boundary(snd_pcm_t *pcm, snd_pcm_uframes_t *boundary)
-{
- snd_pcm_sw_params_t *sw_params;
- int rc;
-
- snd_pcm_sw_params_alloca(&sw_params);
-
- rc = snd_pcm_sw_params_current(pcm, sw_params);
- if (rc < 0) {
- fprintf(stderr, "sw_params_current: %s\n", snd_strerror(rc));
- return rc;
- }
-
- rc = snd_pcm_sw_params_get_boundary(sw_params, boundary);
- if (rc < 0) {
- fprintf(stderr, "get_boundary: %s\n", snd_strerror(rc));
- return rc;
- }
-
- return 0;
-}
-
/* Called when an ALSA stream is started. */
static int snd_pcm_cras_start(snd_pcm_ioplug_t *io)
{
@@ -300,71 +277,8 @@
return rc;
}
-static int snd_pcm_cras_delay(snd_pcm_ioplug_t *io, snd_pcm_sframes_t *delayp)
-{
- snd_pcm_uframes_t limit;
- int rc;
- struct snd_pcm_cras *pcm_cras;
- struct timespec latency;
-
- pcm_cras = (struct snd_pcm_cras *)io->private_data;
-
- rc = get_boundary(io->pcm, &limit);
- if ((rc < 0) || (limit == 0)) {
- *delayp = 0;
- return -EINVAL;
- }
-
- /* To get the delay, first calculate the latency between now and the
- * playback/capture sample time for the old hw_ptr we tracked, note that
- * for playback path this latency could be negative. Then add it up with
- * the difference between appl_ptr and the old hw_ptr.
- */
- if (io->stream == SND_PCM_STREAM_PLAYBACK) {
- /* Do not compute latency if playback_sample_time is not set */
- if (pcm_cras->playback_sample_time.tv_sec == 0 &&
- pcm_cras->playback_sample_time.tv_nsec == 0) {
- latency.tv_sec = 0;
- latency.tv_nsec = 0;
- } else {
- cras_client_calc_playback_latency(
- &pcm_cras->playback_sample_time,
- &latency);
- }
-
- *delayp = limit +
- io->appl_ptr -
- pcm_cras->playback_sample_index +
- latency.tv_sec * io->rate +
- latency.tv_nsec / (1000000000L / (long)io->rate);
- } else {
- /* Do not compute latency if capture_sample_time is not set */
- if (pcm_cras->capture_sample_time.tv_sec == 0 &&
- pcm_cras->capture_sample_time.tv_nsec == 0) {
- latency.tv_sec = 0;
- latency.tv_nsec = 0;
- } else {
- cras_client_calc_capture_latency(
- &pcm_cras->capture_sample_time,
- &latency);
- }
-
- *delayp = limit +
- pcm_cras->capture_sample_index -
- io->appl_ptr +
- latency.tv_sec * io->rate +
- latency.tv_nsec / (1000000000L / (long)io->rate);
- }
-
- /* Both appl and hw pointers wrap at the pcm boundary. */
- *delayp %= limit;
-
- return 0;
-}
-
static snd_pcm_ioplug_callback_t cras_pcm_callback = {
.close = snd_pcm_cras_close,
- .delay = snd_pcm_cras_delay,
.start = snd_pcm_cras_start,
.stop = snd_pcm_cras_stop,
.pointer = snd_pcm_cras_pointer,