On Mon, Sep 18, 2023 at 02:12:21PM +0300, Vitaliy Makkoveev wrote:
> On Mon, Sep 18, 2023 at 02:03:08PM +0300, Vitaliy Makkoveev wrote:
> > Also use this mutex to protect `evqueue_head', `evqueue_tail' and
> > `evqueue_count'.
> > 
> 
> Sorry, the right diff:

OK bluhm@

> Index: sys/dev/hotplug.c
> ===================================================================
> RCS file: /cvs/src/sys/dev/hotplug.c,v
> retrieving revision 1.23
> diff -u -p -r1.23 hotplug.c
> --- sys/dev/hotplug.c 8 Sep 2023 20:00:27 -0000       1.23
> +++ sys/dev/hotplug.c 18 Sep 2023 11:09:12 -0000
> @@ -22,27 +22,39 @@
>  #include <sys/param.h>
>  #include <sys/systm.h>
>  #include <sys/device.h>
> +#include <sys/event.h>
>  #include <sys/fcntl.h>
>  #include <sys/hotplug.h>
>  #include <sys/ioctl.h>
> -#include <sys/selinfo.h>
> +#include <sys/mutex.h>
>  #include <sys/vnode.h>
>  
>  #define HOTPLUG_MAXEVENTS    64
>  
> +/*
> + * Locks used to protect struct members and global data
> + *    M      hotplug_mtx
> + */
> +
> +static struct mutex hotplug_mtx = MUTEX_INITIALIZER(IPL_MPFLOOR);
> +
>  static int opened;
>  static struct hotplug_event evqueue[HOTPLUG_MAXEVENTS];
> -static int evqueue_head, evqueue_tail, evqueue_count;
> -static struct selinfo hotplug_sel;
> +static int evqueue_head, evqueue_tail, evqueue_count;        /* [M] */
> +static struct klist hotplug_klist;                   /* [M] */
>  
>  void filt_hotplugrdetach(struct knote *);
>  int  filt_hotplugread(struct knote *, long);
> +int  filt_hotplugmodify(struct kevent *, struct knote *);
> +int  filt_hotplugprocess(struct knote *, struct kevent *);
>  
>  const struct filterops hotplugread_filtops = {
> -     .f_flags        = FILTEROP_ISFD,
> +     .f_flags        = FILTEROP_ISFD | FILTEROP_MPSAFE,
>       .f_attach       = NULL,
>       .f_detach       = filt_hotplugrdetach,
>       .f_event        = filt_hotplugread,
> +     .f_modify       = filt_hotplugmodify,
> +     .f_process      = filt_hotplugprocess,
>  };
>  
>  #define EVQUEUE_NEXT(p) (p == HOTPLUG_MAXEVENTS - 1 ? 0 : p + 1)
> @@ -60,6 +72,8 @@ hotplugattach(int count)
>       evqueue_head = 0;
>       evqueue_tail = 0;
>       evqueue_count = 0;
> +
> +     klist_init_mutex(&hotplug_klist, &hotplug_mtx);
>  }
>  
>  void
> @@ -87,7 +101,9 @@ hotplug_device_detach(enum devclass clas
>  int
>  hotplug_put_event(struct hotplug_event *he)
>  {
> +     mtx_enter(&hotplug_mtx);
>       if (evqueue_count == HOTPLUG_MAXEVENTS && opened) {
> +             mtx_leave(&hotplug_mtx);
>               printf("hotplug: event lost, queue full\n");
>               return (1);
>       }
> @@ -98,24 +114,21 @@ hotplug_put_event(struct hotplug_event *
>               evqueue_tail = EVQUEUE_NEXT(evqueue_tail);
>       else 
>               evqueue_count++;
> +     knote_locked(&hotplug_klist, 0);
>       wakeup(&evqueue);
> -     selwakeup(&hotplug_sel);
> +     mtx_leave(&hotplug_mtx);
>       return (0);
>  }
>  
>  int
>  hotplug_get_event(struct hotplug_event *he)
>  {
> -     int s;
> -
>       if (evqueue_count == 0)
>               return (1);
>  
> -     s = splbio();
>       *he = evqueue[evqueue_tail];
>       evqueue_tail = EVQUEUE_NEXT(evqueue_tail);
>       evqueue_count--;
> -     splx(s);
>       return (0);
>  }
>  
> @@ -137,8 +150,11 @@ hotplugclose(dev_t dev, int flag, int mo
>  {
>       struct hotplug_event he;
>  
> +     mtx_enter(&hotplug_mtx);
>       while (hotplug_get_event(&he) == 0)
>               continue;
> +     mtx_leave(&hotplug_mtx);
> +     klist_invalidate(&hotplug_klist);
>       opened = 0;
>       return (0);
>  }
> @@ -152,16 +168,23 @@ hotplugread(dev_t dev, struct uio *uio, 
>       if (uio->uio_resid != sizeof(he))
>               return (EINVAL);
>  
> -again:
> -     if (hotplug_get_event(&he) == 0)
> -             return (uiomove(&he, sizeof(he), uio));
> -     if (flags & IO_NDELAY)
> -             return (EAGAIN);
> -
> -     error = tsleep_nsec(&evqueue, PRIBIO | PCATCH, "htplev", INFSLP);
> -     if (error)
> -             return (error);
> -     goto again;
> +     mtx_enter(&hotplug_mtx);
> +     while (hotplug_get_event(&he)) {
> +             if (flags & IO_NDELAY) {
> +                     mtx_leave(&hotplug_mtx);
> +                     return (EAGAIN);
> +             }
> +     
> +             error = msleep_nsec(&evqueue, &hotplug_mtx, PRIBIO | PCATCH,
> +                 "htplev", INFSLP);
> +             if (error) {
> +                     mtx_leave(&hotplug_mtx);
> +                     return (error);
> +             }
> +     }
> +     mtx_leave(&hotplug_mtx);
> +
> +     return (uiomove(&he, sizeof(he), uio));
>  }
>  
>  int
> @@ -183,32 +206,22 @@ hotplugioctl(dev_t dev, u_long cmd, cadd
>  int
>  hotplugkqfilter(dev_t dev, struct knote *kn)
>  {
> -     struct klist *klist;
> -     int s;
> -
>       switch (kn->kn_filter) {
>       case EVFILT_READ:
> -             klist = &hotplug_sel.si_note;
>               kn->kn_fop = &hotplugread_filtops;
>               break;
>       default:
>               return (EINVAL);
>       }
>  
> -     s = splbio();
> -     klist_insert_locked(klist, kn);
> -     splx(s);
> +     klist_insert(&hotplug_klist, kn);
>       return (0);
>  }
>  
>  void
>  filt_hotplugrdetach(struct knote *kn)
>  {
> -     int s;
> -
> -     s = splbio();
> -     klist_remove_locked(&hotplug_sel.si_note, kn);
> -     splx(s);
> +     klist_remove(&hotplug_klist, kn);
>  }
>  
>  int
> @@ -217,4 +230,28 @@ filt_hotplugread(struct knote *kn, long 
>       kn->kn_data = evqueue_count;
>  
>       return (evqueue_count > 0);
> +}
> +
> +int
> +filt_hotplugmodify(struct kevent *kev, struct knote *kn)
> +{
> +     int active;
> +
> +     mtx_enter(&hotplug_mtx);
> +     active = knote_modify(kev, kn);
> +     mtx_leave(&hotplug_mtx);
> +
> +     return (active);
> +}
> +
> +int
> +filt_hotplugprocess(struct knote *kn, struct kevent *kev)
> +{
> +     int active;
> +
> +     mtx_enter(&hotplug_mtx);
> +     active = knote_process(kn, kev);
> +     mtx_leave(&hotplug_mtx);
> +
> +     return (active);
>  }

Reply via email to