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>
