Date: Mon, 22 Oct 2001 02:50:02 -0700 (PDT) From: Daniel Pouzzner <douzzer@mega.nu> To: freebsd-bugs@FreeBSD.org Subject: Re: kern/31429: kernel resource deadlock on /dev/dsp Message-ID: <200110220950.f9M9o2A27170@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
The following reply was made to PR kern/31429; it has been noted by GNATS.
From: Daniel Pouzzner <douzzer@mega.nu>
To: freebsd-gnats-submit@FreeBSD.org
Cc:
Subject: Re: kern/31429: kernel resource deadlock on /dev/dsp
Date: Mon, 22 Oct 2001 05:47:26 -0400 (EDT)
My original submission of half an hour ago was rather flawed, in two
respects:
(1) apparently, it doesn't matter if the dsp was opened WRONLY or RDWR
- a subsequent RDONLY open results in EBUSY either way.
(2) my fix was profoundly bogus, in particular causing a kernel hang
on reboot (probably due to some other resource deadlock introduced
by the code).
Here is a much cleaner fix that seems to actually work all-around.
The changes are that d->arec[chan] is updated immediately after the
allocation, before the pointer can get lost, and the last EBUSY return
in the FWRITE section includes the same un-busying code as the one
before it. I'm not sufficiently familiar with the subsystem to know
if it's important to update d->arec[chan] scrupulously (as I have it
doing now), but it doesn't hurt anything apparently.
int
dsp_open(snddev_info *d, int chan, int oflags, int devtype)
{
pcm_channel *rdch, *wrch;
u_int32_t fmt;
if (chan >= d->chancount) return ENODEV;
if ((d->flags & SD_F_SIMPLEX) && (d->ref[chan] > 0))
return EBUSY;
if (d->atype[chan] != 0 && d->atype[chan] != devtype)
return EBUSY;
rdch = d->arec[chan];
wrch = d->aplay[chan];
if (oflags & FREAD) {
if (rdch == NULL) {
rdch = allocchn(d, PCMDIR_REC);
if (!rdch)
return EBUSY;
d->arec[chan] = rdch;
} else
return EBUSY;
}
if (oflags & FWRITE) {
if (wrch == NULL) {
wrch = allocchn(d, PCMDIR_PLAY);
if (!wrch) {
if (rdch && (oflags & FREAD))
rdch->flags &= ~CHN_F_BUSY;
return EBUSY;
}
} else {
if (rdch && (oflags & FREAD))
rdch->flags &= ~CHN_F_BUSY;
return EBUSY;
}
}
d->atype[chan] = devtype;
d->aplay[chan] = wrch;
d->ref[chan]++;
switch (devtype) {
[...]
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?200110220950.f9M9o2A27170>
