From 8a129a26a95cbf2f7bd523a0bb77a7864d603a81 Mon Sep 17 00:00:00 2001 From: Laxmi Devi Date: Mon, 1 Jul 2019 12:55:12 +0530 Subject: [PATCH 1/2] alsa: Exit JackAlsaDriver::Read if the XRUN recovery is not recovering the device Currently on XRUN, Jack tries a recovery and goes back to read again. But in a case where the device is not recovering at all, Jack is looping continuously taking up 100% cpu as there is no other exit condition. Signed-off-by: Laxmi Devi --- linux/alsa/JackAlsaDriver.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/linux/alsa/JackAlsaDriver.cpp b/linux/alsa/JackAlsaDriver.cpp index 529ec8d3..4ed85198 100644 --- a/linux/alsa/JackAlsaDriver.cpp +++ b/linux/alsa/JackAlsaDriver.cpp @@ -406,6 +406,9 @@ int JackAlsaDriver::Read() int wait_status; jack_nframes_t nframes; fDelayedUsecs = 0.f; + int retry_cnt = 0; + +#define MAX_RECOVERY_RETRY 10 retry: @@ -420,6 +423,11 @@ retry: */ jack_log("ALSA XRun wait_status = %d", wait_status); NotifyXRun(fBeginDateUst, fDelayedUsecs); + if(retry_cnt >= MAX_RECOVERY_RETRY) { + jack_error("ALSA Device not recovering, tried Xrun recovery for %d times", retry_cnt); + return -1; + } + retry_cnt++; goto retry; /* recoverable error*/ } From 8b3ea0522f7f6c9e84f6e7effcffd4df010d81be Mon Sep 17 00:00:00 2001 From: Laxmi Devi Date: Wed, 3 Jul 2019 15:34:55 +0530 Subject: [PATCH 2/2] alsa: Delay xrun recovery if first xrun recovery does not heal the xruns On executing the recovery after XRUN, if we still get an XRUN, delay the start by RECOVER_DELAY_MS ms. Signed-off-by: Laxmi Devi --- linux/alsa/JackAlsaDriver.cpp | 8 +++++--- linux/alsa/JackAlsaDriver.h | 5 +++++ linux/alsa/alsa_driver.c | 21 +++++++++++++++++---- linux/alsa/alsa_driver.h | 2 +- 4 files changed, 28 insertions(+), 8 deletions(-) diff --git a/linux/alsa/JackAlsaDriver.cpp b/linux/alsa/JackAlsaDriver.cpp index 4ed85198..199d8027 100644 --- a/linux/alsa/JackAlsaDriver.cpp +++ b/linux/alsa/JackAlsaDriver.cpp @@ -408,8 +408,6 @@ int JackAlsaDriver::Read() fDelayedUsecs = 0.f; int retry_cnt = 0; -#define MAX_RECOVERY_RETRY 10 - retry: nframes = alsa_driver_wait((alsa_driver_t *)fDriver, -1, &wait_status, &fDelayedUsecs); @@ -933,10 +931,14 @@ void SetTime(jack_time_t time) g_alsa_driver->SetTimetAux(time); } -int Restart() +int Restart(int delay) { int res; + if ((res = g_alsa_driver->Stop()) == 0) { + if(delay > 0) { + usleep(delay * MS_TO_US); + } res = g_alsa_driver->Start(); } return res; diff --git a/linux/alsa/JackAlsaDriver.h b/linux/alsa/JackAlsaDriver.h index b2f44afb..2d2feb6d 100644 --- a/linux/alsa/JackAlsaDriver.h +++ b/linux/alsa/JackAlsaDriver.h @@ -26,6 +26,11 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #include "JackTime.h" #include "alsa_driver.h" +/* Milli Seconds represented in Micro seconds */ +#define MS_TO_US 1000 +/* Max re-try count for Alsa XRUNs */ +#define MAX_RECOVERY_RETRY 10 + namespace Jack { diff --git a/linux/alsa/alsa_driver.c b/linux/alsa/alsa_driver.c index 9573001a..bab502f3 100644 --- a/linux/alsa/alsa_driver.c +++ b/linux/alsa/alsa_driver.c @@ -58,6 +58,8 @@ char* strcasestr(const char* haystack, const char* needle); #define XRUN_REPORT_DELAY 0 /* Max re-try count for Alsa poll timeout handling */ #define MAX_RETRY_COUNT 5 +/* Delay in initiating the second xrun recovery */ +#define RECOVER_DELAY_MS 20 void jack_driver_init (jack_driver_t *driver) @@ -1168,7 +1170,7 @@ alsa_driver_stop (alsa_driver_t *driver) } static int -alsa_driver_restart (alsa_driver_t *driver) +alsa_driver_restart (alsa_driver_t *driver, int delay) { int res; @@ -1178,7 +1180,7 @@ alsa_driver_restart (alsa_driver_t *driver) if ((res = driver->nt_stop((struct _jack_driver_nt *) driver))==0) res = driver->nt_start((struct _jack_driver_nt *) driver); */ - res = Restart(); + res = Restart(delay); driver->xrun_recovery = 0; if (res && driver->midi) @@ -1192,6 +1194,7 @@ alsa_driver_xrun_recovery (alsa_driver_t *driver, float *delayed_usecs) { snd_pcm_status_t *status; int res; + int delay = 0; snd_pcm_status_alloca(&status); @@ -1224,10 +1227,11 @@ alsa_driver_xrun_recovery (alsa_driver_t *driver, float *delayed_usecs) } } + driver->xrun_count++; + if (snd_pcm_status_get_state(status) == SND_PCM_STATE_XRUN && driver->process_count > XRUN_REPORT_DELAY) { struct timeval now, diff, tstamp; - driver->xrun_count++; snd_pcm_status_get_tstamp(status,&now); snd_pcm_status_get_trigger_tstamp(status, &tstamp); timersub(&now, &tstamp, &diff); @@ -1247,7 +1251,12 @@ alsa_driver_xrun_recovery (alsa_driver_t *driver, float *delayed_usecs) } } - if (alsa_driver_restart (driver)) { + /* Try the first xrun recovery without delay and the subsequent ones with delay */ + if(driver->xrun_count > 1) { + delay = RECOVER_DELAY_MS; + } + + if (alsa_driver_restart (driver, delay)) { return -1; } return 0; @@ -1536,6 +1545,10 @@ alsa_driver_wait (alsa_driver_t *driver, int extra_fd, int *status, float if (xrun_detected) { *status = alsa_driver_xrun_recovery (driver, delayed_usecs); return 0; + } else { + if(driver->xrun_count > 0) { + driver->xrun_count = 0; + } } *status = 0; diff --git a/linux/alsa/alsa_driver.h b/linux/alsa/alsa_driver.h index efe93de5..36a0d01c 100644 --- a/linux/alsa/alsa_driver.h +++ b/linux/alsa/alsa_driver.h @@ -278,7 +278,7 @@ void MonitorInput(); void ClearOutput(); void WriteOutput(jack_nframes_t orig_nframes, snd_pcm_sframes_t contiguous, snd_pcm_sframes_t nwritten); void SetTime(jack_time_t time); -int Restart(); +int Restart(int delay); #ifdef __cplusplus }