Hello Paolo, See below. On Oct 20, Paolo Pisati wrote: > from my dmesg: > [snip] > exclusive sleep mutex pcm0:mixer (pcm mixer) r = 0 (0xc2d34540) locked @ > /usr/src/sys/dev/sound/pcm/mixer.c:322
Could you try deleting the snd_mtxlock and snd_mtxunlock in mixer_hwvol_init() in mixer.c? I think it's uneeded as the function is only called in particular device instance creation and no-one should be able touch it yet. > > acquiring duplicate lock of same type: "pcm channel" > 1st pcm0:record:0 @ /usr/src/sys/dev/sound/pcm/sound.c:195 > 2nd pcm0:play:0 @ /usr/src/sys/dev/sound/pcm/sound.c:195 > Stack backtrace: Please try my "wild guess" patch that is attached. I tried to re-arrange the routine to only hold one locked channel at a time. I suppose another option would be flag the lock type as having duplicates ok. --Mat -- If you optimize everything, you will always be unhappy. - Don Knuth
--- dspold.c Sun Sep 14 17:49:38 2003 +++ dsp.c Tue Oct 21 14:38:44 2003 @@ -174,6 +174,8 @@ intrmask_t s; u_int32_t fmt; int devtype; + int rdref; + int error; s = spltty(); d = dsp_get_info(i_dev); @@ -209,6 +211,8 @@ panic("impossible devtype %d", devtype); } + rdref = 0; + /* lock snddev so nobody else can monkey with it */ pcm_lock(d); @@ -251,67 +255,66 @@ return EBUSY; } /* got a channel, already locked for us */ - } - - if (flags & FWRITE) { - /* open for write */ - wrch = pcm_chnalloc(d, PCMDIR_PLAY, td->td_proc->p_pid, -1); - if (!wrch) { - /* no channel available */ - if (flags & FREAD) { - /* just opened a read channel, release it */ - pcm_chnrelease(rdch); - } - /* exit */ - pcm_unlock(d); - splx(s); - return EBUSY; - } - /* got a channel, already locked for us */ - } - - i_dev->si_drv1 = rdch; - i_dev->si_drv2 = wrch; - - /* Bump refcounts, reset and unlock any channels that we just opened, - * and then release device lock. - */ - if (flags & FREAD) { if (chn_reset(rdch, fmt)) { pcm_chnrelease(rdch); i_dev->si_drv1 = NULL; - if (wrch && (flags & FWRITE)) { - pcm_chnrelease(wrch); - i_dev->si_drv2 = NULL; - } pcm_unlock(d); splx(s); return ENODEV; } + if (flags & O_NONBLOCK) rdch->flags |= CHN_F_NBIO; pcm_chnref(rdch, 1); CHN_UNLOCK(rdch); + rdref = 1; + /* + * Record channel created, ref'ed and unlocked + */ } + if (flags & FWRITE) { - if (chn_reset(wrch, fmt)) { - pcm_chnrelease(wrch); - i_dev->si_drv2 = NULL; - if (flags & FREAD) { - CHN_LOCK(rdch); - pcm_chnref(rdch, -1); - pcm_chnrelease(rdch); - i_dev->si_drv1 = NULL; - } - pcm_unlock(d); - splx(s); - return ENODEV; + /* open for write */ + wrch = pcm_chnalloc(d, PCMDIR_PLAY, td->td_proc->p_pid, -1); + error = 0; + + if (!wrch) + error = EBUSY; /* XXX Right return code? */ + else if (chn_reset(wrch, fmt)) + error = ENODEV; + + if (error != 0) { + if (wrch) { + /* + * Free play channel + */ + pcm_chnrelease(wrch); + i_dev->si_drv2 = NULL; } - if (flags & O_NONBLOCK) - wrch->flags |= CHN_F_NBIO; - pcm_chnref(wrch, 1); - CHN_UNLOCK(wrch); + if (rdref) { + /* + * Lock, deref and release previously created record channel + */ + CHN_LOCK(rdch); + pcm_chnref(rdch, -1); + pcm_chnrelease(rdch); + i_dev->si_drv1 = NULL; + } + + pcm_unlock(d); + splx(s); + return error; + } + + if (flags & O_NONBLOCK) + wrch->flags |= CHN_F_NBIO; + pcm_chnref(wrch, 1); + CHN_UNLOCK(wrch); } + + i_dev->si_drv1 = rdch; + i_dev->si_drv2 = wrch; + pcm_unlock(d); splx(s); return 0;
_______________________________________________ [EMAIL PROTECTED] mailing list http://lists.freebsd.org/mailman/listinfo/freebsd-current To unsubscribe, send any mail to "[EMAIL PROTECTED]"