[alsa-devel] [alsa-lib][v1.1.19][pcm][multi plug] multi plug stuck in busy loop which caused high cpu loading.
Dear,
Currently, for Audio Echo Cancellation process, we combined both mic signal and reference signal into one pcm with the multi plug. And both the mic and ref signal are hw pcm devices, and they lived in the same sound card in driver.
Here is the issue:
1. the master slave pcm device is already for read; 2. the second salve pcm is not ready for read, which means no data; 3. under this situation, snd_pcm_read_areas function will be stuck in busy loop as below:
avail = snd_pcm_avail_update(pcm); * // here always return avail=0, due to the second salve pcm device wasn't ready* if (avail < 0) { err = avail; goto _end; } if (avail == 0) { if (state == SND_PCM_STATE_DRAINING) goto _end; if (pcm->mode & SND_PCM_NONBLOCK) { err = -EAGAIN; goto _end; }
err = snd_pcm_wait(pcm, -1); * // return immediately, due to the master slave pcm was ready for read.* if (err < 0) break; goto _again; *// stuck in busy loop !! again and again until the second pcm data was ready !!!*
}
it seemed that the root cause is that the two devices have obvious interrupt period gap , and we also found that this issue can be easily reproduced on our device under low memory case.
Currently we monitor this gap and return error to up layer to close-and-reopen device to fix this issue. So I wonder if there is any good solution ?
Thanks
Dne 25. 07. 19 v 11:59 eleven xiang napsal(a):
Dear,
Currently, for Audio Echo Cancellation process, we combined both mic signal and reference signal into one pcm with the multi plug. And both the mic and ref signal are hw pcm devices, and they lived in the same sound card in driver.
Here is the issue:
- the master slave pcm device is already for read;
- the second salve pcm is not ready for read, which means no data;
- under this situation, snd_pcm_read_areas function will be stuck in busy
loop as below:
avail = snd_pcm_avail_update(pcm); * // here always return avail=0,
due to the second salve pcm device wasn't ready* if (avail < 0) { err = avail; goto _end; } if (avail == 0) { if (state == SND_PCM_STATE_DRAINING) goto _end; if (pcm->mode & SND_PCM_NONBLOCK) { err = -EAGAIN; goto _end; }
err = snd_pcm_wait(pcm, -1); * // return immediately, due to
the master slave pcm was ready for read.* if (err < 0) break; goto _again; *// stuck in busy loop !! again and again until the second pcm data was ready !!!*
}
it seemed that the root cause is that the two devices have obvious interrupt period gap , and we also found that this issue can be easily reproduced on our device under low memory case.
Currently we monitor this gap and return error to up layer to close-and-reopen device to fix this issue. So I wonder if there is any good solution ?
I tried to resolve this sync in my latest pcm_multi updates (all are in 1.1.9 already). Could you trace, why snd_pcm_wait() does not really wait for the slave when avail == 0? There should not be the busy loop. The snd_pcm_multi_may_wait_for_avail_min() callback should be called inside the multi plugin.
Jaroslav
Dear Jaroslav,
So glad to read your mail ~
I have read the multi plug pcm's *snd_pcm_multi_may_wait_for_avail_min*() function, from your reply, this function will wait for avail_min ready ?
and from the detail implementation, multi pcm's *snd_pcm_multi_may_wait_for_avail_min*() will call each pcm's *may_wait_for_avail_min* function. And here is the problem, the hardware pcm_hw device didn't implement this interface, so it will not wait, just skip it.
as for why snd_pcm_wait() does not wait even when avil==0, we found below code:
*// snd_pcm_wait() only poll master slave fd.* static int snd_pcm_multi_poll_descriptors_count(snd_pcm_t *pcm) { snd_pcm_multi_t *multi = pcm->private_data; snd_pcm_t **slave_0* = multi->slaves[multi->master_slave].pcm; return snd_pcm_poll_descriptors_count(*slave_0*); *// only check master slave pcm ??* }
back to our issue, the master slave was ready to read, but the second slave pcm wasn' t ready, so snd_pcm_wait() will return immediately due to master slave ready.
Thanks
Jaroslav Kysela perex@perex.cz 于2019年7月27日周六 下午5:38写道:
Dne 25. 07. 19 v 11:59 eleven xiang napsal(a):
Dear,
Currently, for Audio Echo Cancellation process, we combined both mic
signal
and reference signal into one pcm with the multi plug. And both the mic and ref signal are hw pcm devices, and they lived in the same sound card in driver.
Here is the issue:
- the master slave pcm device is already for read;
- the second salve pcm is not ready for read, which means no data;
- under this situation, snd_pcm_read_areas function will be stuck in
busy
loop as below:
avail = snd_pcm_avail_update(pcm); * // here always return
avail=0,
due to the second salve pcm device wasn't ready* if (avail < 0) { err = avail; goto _end; } if (avail == 0) { if (state == SND_PCM_STATE_DRAINING) goto _end; if (pcm->mode & SND_PCM_NONBLOCK) { err = -EAGAIN; goto _end; }
err = snd_pcm_wait(pcm, -1); * // return immediately, due to
the master slave pcm was ready for read.* if (err < 0) break; goto _again; *// stuck in busy loop !! again and again until the second pcm data was ready !!!*
}
it seemed that the root cause is that the two devices have obvious interrupt period gap , and we also found that this issue can be easily reproduced on our device under low memory case.
Currently we monitor this gap and return error to up layer to close-and-reopen device to fix this issue. So I wonder if there is any good solution ?
I tried to resolve this sync in my latest pcm_multi updates (all are in 1.1.9 already). Could you trace, why snd_pcm_wait() does not really wait for the slave when avail == 0? There should not be the busy loop. The snd_pcm_multi_may_wait_for_avail_min() callback should be called inside the multi plugin.
Jaroslav
-- Jaroslav Kysela perex@perex.cz Linux Sound Maintainer; ALSA Project; Red Hat, Inc.
participants (2)
-
eleven xiang
-
Jaroslav Kysela