Fix lock assertion on async I/O mode.

psignal() must be called without any spin locks.
Thanks maxv@!
This commit is contained in:
isaki 2019-08-29 13:01:07 +00:00
parent 5dd22a92f0
commit 5b1ad8c026
2 changed files with 39 additions and 14 deletions

View File

@ -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"
@ -5729,6 +5729,36 @@ audio_track_drain(struct audio_softc *sc, audio_track_t *track)
return 0;
}
/*
* 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.
@ -5747,7 +5777,6 @@ audio_softintr_rd(void *cookie)
{
struct audio_softc *sc = cookie;
audio_file_t *f;
proc_t *p;
pid_t pid;
mutex_enter(sc->sc_lock);
@ -5767,10 +5796,7 @@ audio_softintr_rd(void *cookie)
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 @@ audio_softintr_wr(void *cookie)
struct audio_softc *sc = cookie;
audio_file_t *f;
bool found;
proc_t *p;
pid_t pid;
TRACE(4, "called");
@ -5826,14 +5851,13 @@ audio_softintr_wr(void *cookie)
*/
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);
}
}
}

View File

@ -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 @@ struct audio_softc {
/*
* 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;