> Date: Wed, 1 Apr 2020 10:28:33 +0200
> From: Martin Pieuchot <m...@openbsd.org>
> 
> I've started to refactor some of the kqueue() subsystem to make progress
> on moving selwakeup() out of the KERNEL_LOCK().  Diff below is a small
> part of this work.  It extracts the sleeping logic outside of the main
> loop.
> 
> I find this easier to read and it allows me to make my huge diff more
> easily reviewable.  Do we see value in this alone or do we prefer to
> wait for a big diff?
> 
> Any comment or ok?

Doing the validity test earlier makes sense.  The behaviour changes
slightly if nevents == 0 since now the validity does get checked where
it would previously succeed.  But that is probably ok.

ok kettenis@

> Index: kern/kern_event.c
> ===================================================================
> RCS file: /cvs/src/sys/kern/kern_event.c,v
> retrieving revision 1.128
> diff -u -p -r1.128 kern_event.c
> --- kern/kern_event.c 20 Mar 2020 04:14:50 -0000      1.128
> +++ kern/kern_event.c 1 Apr 2020 08:16:52 -0000
> @@ -61,6 +61,7 @@ void        kqueue_init(void);
>  void KQREF(struct kqueue *);
>  void KQRELE(struct kqueue *);
>  
> +int  kqueue_sleep(struct kqueue *, struct timespec *);
>  int  kqueue_scan(struct kqueue *kq, int maxevents,
>                   struct kevent *ulistp, struct timespec *timeout,
>                   struct proc *p, int *retval);
> @@ -556,6 +557,10 @@ sys_kevent(struct proc *p, void *v, regi
>               error = copyin(SCARG(uap, timeout), &ts, sizeof(ts));
>               if (error)
>                       goto done;
> +             if (ts.tv_sec < 0 || !timespecisvalid(&ts)) {
> +                     error = EINVAL;
> +                     goto done;
> +             }
>  #ifdef KTRACE
>               if (KTRPOINT(p, KTR_STRUCT))
>                       ktrreltimespec(p, &ts);
> @@ -838,13 +843,37 @@ done:
>  }
>  
>  int
> +kqueue_sleep(struct kqueue *kq, struct timespec *tsp)
> +{
> +     struct timespec elapsed, start, stop;
> +     uint64_t nsecs;
> +     int error;
> +
> +     splassert(IPL_HIGH);
> +
> +     if (tsp != NULL) {
> +             getnanouptime(&start);
> +             nsecs = MIN(TIMESPEC_TO_NSEC(tsp), MAXTSLP);
> +     } else
> +             nsecs = INFSLP;
> +     error = tsleep_nsec(kq, PSOCK | PCATCH, "kqread", nsecs);
> +     if (tsp != NULL) {
> +             getnanouptime(&stop);
> +             timespecsub(&stop, &start, &elapsed);
> +             timespecsub(tsp, &elapsed, tsp);
> +             if (tsp->tv_sec < 0)
> +                     timespecclear(tsp);
> +     }
> +
> +     return (error);
> +}
> +
> +int
>  kqueue_scan(struct kqueue *kq, int maxevents, struct kevent *ulistp,
>      struct timespec *tsp, struct proc *p, int *retval)
>  {
>       struct kevent *kevp;
> -     struct timespec elapsed, start, stop;
>       struct knote mend, mstart, *kn;
> -     uint64_t nsecs;
>       int s, count, nkev = 0, error = 0;
>       struct kevent kev[KQ_NEVENTS];
>  
> @@ -852,11 +881,6 @@ kqueue_scan(struct kqueue *kq, int maxev
>       if (count == 0)
>               goto done;
>  
> -     if (tsp != NULL && (tsp->tv_sec < 0 || !timespecisvalid(tsp))) {
> -             error = EINVAL;
> -             goto done;
> -     }
> -
>       memset(&mstart, 0, sizeof(mstart));
>       memset(&mend, 0, sizeof(mend));
>  
> @@ -875,19 +899,7 @@ retry:
>                       goto done;
>               }
>               kq->kq_state |= KQ_SLEEP;
> -             if (tsp != NULL) {
> -                     getnanouptime(&start);
> -                     nsecs = MIN(TIMESPEC_TO_NSEC(tsp), MAXTSLP);
> -             } else
> -                     nsecs = INFSLP;
> -             error = tsleep_nsec(kq, PSOCK | PCATCH, "kqread", nsecs);
> -             if (tsp != NULL) {
> -                     getnanouptime(&stop);
> -                     timespecsub(&stop, &start, &elapsed);
> -                     timespecsub(tsp, &elapsed, tsp);
> -                     if (tsp->tv_sec < 0)
> -                             timespecclear(tsp);
> -             }
> +             error = kqueue_sleep(kq, tsp);
>               splx(s);
>               if (error == 0 || error == EWOULDBLOCK)
>                       goto retry;
> 
> 

Reply via email to