Date: Mon, 11 Jun 2001 18:31:02 -0400 (EDT) From: "Alexander N. Kabaev" <ak03@gte.com> To: FreeBSD-gnats-submit@freebsd.org Cc: cg@freebsd.org Subject: kern/28084: Two possible PCM problems and patch Message-ID: <200106112231.f5BMV2k00928@h132-197-97-45.gte.com>
next in thread | raw e-mail | index | archive | help
>Number: 28084 >Category: kern >Synopsis: Two possible PCM problems and patch >Confidential: no >Severity: serious >Priority: low >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Mon Jun 11 15:40:01 PDT 2001 >Closed-Date: >Last-Modified: >Originator: Alexander N. Kabaev >Release: FreeBSD 5.0-CURRENT i386 >Organization: Verizon Information Technology >Environment: System: FreeBSD kanpc.gte.com 5.0-CURRENT FreeBSD 5.0-CURRENT #21: Fri Jun 8 12:48:33 EDT 2001 root@kanpc.gte.com:/usr/src/sys/compile/KANPC i386 >Description: There are three possible promlems in the -CURRENT PCM code a) pcm_chn_add deletes channel passed to it as a parameter, even though all pcm_chn_add callers call pcm_chn_destroy themselves when pcm_chn_add fails. pcm_chn_destroy then attempts to delete pcm_channel struct which already has been deleted b) dynamic sysctl handler for the number of virtual channels does not resize d->arec and d->aplay arrays. The code like d->aplay[chan] is used all over the place in PCM, and in presence of dynamically allocated vchannels channel number can be bigger than d->maxchan which is statically computed in pcm_register based of the number of actual hardware channels. c) When creating additional vchannels, the code sets CHN_F_BUSY flag _before_ calling vchan_create and fails to clean that flag when vchan_create returns error and no other vchannels weres created, thus leaving the parent channel permanently busy. >How-To-Repeat: N/A >Fix: Attached patch patch tries to address the above problems. With patch applied I was able to run my sbc16 sound card with 4 vchannels all playing simultaneously :) Index: pcm/sound.c =================================================================== RCS file: /usr/ncvs/src/sys/dev/sound/pcm/sound.c,v retrieving revision 1.48 diff -u -r1.48 sound.c --- pcm/sound.c 2001/06/10 15:48:03 1.48 +++ pcm/sound.c 2001/06/11 20:09:47 @@ -345,10 +345,8 @@ int unit = device_get_unit(d->dev); sce = malloc(sizeof(*sce), M_DEVBUF, M_WAITOK | M_ZERO); - if (!sce) { - free(ch, M_DEVBUF); + if (!sce) return ENOMEM; - } snd_mtxlock(d->lock); sce->channel = ch; Index: pcm/vchan.c =================================================================== RCS file: /usr/ncvs/src/sys/dev/sound/pcm/vchan.c,v retrieving revision 1.2 diff -u -r1.2 vchan.c --- pcm/vchan.c 2001/06/07 20:06:22 1.2 +++ pcm/vchan.c 2001/06/11 22:07:31 @@ -331,8 +331,8 @@ { struct snddev_info *d; struct snddev_channel *sce; - struct pcm_channel *c; - int err, newcnt, cnt; + struct pcm_channel *c, **arec, **aplay; + int err, newcnt, cnt, sz; d = oidp->oid_arg1; @@ -373,12 +373,36 @@ snd_mtxunlock(d->lock); return EBUSY; addok: + if (d->maxchans < (d->chancount + newcnt - cnt)) { + sz = (d->chancount + newcnt - cnt) * + sizeof(struct pcm_channel *); + aplay = (struct pcm_channel **) + malloc(sz, M_DEVBUF, M_WAITOK | M_ZERO); + arec = (struct pcm_channel **) + malloc(sz, M_DEVBUF, M_WAITOK | M_ZERO); + if (!arec || !aplay) { + if (aplay) free(aplay, M_DEVBUF); + if (arec) free(arec, M_DEVBUF); + return ENOMEM; + } + sz = d->maxchans * sizeof(struct pcm_channel *); + bcopy(d->arec, arec, sz); + bcopy(d->aplay, aplay, sz); + free(d->arec, M_DEVBUF); + free(d->aplay, M_DEVBUF); + d->arec = arec; + d->aplay = aplay; + d->maxchans = d->chancount + newcnt - cnt; + } c->flags |= CHN_F_BUSY; while (err == 0 && newcnt > cnt) { err = vchan_create(c); if (err == 0) cnt++; } + /* Clear parent busy flag if no children were created */ + if (SLIST_EMPTY(&c->children)) + c->flags &= ~CHN_F_BUSY; } else if (newcnt < cnt) { while (err == 0 && newcnt < cnt) { SLIST_FOREACH(sce, &d->channels, link) { >Release-Note: >Audit-Trail: >Unformatted: To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-bugs" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200106112231.f5BMV2k00928>