* How to report error in _pointer function?
@ 2008-07-30 15:56 Timur Tabi
2008-07-30 16:12 ` Takashi Iwai
0 siblings, 1 reply; 10+ messages in thread
From: Timur Tabi @ 2008-07-30 15:56 UTC (permalink / raw)
To: alsa-devel
In my driver, I can detect in the _pointer callback function whether
or not the DMA engine has actually started. Sometimes, when I have a
programming error, the DMA will not start, so my _pointer function
calculates a crazy value for the current position. The number it
returns causes ALSA to go haywire (see my post titled, "underrun!!!
(at least 1786051083.613 ms long)".
What is the best way to handle this? Is there a way I can tell ALSA,
"hey, this is really screwed up, just abort playback and return an
error to the app"?
--
Timur Tabi
Linux kernel developer at Freescale
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: How to report error in _pointer function?
2008-07-30 15:56 How to report error in _pointer function? Timur Tabi
@ 2008-07-30 16:12 ` Takashi Iwai
2008-08-06 21:54 ` Timur Tabi
0 siblings, 1 reply; 10+ messages in thread
From: Takashi Iwai @ 2008-07-30 16:12 UTC (permalink / raw)
To: Timur Tabi; +Cc: alsa-devel
At Wed, 30 Jul 2008 10:56:31 -0500,
Timur Tabi wrote:
>
> In my driver, I can detect in the _pointer callback function whether
> or not the DMA engine has actually started. Sometimes, when I have a
> programming error, the DMA will not start, so my _pointer function
> calculates a crazy value for the current position. The number it
> returns causes ALSA to go haywire (see my post titled, "underrun!!!
> (at least 1786051083.613 ms long)".
>
> What is the best way to handle this? Is there a way I can tell ALSA,
> "hey, this is really screwed up, just abort playback and return an
> error to the app"?
You can return SNDRV_PCM_POS_XRUN from the pointer callback (with
kernel messages if you like). Then the PCM stream is stopped and the
status is changed to SND_PCM_STATUS_XRUN. Further access will result
in -EPIPE.
I guess this doesn't fully satisfy your demand, but maybe better than
now :) We'd need a mechanism to pass a proper error code if other
critical error code must be passed.
Takashi
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: How to report error in _pointer function?
2008-07-30 16:12 ` Takashi Iwai
@ 2008-08-06 21:54 ` Timur Tabi
2008-08-07 16:29 ` Takashi Iwai
0 siblings, 1 reply; 10+ messages in thread
From: Timur Tabi @ 2008-08-06 21:54 UTC (permalink / raw)
To: Takashi Iwai; +Cc: alsa-devel
Takashi Iwai wrote:
> You can return SNDRV_PCM_POS_XRUN from the pointer callback (with
> kernel messages if you like). Then the PCM stream is stopped and the
> status is changed to SND_PCM_STATUS_XRUN. Further access will result
> in -EPIPE.
This doesn't seem to work. I don't get any more underrun/overrun messages, but
the application doesn't know that something's failed.
With mplayer, I see this message:
alsa-lib: pcm_hw.c:405:(snd_pcm_hw_hwsync) SNDRV_PCM_IOCTL_HWSYNC failed: Broken
pipe
And then mplayer hangs with the status bar here:
A: 0.0 (00.0) of 249.0 (04:09.0) ??,?% $<50>
aplay just hangs.
I also tried adding this code to my _pointer function:
snd_pcm_stream_lock_irqsave(substream, flags);
if (snd_pcm_running(substream))
snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
snd_pcm_stream_unlock_irqrestore(substream, flags);
but it didn't make any difference.
--
Timur Tabi
Linux kernel developer at Freescale
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: How to report error in _pointer function?
2008-08-06 21:54 ` Timur Tabi
@ 2008-08-07 16:29 ` Takashi Iwai
2008-08-07 18:59 ` Timur Tabi
0 siblings, 1 reply; 10+ messages in thread
From: Takashi Iwai @ 2008-08-07 16:29 UTC (permalink / raw)
To: Timur Tabi; +Cc: alsa-devel
At Wed, 06 Aug 2008 16:54:38 -0500,
Timur Tabi wrote:
>
> Takashi Iwai wrote:
>
> > You can return SNDRV_PCM_POS_XRUN from the pointer callback (with
> > kernel messages if you like). Then the PCM stream is stopped and the
> > status is changed to SND_PCM_STATUS_XRUN. Further access will result
> > in -EPIPE.
>
> This doesn't seem to work. I don't get any more underrun/overrun messages, but
> the application doesn't know that something's failed.
>
> With mplayer, I see this message:
>
> alsa-lib: pcm_hw.c:405:(snd_pcm_hw_hwsync) SNDRV_PCM_IOCTL_HWSYNC failed: Broken
> pipe
>
> And then mplayer hangs with the status bar here:
>
> A: 0.0 (00.0) of 249.0 (04:09.0) ??,?% $<50>
>
> aplay just hangs.
Hm... The behavior with returning SNDRV_PCM_POS_XRUN is basically
identical with the real XRUN detection. I guess the XRUN-stop
mechanism doesn't work well with the case of hwsync.
How is the PCM status during hang? Check
/proc/asound/card0/pcm*/sub*/* files.
Also, could you run with gdb and check at which code-path is it
stopped?
thanks,
Takashi
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: How to report error in _pointer function?
2008-08-07 16:29 ` Takashi Iwai
@ 2008-08-07 18:59 ` Timur Tabi
2008-08-08 12:03 ` Takashi Iwai
0 siblings, 1 reply; 10+ messages in thread
From: Timur Tabi @ 2008-08-07 18:59 UTC (permalink / raw)
To: Takashi Iwai; +Cc: alsa-devel
On Thu, Aug 7, 2008 at 11:29 AM, Takashi Iwai <tiwai@suse.de> wrote:
> How is the PCM status during hang? Check
> /proc/asound/card0/pcm*/sub*/* files.
I wrote a script that repeatedly dumps the contents of
/proc/asound/card0/pcm0p/sub0/status. I started playback, and it
shows this:
...
closed
closed
closed
state: OPEN
trigger_time: 0.000000000
tstamp : 0.000000000
delay : 0
avail : 0
avail_max : 0
-----
hw_ptr : 0
appl_ptr : 0
state: OPEN
trigger_time: 0.000000000
tstamp : 0.000000000
delay : 0
avail : 0
avail_max : 0
-----
hw_ptr : 0
appl_ptr : 0
state: XRUN
trigger_time: 165.300191122
tstamp : 165.302136461
delay : 0
avail : 0
avail_max : 0
-----
hw_ptr : 0
appl_ptr : 17840
state: XRUN
trigger_time: 165.300191122
tstamp : 165.304661787
delay : 0
avail : 0
avail_max : 0
-----
hw_ptr : 0
appl_ptr : 17840
state: XRUN
trigger_time: 165.300191122
tstamp : 165.306860459
delay : 0
avail : 0
avail_max : 0
-----
hw_ptr : 0
appl_ptr : 17840
and so on.
> Also, could you run with gdb and check at which code-path is it
> stopped?
Sorry, I don't use gdb that much. How can I do this? I don't think I
have debug versions of alsa-lib or mplayer.
--
Timur Tabi
Linux kernel developer at Freescale
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: How to report error in _pointer function?
2008-08-07 18:59 ` Timur Tabi
@ 2008-08-08 12:03 ` Takashi Iwai
2008-08-08 15:55 ` Timur Tabi
2008-08-08 22:26 ` Timur Tabi
0 siblings, 2 replies; 10+ messages in thread
From: Takashi Iwai @ 2008-08-08 12:03 UTC (permalink / raw)
To: Timur Tabi; +Cc: alsa-devel
At Thu, 7 Aug 2008 13:59:56 -0500,
Timur Tabi wrote:
>
> On Thu, Aug 7, 2008 at 11:29 AM, Takashi Iwai <tiwai@suse.de> wrote:
>
> > How is the PCM status during hang? Check
> > /proc/asound/card0/pcm*/sub*/* files.
>
> I wrote a script that repeatedly dumps the contents of
> /proc/asound/card0/pcm0p/sub0/status. I started playback, and it
> shows this:
...
> hw_ptr : 0
> appl_ptr : 17840
> state: XRUN
> trigger_time: 165.300191122
> tstamp : 165.304661787
> delay : 0
> avail : 0
> avail_max : 0
So, the PCM status is properly changed to XRUN as expected. From the
driver perspective, everything must be fine.
> > Also, could you run with gdb and check at which code-path is it
> > stopped?
>
> Sorry, I don't use gdb that much. How can I do this? I don't think I
> have debug versions of alsa-lib or mplayer.
What about ltrace? I'd like to know which functions are called.
Takashi
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: How to report error in _pointer function?
2008-08-08 12:03 ` Takashi Iwai
@ 2008-08-08 15:55 ` Timur Tabi
2008-08-08 22:26 ` Timur Tabi
1 sibling, 0 replies; 10+ messages in thread
From: Timur Tabi @ 2008-08-08 15:55 UTC (permalink / raw)
To: Takashi Iwai; +Cc: alsa-devel
Takashi Iwai wrote:
> What about ltrace? I'd like to know which functions are called.
This is an embedded system. I don't have ltrace or strace installed.
I suspect that this problem can easily be reproduced on any system. Just modify
the _pointer function to always return XRUN, and see what aplay does.
Anyway, I tried debugging aplay. I'm not familiar with ALSA application
programming (just drivers), so I don't know what to look for, but I did find a
pattern.
I set a breakpoint on function snd_pcm_hw_writei(), which I presume is an
alsa-lib function. When I run aplay, the breakpoint is hit:
Breakpoint 1, snd_pcm_hw_writei (pcm=0x10024fd8, buffer=0x100250e8, size=6000)
at pcm_hw.c:627
627 err = ioctl(fd, SNDRV_PCM_IOCTL_WRITEI_FRAMES, &xferi);
(gdb)
I hit continue, and then it immediately stops at this function again. I can do
continue four more times and it does the same thing. On the sixth "continue",
there is an 8-second delay. Then my driver prints a message saying that it's
returning XRUN, and GDB stops again at snd_pcm_hw_writei(). I don't know what's
happening during that 8-second delay.
This whole process repeats forever.
--
Timur Tabi
Linux kernel developer at Freescale
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: How to report error in _pointer function?
2008-08-08 12:03 ` Takashi Iwai
2008-08-08 15:55 ` Timur Tabi
@ 2008-08-08 22:26 ` Timur Tabi
2008-08-11 7:19 ` Takashi Iwai
1 sibling, 1 reply; 10+ messages in thread
From: Timur Tabi @ 2008-08-08 22:26 UTC (permalink / raw)
To: Takashi Iwai; +Cc: alsa-devel
Takashi Iwai wrote:
> So, the PCM status is properly changed to XRUN as expected. From the
> driver perspective, everything must be fine.
I've been debugging aplay. The main loop is function pcm_write(). It calls
writei_func() which returns -EPIPE. This causes aplay to jump to xrun(), which
attempts to recover.
This is not what I want. I don't want to return overrun/underrun. I want to
return failure. Returning XRUN is wrong.
Instead, I need to take a look at this code I have:
snd_pcm_stream_lock_irqsave(substream, flags);
if (snd_pcm_running(substream))
snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
snd_pcm_stream_unlock_irqrestore(substream, flags);
It's the call to snd_pcm_stop() that I don't like. There doesn't appear to be a
SNDRV_PCM_STATE_xxx state that makes sense. This function should eventually
bring me to snd_pcm_pre_stop(). But this function returns -EBADFD because the
current state is RUNNING and not OPEN. Because it returns an error,
snd_pcm_do_stop() is never called.
This doesn't make any sense to me. Why should I be able to stop a stream only
if it's open but not running? If it's open, but not running, then there's
nothing to stop! Can you explain the restriction in snd_pcm_pre_stop()?
--
Timur Tabi
Linux kernel developer at Freescale
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: How to report error in _pointer function?
2008-08-08 22:26 ` Timur Tabi
@ 2008-08-11 7:19 ` Takashi Iwai
2008-08-11 15:37 ` Timur Tabi
0 siblings, 1 reply; 10+ messages in thread
From: Takashi Iwai @ 2008-08-11 7:19 UTC (permalink / raw)
To: Timur Tabi; +Cc: alsa-devel
At Fri, 08 Aug 2008 17:26:11 -0500,
Timur Tabi wrote:
>
> Takashi Iwai wrote:
>
> > So, the PCM status is properly changed to XRUN as expected. From the
> > driver perspective, everything must be fine.
>
> I've been debugging aplay. The main loop is function pcm_write(). It calls
> writei_func() which returns -EPIPE. This causes aplay to jump to xrun(), which
> attempts to recover.
>
> This is not what I want. I don't want to return overrun/underrun. I want to
> return failure. Returning XRUN is wrong.
>
> Instead, I need to take a look at this code I have:
>
> snd_pcm_stream_lock_irqsave(substream, flags);
>
> if (snd_pcm_running(substream))
> snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
>
> snd_pcm_stream_unlock_irqrestore(substream, flags);
>
> It's the call to snd_pcm_stop() that I don't like. There doesn't appear to be a
> SNDRV_PCM_STATE_xxx state that makes sense. This function should eventually
> bring me to snd_pcm_pre_stop(). But this function returns -EBADFD because the
> current state is RUNNING and not OPEN. Because it returns an error,
> snd_pcm_do_stop() is never called.
Hm? snd_pcm_pre_stop() returns -EBADFD if the stream *IS* OPEN.
If it's RUNNING, it will stop the stream and change the state.
> This doesn't make any sense to me. Why should I be able to stop a stream only
> if it's open but not running? If it's open, but not running, then there's
> nothing to stop! Can you explain the restriction in snd_pcm_pre_stop()?
If the state is OPEN, it means that the stream is already stopped.
Not sure which version you are referring, but I see no problem in the current code, at least...
Takashi
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: How to report error in _pointer function?
2008-08-11 7:19 ` Takashi Iwai
@ 2008-08-11 15:37 ` Timur Tabi
0 siblings, 0 replies; 10+ messages in thread
From: Timur Tabi @ 2008-08-11 15:37 UTC (permalink / raw)
To: Takashi Iwai; +Cc: alsa-devel
Takashi Iwai wrote:
> Hm? snd_pcm_pre_stop() returns -EBADFD if the stream *IS* OPEN.
> If it's RUNNING, it will stop the stream and change the state.
Hmmm.... you're right. I don't know what I was thinking.
Tracing the code, I see that ALSA does call my driver's trigger function to stop
the stream. So why doesn't the application also stop?
--
Timur Tabi
Linux kernel developer at Freescale
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2008-08-11 15:37 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-07-30 15:56 How to report error in _pointer function? Timur Tabi
2008-07-30 16:12 ` Takashi Iwai
2008-08-06 21:54 ` Timur Tabi
2008-08-07 16:29 ` Takashi Iwai
2008-08-07 18:59 ` Timur Tabi
2008-08-08 12:03 ` Takashi Iwai
2008-08-08 15:55 ` Timur Tabi
2008-08-08 22:26 ` Timur Tabi
2008-08-11 7:19 ` Takashi Iwai
2008-08-11 15:37 ` Timur Tabi
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.