sound/pcm/* bugs (was: Re: page fault panic tracked down (selwakeuppri()) - really sound/pcm/*)

Don Lewis truckman at FreeBSD.org
Sun Jan 18 14:35:06 PST 2004


On 18 Jan, Stefan Ehmann wrote:
> On Sat, 2004-01-17 at 10:15, Don Lewis wrote:
>> I think this problem can be caused by a transient malloc() M_NOWAIT
>> failure.
>> 
>> Changes in this version of the patch:
>> 
>> 	When increasing blksz in chn_setblocksize(), increase the size
>> 	of bufsoft before increasing bufhard, and decrease bufsoft after
>> 	decreasing bufhard in an attempt to avoid the buffer overflow in
>> 	feed_vchan_s16().
>> 	
>> 	Buffers are now allocated using M_WAITOK, requiring locks to
>> 	be dropped for the malloc() calls.  This required adding a mutex
>> 	parameter to sndbuf_remalloc().
>> 
>> 	Locking order between parent and child channels is changed.  The
>>         parent is now locked first and then the child.  The list of
>>         children is protected by the parent's lock.  There are still
>>         potential race conditions in the vchan creation/destruction code
>>         because all the locks have to be dropped in order to call
>>         malloc(), etc.
>> 
>> 	Locking cleaned up to eliminate the need for MTX_RECURSE.
>> 
>> 	A new mutex allocator for the channel mutexes was added that
>> 	initializes the mutexes with the MTX_DUPOK flags so that multiple
>> 	channel mutexes of the same type can be held at once.
>> 
>> 	Locking simplification in dsp_ioctl().
>> 
>> 	Added KASSERTs in chn_wrfeed().
> 
> Using this patch (and the small changes to avoid the esd problem) I got
> an assertion triggered in channel.c: chn_wrfeed amt > source size

Doh!

I was sort of afraid that might happen when the buffer size got set back
down to the size I intended.  Dit it happen immediately, or did you get
some sound first?

> #0  doadump () at /usr/src/sys/kern/kern_shutdown.c:240
> #1  0xc04e57c8 in boot (howto=256) at
> /usr/src/sys/kern/kern_shutdown.c:372
> #2  0xc04e5b57 in panic () at /usr/src/sys/kern/kern_shutdown.c:550
> #3  0xc07e36cd in chn_wrfeed (c=0xc37a8880)
>     at /usr/src/sys/dev/sound/pcm/channel.c:219
> #4  0xc07e377f in chn_wrintr (c=0xc37a8880)
>     at /usr/src/sys/dev/sound/pcm/channel.c:239
> #5  0xc07e3f70 in chn_intr (c=0xc37a8880)
>     at /usr/src/sys/dev/sound/pcm/channel.c:485
> #6  0xc07fda2f in csa_intr (p=0xc37a8700)
>     at /usr/src/sys/dev/sound/pci/csapcm.c:623
> #7  0xc07fc724 in csa_intr (arg=0xc37a8600)
>     at /usr/src/sys/dev/sound/pci/csa.c:532
> #8  0xc04d1c62 in ithread_loop (arg=0xc1736b00)
>     at /usr/src/sys/kern/kern_intr.c:544
> #9  0xc04d0c54 in fork_exit (callout=0xc04d1ad0 <ithread_loop>, arg=0x0,
> 
>     frame=0x0) at /usr/src/sys/kern/kern_fork.c:797
> 
> In frame #3 amt evaluates to 2176, bufsize is 2048

I just don't see how this can be happening.  Your hardware has a fixed
4K buffer size.  My changes to chn_setblocksize() should prevent bufsoft
from dropping below this value.

The only place that bufsoft is allocated appears to be in
chn_setblocksize().  Try inserting the following KASSERT() into two
locations in chn_setblocksize(), between the "if" test and the "return
EINVAL" at the beginning of the function (adding the necessary
brackets), and after the "out" label at the end of the function.

        KASSERT(sndbuf_getsize(bs) ==  0 ||
            sndbuf_getsize(bs) >= sndbuf_getsize(b),
            ("%s: bufsoft size %d < bufhard size %d", c->name,
            sndbuf_getsize(bs), sndbuf_getsize(b)));


Hopefully this will catch the problem closer to the source, but I still
don't see how this can be happening ...




More information about the freebsd-current mailing list