Don't hold the audio mutex when calling uiomove(), as uiomove()
authorratchov <ratchov@openbsd.org>
Tue, 12 May 2015 18:05:43 +0000 (18:05 +0000)
committerratchov <ratchov@openbsd.org>
Tue, 12 May 2015 18:05:43 +0000 (18:05 +0000)
may sleep in case of a page fault

sys/dev/midi.c

index d2f0046..277682a 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: midi.c,v 1.34 2015/03/14 03:38:46 jsg Exp $   */
+/*     $OpenBSD: midi.c,v 1.35 2015/05/12 18:05:43 ratchov Exp $       */
 
 /*
  * Copyright (c) 2003, 2004 Alexandre Ratchov
@@ -141,11 +141,11 @@ midiread(dev_t dev, struct uio *uio, int ioflag)
                        count = mb->used;
                if (count > uio->uio_resid)
                        count = uio->uio_resid;
+               mtx_leave(&audio_lock);
                error = uiomovei(mb->data + mb->start, count, uio);
-               if (error) {
-                       mtx_leave(&audio_lock);
+               if (error)
                        return error;
-               }
+               mtx_enter(&audio_lock);
                MIDIBUF_REMOVE(mb, count);
        }
        mtx_leave(&audio_lock);
@@ -246,12 +246,13 @@ midiwrite(dev_t dev, struct uio *uio, int ioflag)
         * in the buffer to store at least one byte. If not then dont
         * start the write process.
         */
-
-       if ((ioflag & IO_NDELAY) && MIDIBUF_ISFULL(mb) && (uio->uio_resid > 0))
+       mtx_enter(&audio_lock);
+       if ((ioflag & IO_NDELAY) && MIDIBUF_ISFULL(mb) && (uio->uio_resid > 0)) {
+               mtx_leave(&audio_lock);
                return EWOULDBLOCK;
+       }
 
        while (uio->uio_resid > 0) {
-               mtx_enter(&audio_lock);
                while (MIDIBUF_ISFULL(mb)) {
                        if (ioflag & IO_NDELAY) {
                                /*
@@ -279,15 +280,15 @@ midiwrite(dev_t dev, struct uio *uio, int ioflag)
                        count = MIDIBUF_AVAIL(mb);
                if (count > uio->uio_resid)
                        count = uio->uio_resid;
+               mtx_leave(&audio_lock);
                error = uiomovei(mb->data + MIDIBUF_END(mb), count, uio);
-               if (error) {
-                       mtx_leave(&audio_lock);
+               if (error)
                        return error;
-               }
+               mtx_enter(&audio_lock);
                mb->used += count;
                midi_out_start(sc);
-               mtx_leave(&audio_lock);
        }
+       mtx_leave(&audio_lock);
        return 0;
 }