Skip site navigation (1)Skip section navigation (2)
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>