[alsa-devel] [PATCH] disable period wakeups

Jaroslav Kysela perex at perex.cz
Thu Nov 18 09:35:27 CET 2010


On Tue, 16 Nov 2010, Clemens Ladisch wrote:

> Jaroslav Kysela wrote:
>>> pl bossart wrote:
>>>> Here's the second set of patches based on feedback from Takashi,
>>>> Jaroslav and Clemens. Hope this is fine now.
>>
>> The problem in the kernel side is that there is no ring buffer boundary
>> check using system jiffies. Without this check, the actual implementation
>> does not guarantee the consistency of hw_ptr.
>
> How about this?

The patch bellow looks good. I would probably add some lightweight 
condition on top like:

 	if (jdelta < runtime->hw_ptr_buffer_jiffies / 2 + 1)
 		goto no_delta_check;

But it's just an optimization. Please, commit.

 					Thanks,
 						Jaroslav

> --8<---------------------------------------------------------------->8--
> ALSA: pcm: detect xruns in no-period-wakeup mode
>
> When period wakeups are disabled, successive calls to the pointer update
> function do not have a maximum allowed distance, so xruns cannot be
> detected with the pointer value only.
>
> To detect xruns, compare the actually elapsed time with the time that
> should have theoretically elapsed since the last update.  When the
> hardware pointer has wrapped around due to an xrun, the actually elapsed
> time will be too big by about hw_ptr_buffer_jiffies.
>
> Signed-off-by: Clemens Ladisch <clemens at ladisch.de>
> ---
> sound/core/pcm_lib.c |   18 ++++++++++++++++--
> 1 file changed, 16 insertions(+), 2 deletions(-)
>
> --- alsa-kernel/sound/core/pcm_lib.c
> +++ alsa-kernel/sound/core/pcm_lib.c
> @@ -374,9 +374,23 @@ static int snd_pcm_update_hw_ptr0(struct
> 			   (unsigned long)runtime->hw_ptr_base);
> 	}
>
> -	/* without period interrupts, there are no regular pointer updates */
> -	if (runtime->no_period_wakeup)
> +	if (runtime->no_period_wakeup) {
> +		/*
> +		 * Without regular period interrupts, we have to check
> +		 * the elapsed time to detect xruns.
> +		 */
> +		jdelta = jiffies - runtime->hw_ptr_jiffies;
> +		hdelta = jdelta - delta * HZ / runtime->rate;
> +		while (hdelta > runtime->hw_ptr_buffer_jiffies / 2 + 1) {
> +			delta += runtime->buffer_size;
> +			hw_base += runtime->buffer_size;
> +			if (hw_base >= runtime->boundary)
> +				hw_base = 0;
> +			new_hw_ptr = hw_base + pos;
> +			hdelta -= runtime->hw_ptr_buffer_jiffies;
> +		}
> 		goto no_delta_check;
> +	}
>
> 	/* something must be really wrong */
> 	if (delta >= runtime->buffer_size + runtime->period_size) {

-----
Jaroslav Kysela <perex at perex.cz>
Linux Kernel Sound Maintainer
ALSA Project, Red Hat, Inc.



More information about the Alsa-devel mailing list