ping

> On 27 Sep 2023, at 23:19, Vitaliy Makkoveev <m...@openbsd.org> wrote:
> 
> Introduce `sc_mtx` mutex(9) and use it for `sc_frames_ready' and
> `sc_rklist' knotes list protection.
> 
> Index: sys/dev/video.c
> ===================================================================
> RCS file: /cvs/src/sys/dev/video.c,v
> retrieving revision 1.57
> diff -u -p -r1.57 video.c
> --- sys/dev/video.c   2 Jul 2022 08:50:41 -0000       1.57
> +++ sys/dev/video.c   27 Sep 2023 20:15:34 -0000
> @@ -20,12 +20,14 @@
> #include <sys/param.h>
> #include <sys/systm.h>
> #include <sys/errno.h>
> +#include <sys/event.h>
> #include <sys/ioctl.h>
> #include <sys/fcntl.h>
> #include <sys/device.h>
> #include <sys/vnode.h>
> #include <sys/kernel.h>
> #include <sys/malloc.h>
> +#include <sys/mutex.h>
> #include <sys/conf.h>
> #include <sys/proc.h>
> #include <sys/videoio.h>
> @@ -34,6 +36,11 @@
> 
> #include <uvm/uvm_extern.h>
> 
> +/*
> + * Locks used to protect struct members and global data
> + *   m       sc_mtx
> + */
> +
> #ifdef VIDEO_DEBUG
> int video_debug = 1;
> #define DPRINTF(l, x...) do { if ((l) <= video_debug) printf(x); } while (0)
> @@ -50,6 +57,8 @@ struct video_softc {
>       struct process          *sc_owner;      /* owner process */
>       uint8_t                  sc_open;       /* device opened */
> 
> +     struct mutex             sc_mtx;
> +
>       int                      sc_fsize;
>       uint8_t                 *sc_fbuffer;
>       caddr_t                  sc_fbuffer_mmap;
> @@ -58,9 +67,9 @@ struct video_softc {
> #define               VIDMODE_NONE    0
> #define               VIDMODE_MMAP    1
> #define               VIDMODE_READ    2
> -     int                      sc_frames_ready;
> +     int                      sc_frames_ready;       /* [m] */
> 
> -     struct selinfo           sc_rsel;       /* read selector */
> +     struct klist             sc_rklist;             /* [m] read selector */
> };
> 
> int   videoprobe(struct device *, void *, void *);
> @@ -105,6 +114,8 @@ videoattach(struct device *parent, struc
>       sc->sc_dev = parent;
>       sc->sc_fbufferlen = 0;
>       sc->sc_owner = NULL;
> +     mtx_init(&sc->sc_mtx, IPL_MPFLOOR);
> +     klist_init_mutex(&sc->sc_rklist, &sc->sc_mtx);
> 
>       if (sc->hw_if->get_bufsize)
>               sc->sc_fbufferlen = (sc->hw_if->get_bufsize)(sc->hw_hdl);
> @@ -205,21 +216,28 @@ videoread(dev_t dev, struct uio *uio, in
> 
>       DPRINTF(1, "resid=%zu\n", uio->uio_resid);
> 
> +     mtx_enter(&sc->sc_mtx);
> +
>       if (sc->sc_frames_ready < 1) {
>               /* block userland read until a frame is ready */
> -             error = tsleep_nsec(sc, PWAIT | PCATCH, "vid_rd", INFSLP);
> +             error = msleep_nsec(sc, &sc->sc_mtx, PWAIT | PCATCH,
> +                 "vid_rd", INFSLP);
>               if (sc->sc_dying)
>                       error = EIO;
> -             if (error)
> +             if (error) {
> +                     mtx_leave(&sc->sc_mtx);
>                       return (error);
> +             }
>       }
> +     sc->sc_frames_ready--;
> +
> +     mtx_leave(&sc->sc_mtx);
> 
>       /* move no more than 1 frame to userland, as per specification */
>       size = ulmin(uio->uio_resid, sc->sc_fsize);
>       if (!video_record_enable)
>               bzero(sc->sc_fbuffer, size);
>       error = uiomove(sc->sc_fbuffer, size, uio);
> -     sc->sc_frames_ready--;
>       if (error)
>               return (error);
> 
> @@ -356,7 +374,9 @@ videoioctl(dev_t dev, u_long cmd, caddr_
>                   (struct v4l2_buffer *)data);
>               if (!video_record_enable)
>                       bzero(sc->sc_fbuffer_mmap + vb->m.offset, vb->length);
> +             mtx_enter(&sc->sc_mtx);
>               sc->sc_frames_ready--;
> +             mtx_leave(&sc->sc_mtx);
>               break;
>       case VIDIOC_STREAMON:
>               if (sc->hw_if->streamon)
> @@ -429,11 +449,8 @@ void
> filt_videodetach(struct knote *kn)
> {
>       struct video_softc *sc = kn->kn_hook;
> -     int s;
> 
> -     s = splhigh();
> -     klist_remove_locked(&sc->sc_rsel.si_note, kn);
> -     splx(s);
> +     klist_remove(&sc->sc_rklist, kn);
> }
> 
> int
> @@ -447,11 +464,39 @@ filt_videoread(struct knote *kn, long hi
>       return (0);
> }
> 
> +int
> +filt_videomodify(struct kevent *kev, struct knote *kn)
> +{
> +     struct video_softc *sc = kn->kn_hook;
> +     int active;
> +
> +     mtx_enter(&sc->sc_mtx);
> +     active = knote_modify(kev, kn); 
> +     mtx_leave(&sc->sc_mtx);
> +
> +     return (active);
> +}
> +
> +int
> +filt_videoprocess(struct knote *kn, struct kevent *kev)
> +{
> +     struct video_softc *sc = kn->kn_hook;
> +     int active;
> +
> +     mtx_enter(&sc->sc_mtx);
> +     active = knote_process(kn, kev);
> +     mtx_leave(&sc->sc_mtx);
> +
> +     return (active);
> +}
> +
> const struct filterops video_filtops = {
> -     .f_flags        = FILTEROP_ISFD,
> +     .f_flags        = FILTEROP_ISFD | FILTEROP_MPSAFE,
>       .f_attach       = NULL,
>       .f_detach       = filt_videodetach,
>       .f_event        = filt_videoread,
> +     .f_modify       = filt_videomodify,
> +     .f_process      = filt_videoprocess,
> };
> 
> int
> @@ -459,7 +504,7 @@ videokqfilter(dev_t dev, struct knote *k
> {
>       int unit = VIDEOUNIT(dev);
>       struct video_softc *sc;
> -     int s, error;
> +     int error;
> 
>       KERNEL_ASSERT_LOCKED();
> 
> @@ -493,9 +538,7 @@ videokqfilter(dev_t dev, struct knote *k
>               sc->sc_vidmode = VIDMODE_READ;
>       }
> 
> -     s = splhigh();
> -     klist_insert_locked(&sc->sc_rsel.si_note, kn);
> -     splx(s);
> +     klist_insert(&sc->sc_rklist, kn);
> 
>       return (0);
> }
> @@ -528,13 +571,15 @@ video_intr(void *addr)
>       struct video_softc *sc = (struct video_softc *)addr;
> 
>       DPRINTF(3, "video_intr sc=%p\n", sc);
> +     mtx_enter(&sc->sc_mtx);
>       if (sc->sc_vidmode != VIDMODE_NONE)
>               sc->sc_frames_ready++;
>       else
>               printf("%s: interrupt but no streams!\n", __func__);
>       if (sc->sc_vidmode == VIDMODE_READ)
>               wakeup(sc);
> -     selwakeup(&sc->sc_rsel);
> +     knote_locked(&sc->sc_rklist, 0);
> +     mtx_leave(&sc->sc_mtx);
> }
> 
> int
> @@ -548,7 +593,9 @@ video_stop(struct video_softc *sc)
>               error = sc->hw_if->close(sc->hw_hdl);
> 
>       sc->sc_vidmode = VIDMODE_NONE;
> +     mtx_enter(&sc->sc_mtx);
>       sc->sc_frames_ready = 0;
> +     mtx_leave(&sc->sc_mtx);
>       sc->sc_owner = NULL;
> 
>       return (error);
> @@ -582,7 +629,7 @@ int
> videodetach(struct device *self, int flags)
> {
>       struct video_softc *sc = (struct video_softc *)self;
> -     int s, maj, mn;
> +     int maj, mn;
> 
>       /* locate the major number */
>       for (maj = 0; maj < nchrdev; maj++)
> @@ -593,9 +640,8 @@ videodetach(struct device *self, int fla
>       mn = self->dv_unit;
>       vdevgone(maj, mn, mn, VCHR);
> 
> -     s = splhigh();
> -     klist_invalidate(&sc->sc_rsel.si_note);
> -     splx(s);
> +     klist_invalidate(&sc->sc_rklist);
> +     klist_free(&sc->sc_rklist);
> 
>       free(sc->sc_fbuffer, M_DEVBUF, sc->sc_fbufferlen);
> 
> 

Reply via email to