From: Clemens Ladisch <clemens@ladisch.de>
To: Kelly Anderson <kelly@silka.with-linux.com>
Cc: Nix <nix@esperi.org.uk>,
"Christopher K." <c.krooss@googlemail.com>,
linux-kernel@vger.kernel.org, alsa-devel@alsa-project.org
Subject: Re: Linux 2.6.38 freeze because of sound/core/pcm_lib.c commit 59ff878ffb26bc0be812ca8295799164f413ae88
Date: Fri, 01 Apr 2011 09:47:59 +0200 [thread overview]
Message-ID: <4D95832F.3020200@ladisch.de> (raw)
In-Reply-To: <4D952B76.7000201@silka.with-linux.com>
Kelly Anderson wrote:
> OK, I debugged the problem and came up with a solution. The bottom line
> is that it's a problem with a signed to unsigned compare.
Aaargh, I didn't suspect this.
> First the fix:
>
> --- ./sound/core/pcm_lib.c.orig 2011-03-27 12:37:20.000000000 -0600
> +++ ./sound/core/pcm_lib.c 2011-03-31 19:01:35.392739127 -0600
> @@ -379,17 +379,17 @@ static int snd_pcm_update_hw_ptr0(struct
> * Without regular period interrupts, we have to check
> * the elapsed time to detect xruns.
> */
> - jdelta = jiffies - runtime->hw_ptr_jiffies;
> - if (jdelta < runtime->hw_ptr_buffer_jiffies / 2)
> + jdelta = (snd_pcm_sframes_t)(jiffies - runtime->hw_ptr_jiffies);
> + if (jdelta < (snd_pcm_sframes_t)runtime->hw_ptr_buffer_jiffies / 2)
> goto no_delta_check;
> hdelta = jdelta - delta * HZ / runtime->rate;
> - while (hdelta > runtime->hw_ptr_buffer_jiffies / 2 + 1) {
> + while (hdelta > (snd_pcm_sframes_t)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;
> + hdelta -= (snd_pcm_sframes_t)runtime->hw_ptr_buffer_jiffies;
> }
> goto no_delta_check;
> }
Most of these casts have no effect; only the loop condition is
important. Please test the patch below.
Kelly, to apply this patch I need a Signed-off-by tag from you (see
Documentation/SubmittingPatches).
--8<---------------------------------------------------------------->8--
ALSA: pcm: fix infinite loop in snd_pcm_update_hw_ptr0()
When period interrupts are disabled, snd_pcm_update_hw_ptr0() compares
the current time against the time estimated for the current hardware
pointer to detect xruns. The somewhat fuzzy threshold in the while loop
makes it possible that hdelta becomes negative; the comparison being
done with unsigned types then makes the loop go through the entire 2^63
negative range, and, depending on the value, never reaching an unsigned
value that is small enough to stop the loop. Doing this with interrupts
disabled results in the machine locking up.
To prevent this, ensure that the loop condition uses signed types for
both operands so that the comparison is correctly done.
Many thanks to Kelly Anderson for debugging this.
Reported-by: Nix <nix@esperi.org.uk>
Reported-by: "Christopher K." <c.krooss@googlemail.com>
Reported-by: Kelly Anderson <kelly@silka.with-linux.com>
[cl: remove unneeded casts; use a temp variable]
Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -375,6 +375,7 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
}
if (runtime->no_period_wakeup) {
+ snd_pcm_sframes_t xrun_threshold;
/*
* Without regular period interrupts, we have to check
* the elapsed time to detect xruns.
@@ -383,7 +384,8 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
if (jdelta < runtime->hw_ptr_buffer_jiffies / 2)
goto no_delta_check;
hdelta = jdelta - delta * HZ / runtime->rate;
+ xrun_threshold = runtime->hw_ptr_buffer_jiffies / 2 + 1;
- while (hdelta > runtime->hw_ptr_buffer_jiffies / 2 + 1) {
+ while (hdelta > xrun_threshold) {
delta += runtime->buffer_size;
hw_base += runtime->buffer_size;
if (hw_base >= runtime->boundary)
next prev parent reply other threads:[~2011-04-01 7:46 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <AANLkTin17=rCU4eDGYtnVFZ1ffbUn+var4Q_AQUuGKaw@mail.gmail.com>
2011-03-31 11:58 ` Linux 2.6.38 freeze because of sound/core/pcm_lib.c commit 59ff878ffb26bc0be812ca8295799164f413ae88 Clemens Ladisch
2011-03-31 16:09 ` Christopher K.
2011-03-31 21:50 ` Kelly Anderson
2011-04-01 1:33 ` Kelly Anderson
2011-04-01 3:05 ` Christopher K.
2011-04-01 7:47 ` Clemens Ladisch [this message]
2011-04-01 9:10 ` Kelly Anderson
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4D95832F.3020200@ladisch.de \
--to=clemens@ladisch.de \
--cc=alsa-devel@alsa-project.org \
--cc=c.krooss@googlemail.com \
--cc=kelly@silka.with-linux.com \
--cc=linux-kernel@vger.kernel.org \
--cc=nix@esperi.org.uk \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).