Thu Aug 29 13:01:07 2019 UTC ()
Fix lock assertion on async I/O mode.
psignal() must be called without any spin locks.
Thanks maxv@!


(isaki)
diff -r1.29 -r1.30 src/sys/dev/audio/audio.c
diff -r1.4 -r1.5 src/sys/dev/audio/audiovar.h

cvs diff -r1.29 -r1.30 src/sys/dev/audio/audio.c (expand / switch to context diff)
--- src/sys/dev/audio/audio.c 2019/08/23 09:41:26 1.29
+++ src/sys/dev/audio/audio.c 2019/08/29 13:01:07 1.30
@@ -1,4 +1,4 @@
-/*	$NetBSD: audio.c,v 1.29 2019/08/23 09:41:26 maxv Exp $	*/
+/*	$NetBSD: audio.c,v 1.30 2019/08/29 13:01:07 isaki Exp $	*/
 
 /*-
  * Copyright (c) 2008 The NetBSD Foundation, Inc.
@@ -142,7 +142,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: audio.c,v 1.29 2019/08/23 09:41:26 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: audio.c,v 1.30 2019/08/29 13:01:07 isaki Exp $");
 
 #ifdef _KERNEL_OPT
 #include "audio.h"
@@ -5730,6 +5730,36 @@
 }
 
 /*
+ * Send signal to process.
+ * This is intended to be called only from audio_softintr_{rd,wr}.
+ * Must be called with sc_lock && sc_intr_lock held.
+ */
+static inline void
+audio_psignal(struct audio_softc *sc, pid_t pid, int signum)
+{
+	proc_t *p;
+
+	KASSERT(mutex_owned(sc->sc_lock));
+	KASSERT(mutex_owned(sc->sc_intr_lock));
+	KASSERT(pid != 0);
+
+	/*
+	 * psignal() must be called without spin lock held.
+	 * So leave intr_lock temporarily here.
+	 */
+	mutex_exit(sc->sc_intr_lock);
+
+	mutex_enter(proc_lock);
+	p = proc_find(pid);
+	if (p)
+		psignal(p, signum);
+	mutex_exit(proc_lock);
+
+	/* Enter intr_lock again */
+	mutex_enter(sc->sc_intr_lock);
+}
+
+/*
  * This is software interrupt handler for record.
  * It is called from recording hardware interrupt everytime.
  * It does:
@@ -5747,7 +5777,6 @@
 {
 	struct audio_softc *sc = cookie;
 	audio_file_t *f;
-	proc_t *p;
 	pid_t pid;
 
 	mutex_enter(sc->sc_lock);
@@ -5767,10 +5796,7 @@
 		pid = f->async_audio;
 		if (pid != 0) {
 			TRACEF(4, f, "sending SIGIO %d", pid);
-			mutex_enter(proc_lock);
-			if ((p = proc_find(pid)) != NULL)
-				psignal(p, SIGIO);
-			mutex_exit(proc_lock);
+			audio_psignal(sc, pid, SIGIO);
 		}
 	}
 	mutex_exit(sc->sc_intr_lock);
@@ -5799,7 +5825,6 @@
 	struct audio_softc *sc = cookie;
 	audio_file_t *f;
 	bool found;
-	proc_t *p;
 	pid_t pid;
 
 	TRACE(4, "called");
@@ -5826,14 +5851,13 @@
 		 */
 		if (track->usrbuf.used <= track->usrbuf_usedlow &&
 		    !track->is_pause) {
+			/* For selnotify */
 			found = true;
+			/* For SIGIO */
 			pid = f->async_audio;
 			if (pid != 0) {
 				TRACEF(4, f, "sending SIGIO %d", pid);
-				mutex_enter(proc_lock);
-				if ((p = proc_find(pid)) != NULL)
-					psignal(p, SIGIO);
-				mutex_exit(proc_lock);
+				audio_psignal(sc, pid, SIGIO);
 			}
 		}
 	}

cvs diff -r1.4 -r1.5 src/sys/dev/audio/audiovar.h (expand / switch to context diff)
--- src/sys/dev/audio/audiovar.h 2019/06/26 06:57:45 1.4
+++ src/sys/dev/audio/audiovar.h 2019/08/29 13:01:07 1.5
@@ -1,4 +1,4 @@
-/*	$NetBSD: audiovar.h,v 1.4 2019/06/26 06:57:45 isaki Exp $	*/
+/*	$NetBSD: audiovar.h,v 1.5 2019/08/29 13:01:07 isaki Exp $	*/
 
 /*-
  * Copyright (c) 2002 The NetBSD Foundation, Inc.
@@ -149,7 +149,8 @@
 
 	/*
 	 * List of opened descriptors.
-	 * Must be protected by sc_intr_lock.
+	 * Must be protected by sc_lock || sc_intr_lock for traversal(FOREACH).
+	 * Must be protected by sc_lock && sc_intr_lock for insertion/removal.
 	 */
 	SLIST_HEAD(, audio_file) sc_files;