LOR sndstat.c:165 vm_map.c:2997

Don Lewis truckman at FreeBSD.org
Wed Sep 8 00:45:59 PDT 2004


On  6 Sep, Ion-Mihai Tetcu wrote:
>  # uname -a
> FreeBSD it.buh.tecnik93.com 5.3-BETA3 FreeBSD 5.3-BETA3 #1: Sat Sep  4 07:14:07 EEST 2004     itetcu at it.buh.tecnik93.com:/usr/obj/usr/src/sys/IT53_b2_df  i386
> 
> with "normal" debugging stuff minus malloc
> 
>  # cat /dev/sndstat
> FreeBSD Audio Driver (newpcm)
> Installed devices:
> pcm0: <VIA VT8235> at io 0xe400 irq 22 kld snd_via8233 (5p/1r/0v channels duplex default)
> 
> It happen when I've first cat /dev/sndstat, it doesn't happen after.
> 
> Sep  6 10:25:28 it kernel: 1st 0xc07f9800 sndstat (sndstat) @ /usr/src/sys/modules/sound/sound/../../../dev/sound/pcm/sndstat.c:165
> Sep  6 10:25:28 it kernel: 2nd 0xc2e6174c user map (user map) @ /usr/src/sys/vm/vm_map.c:2997
> Sep  6 10:25:28 it kernel: KDB: stack backtrace:
> Sep  6 10:25:28 it kernel: kdb_backtrace(c0687b96,c2e6174c,c069778e,c069778e,c069780e) at kdb_backtrace+0x2e
> Sep  6 10:25:28 it kernel: witness_checkorder(c2e6174c,9,c069780e,bb5,ef65c000) at witness_checkorder+0x6b2
> Sep  6 10:25:28 it kernel: _sx_xlock(c2e6174c,c069780e,bb5,c2279a00,ef26a978) at _sx_xlock+0x7e
> Sep  6 10:25:28 it kernel: _vm_map_lock_read(c2e61708,c069780e,bb5,26446e1,804c000) at _vm_map_lock_read+0x4a
> Sep  6 10:25:28 it kernel: vm_map_lookup(ef26aa20,804c000,2,ef26aa24,ef26aa14) at vm_map_lookup+0x2e
> Sep  6 10:25:28 it kernel: vm_fault(c2e61708,804c000,2,8,c2e8fb00) at vm_fault+0x7e
> Sep  6 10:25:28 it kernel: trap_pfault(ef26aaec,0,804c000,c06df600,804c000) at trap_pfault+0xf7
> Sep  6 10:25:28 it kernel: trap(18,10,10,804c000,c4b56000) at trap+0x34d
> Sep  6 10:25:28 it kernel: calltrap() at calltrap+0x5
> Sep  6 10:25:28 it kernel: --- trap 0xc, eip = 0xc06509aa, esp = 0xef26ab2c, ebp = 0xef26ab60 ---
> Sep  6 10:25:28 it kernel: generic_copyout(c4b56000,8b,ef26ac80,a5,c2e0f660) at generic_copyout+0x36
> Sep  6 10:25:28 it kernel: sndstat_read(c06d6c68,ef26ac80,20000,ef26abc4,c07f82a0) at sndstat_read+0xb5
> Sep  6 10:25:28 it kernel: spec_read(ef26ac0c,ef26ac58,c053c228,ef26ac0c,1020002) at spec_read+0x1e3
> Sep  6 10:25:28 it kernel: spec_vnoperate(ef26ac0c,1020002,c2e8fb00,219,ef26ac80) at spec_vnoperate+0x18
> Sep  6 10:25:28 it kernel: vn_read(c2e0f660,ef26ac80,c4e51480,0,c2e8fb00) at vn_read+0x198
> Sep  6 10:25:28 it kernel: dofileread(c2e8fb00,c2e0f660,3,804c000,1000) at dofileread+0xa4
> Sep  6 10:25:28 it kernel: read(c2e8fb00,ef26ad14,c,431,3) at read+0x6b
> Sep  6 10:25:28 it kernel: syscall(2f,2f,2f,1,bfbfec05) at syscall+0x272
> Sep  6 10:25:28 it kernel: Xint0x80_syscall() at Xint0x80_syscall+0x1f
> Sep  6 10:25:28 it kernel: --- syscall (3, FreeBSD ELF32, read), eip = 0x280d5fbf, esp = 0xbfbfe9dc, ebp = 0xbfbfea68 ---

sndstat_read() is holding a mutex across a call to uiomove(), which is
generally not allowed because accessing the user's buffer can block. The
mutex could be dropped around the call to uiomove(), but it would
require adding another mechanism to keep sndstat_read() from being
re-entered.  I took the lazy route and converted sndstat_lock from a
mutex to an sx lock.


Index: sys/dev/sound/pcm/sndstat.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/sound/pcm/sndstat.c,v
retrieving revision 1.17
diff -u -r1.17 sndstat.c
--- sys/dev/sound/pcm/sndstat.c	16 Jun 2004 09:46:57 -0000	1.17
+++ sys/dev/sound/pcm/sndstat.c	8 Sep 2004 07:36:29 -0000
@@ -26,6 +26,9 @@
 
 #include <dev/sound/pcm/sound.h>
 #include <dev/sound/pcm/vchan.h>
+#ifdef	USING_MUTEX
+#include <sys/sx.h>
+#endif
 
 SND_DECLARE_FILE("$FreeBSD: src/sys/dev/sound/pcm/sndstat.c,v 1.17 2004/06/16 09:46:57 phk Exp $");
 
@@ -59,7 +62,7 @@
 };
 
 #ifdef	USING_MUTEX
-static struct mtx sndstat_lock;
+static struct sx sndstat_lock;
 #endif
 static struct sbuf sndstat_sbuf;
 static struct cdev *sndstat_dev = 0;
@@ -89,12 +92,12 @@
 	error = sysctl_handle_int(oidp, &verbose, sizeof(verbose), req);
 	if (error == 0 && req->newptr != NULL) {
 		s = spltty();
-		mtx_lock(&sndstat_lock);
+		sx_xlock(&sndstat_lock);
 		if (verbose < 0 || verbose > 3)
 			error = EINVAL;
 		else
 			sndstat_verbose = verbose;
-		mtx_unlock(&sndstat_lock);
+		sx_xunlock(&sndstat_lock);
 		splx(s);
 	}
 	return error;
@@ -109,14 +112,14 @@
 	int error;
 
 	s = spltty();
-	mtx_lock(&sndstat_lock);
+	sx_xlock(&sndstat_lock);
 	if (sndstat_isopen) {
-		mtx_unlock(&sndstat_lock);
+		sx_xunlock(&sndstat_lock);
 		splx(s);
 		return EBUSY;
 	}
 	sndstat_isopen = 1;
-	mtx_unlock(&sndstat_lock);
+	sx_xunlock(&sndstat_lock);
 	splx(s);
 	if (sbuf_new(&sndstat_sbuf, NULL, 4096, 0) == NULL) {
 		error = ENXIO;
@@ -127,9 +130,9 @@
 out:
 	if (error) {
 		s = spltty();
-		mtx_lock(&sndstat_lock);
+		sx_xlock(&sndstat_lock);
 		sndstat_isopen = 0;
-		mtx_unlock(&sndstat_lock);
+		sx_xunlock(&sndstat_lock);
 		splx(s);
 	}
 	return (error);
@@ -141,16 +144,16 @@
 	intrmask_t s;
 
 	s = spltty();
-	mtx_lock(&sndstat_lock);
+	sx_xlock(&sndstat_lock);
 	if (!sndstat_isopen) {
-		mtx_unlock(&sndstat_lock);
+		sx_xunlock(&sndstat_lock);
 		splx(s);
 		return EBADF;
 	}
 	sbuf_delete(&sndstat_sbuf);
 	sndstat_isopen = 0;
 
-	mtx_unlock(&sndstat_lock);
+	sx_xunlock(&sndstat_lock);
 	splx(s);
 	return 0;
 }
@@ -162,9 +165,9 @@
 	int l, err;
 
 	s = spltty();
-	mtx_lock(&sndstat_lock);
+	sx_xlock(&sndstat_lock);
 	if (!sndstat_isopen) {
-		mtx_unlock(&sndstat_lock);
+		sx_xunlock(&sndstat_lock);
 		splx(s);
 		return EBADF;
 	}
@@ -172,7 +175,7 @@
 	err = (l > 0)? uiomove(sbuf_data(&sndstat_sbuf) + sndstat_bufptr, l, buf) : 0;
 	sndstat_bufptr += l;
 
-	mtx_unlock(&sndstat_lock);
+	sx_xunlock(&sndstat_lock);
 	splx(s);
 	return err;
 }
@@ -227,12 +230,12 @@
 	ent->handler = handler;
 
 	s = spltty();
-	mtx_lock(&sndstat_lock);
+	sx_xlock(&sndstat_lock);
 	SLIST_INSERT_HEAD(&sndstat_devlist, ent, link);
 	if (type == SS_TYPE_MODULE)
 		sndstat_files++;
 	sndstat_maxunit = (unit > sndstat_maxunit)? unit : sndstat_maxunit;
-	mtx_unlock(&sndstat_lock);
+	sx_xunlock(&sndstat_lock);
 	splx(s);
 
 	return 0;
@@ -251,18 +254,18 @@
 	struct sndstat_entry *ent;
 
 	s = spltty();
-	mtx_lock(&sndstat_lock);
+	sx_xlock(&sndstat_lock);
 	SLIST_FOREACH(ent, &sndstat_devlist, link) {
 		if (ent->dev == dev) {
 			SLIST_REMOVE(&sndstat_devlist, ent, sndstat_entry, link);
-			mtx_unlock(&sndstat_lock);
+			sx_xunlock(&sndstat_lock);
 			splx(s);
 			free(ent, M_DEVBUF);
 
 			return 0;
 		}
 	}
-	mtx_unlock(&sndstat_lock);
+	sx_xunlock(&sndstat_lock);
 	splx(s);
 
 	return ENXIO;
@@ -275,19 +278,19 @@
 	struct sndstat_entry *ent;
 
 	s = spltty();
-	mtx_lock(&sndstat_lock);
+	sx_xlock(&sndstat_lock);
 	SLIST_FOREACH(ent, &sndstat_devlist, link) {
 		if (ent->dev == NULL && ent->str == str) {
 			SLIST_REMOVE(&sndstat_devlist, ent, sndstat_entry, link);
 			sndstat_files--;
-			mtx_unlock(&sndstat_lock);
+			sx_xunlock(&sndstat_lock);
 			splx(s);
 			free(ent, M_DEVBUF);
 
 			return 0;
 		}
 	}
-	mtx_unlock(&sndstat_lock);
+	sx_xunlock(&sndstat_lock);
 	splx(s);
 
 	return ENXIO;
@@ -342,7 +345,7 @@
 static int
 sndstat_init(void)
 {
-	mtx_init(&sndstat_lock, "sndstat", NULL, MTX_DEF);
+	sx_init(&sndstat_lock, "sndstat");
 	sndstat_dev = make_dev(&sndstat_cdevsw, SND_DEV_STATUS, UID_ROOT, GID_WHEEL, 0444, "sndstat");
 
 	return (sndstat_dev != 0)? 0 : ENXIO;
@@ -354,9 +357,9 @@
 	intrmask_t s;
 
 	s = spltty();
-	mtx_lock(&sndstat_lock);
+	sx_xlock(&sndstat_lock);
 	if (sndstat_isopen) {
-		mtx_unlock(&sndstat_lock);
+		sx_xunlock(&sndstat_lock);
 		splx(s);
 		return EBUSY;
 	}
@@ -366,7 +369,7 @@
 	sndstat_dev = 0;
 
 	splx(s);
-	mtx_destroy(&sndstat_lock);
+	sx_destroy(&sndstat_lock);
 	return 0;
 }
 



More information about the freebsd-current mailing list