diff --git a/sys/dev/audio/audio.c b/sys/dev/audio/audio.c index 3e8577fcef75..eeb839bce274 100644 --- a/sys/dev/audio/audio.c +++ b/sys/dev/audio/audio.c @@ -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 -__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); } } } diff --git a/sys/dev/audio/audiovar.h b/sys/dev/audio/audiovar.h index 97cef92b12f3..7a9b7e58ce1d 100644 --- a/sys/dev/audio/audiovar.h +++ b/sys/dev/audio/audiovar.h @@ -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;