Don't grab audio_lock in filt_midi{read,write} if NOTE_SUBMIT is set.
authorratchov <ratchov@openbsd.org>
Fri, 29 Oct 2021 13:24:50 +0000 (13:24 +0000)
committerratchov <ratchov@openbsd.org>
Fri, 29 Oct 2021 13:24:50 +0000 (13:24 +0000)
Fixes panics caused by attempts to grab audio_lock twice in the
interrupt code path: once in the low-lever interrupt handler and once
in selwakeup()

This is exactly how audio(4) handles this problem.

ok mpi

sys/dev/midi.c

index d27c349..4332eb5 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: midi.c,v 1.48 2020/12/25 12:59:52 visa Exp $  */
+/*     $OpenBSD: midi.c,v 1.49 2021/10/29 13:24:50 ratchov Exp $       */
 
 /*
  * Copyright (c) 2003, 2004 Alexandre Ratchov
@@ -386,9 +386,11 @@ filt_midiread(struct knote *kn, long hint)
        struct midi_softc *sc = (struct midi_softc *)kn->kn_hook;
        int retval;
 
-       mtx_enter(&audio_lock);
+       if ((hint & NOTE_SUBMIT) == 0)
+               mtx_enter(&audio_lock);
        retval = !MIDIBUF_ISEMPTY(&sc->inbuf);
-       mtx_leave(&audio_lock);
+       if ((hint & NOTE_SUBMIT) == 0)
+               mtx_leave(&audio_lock);
 
        return (retval);
 }
@@ -409,9 +411,11 @@ filt_midiwrite(struct knote *kn, long hint)
        struct midi_softc *sc = (struct midi_softc *)kn->kn_hook;
        int                retval;
 
-       mtx_enter(&audio_lock);
+       if ((hint & NOTE_SUBMIT) == 0)
+               mtx_enter(&audio_lock);
        retval = !MIDIBUF_ISFULL(&sc->outbuf);
-       mtx_leave(&audio_lock);
+       if ((hint & NOTE_SUBMIT) == 0)
+               mtx_leave(&audio_lock);
 
        return (retval);
 }