Diff below changes the order of operations in kqueue_register() to get
rid of an unnecessary pool_get().  When an event is already present on
the list try to acquire it first.  Note that knote_acquire() may sleep
in which case the list might have changed so the lookup has to always
begin from the start.

This will help with lazy removal of knote in poll/select.  In this
scenario EV_ADD is generally always done with an knote already on the
list.

ok?

Index: kern/kern_event.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_event.c,v
retrieving revision 1.142
diff -u -p -r1.142 kern_event.c
--- kern/kern_event.c   12 Aug 2020 13:49:24 -0000      1.142
+++ kern/kern_event.c   18 Aug 2020 08:58:27 -0000
@@ -696,7 +696,7 @@ kqueue_register(struct kqueue *kq, struc
        struct filedesc *fdp = kq->kq_fdp;
        const struct filterops *fops = NULL;
        struct file *fp = NULL;
-       struct knote *kn = NULL, *newkn = NULL;
+       struct knote *kn, *newkn = NULL;
        struct knlist *list = NULL;
        int s, error = 0;
 
@@ -721,22 +721,12 @@ kqueue_register(struct kqueue *kq, struc
                        return (EBADF);
        }
 
-       if (kev->flags & EV_ADD)
-               newkn = pool_get(&knote_pool, PR_WAITOK | PR_ZERO);
-
 again:
+       kn = NULL;
        if (fops->f_flags & FILTEROP_ISFD) {
-               if ((fp = fd_getfile(fdp, kev->ident)) == NULL) {
-                       error = EBADF;
-                       goto done;
-               }
-               if (kev->flags & EV_ADD)
-                       kqueue_expand_list(kq, kev->ident);
                if (kev->ident < kq->kq_knlistsize)
                        list = &kq->kq_knlist[kev->ident];
        } else {
-               if (kev->flags & EV_ADD)
-                       kqueue_expand_hash(kq);
                if (kq->kq_knhashmask != 0) {
                        list = &kq->kq_knhash[
                            KN_HASH((u_long)kev->ident, kq->kq_knhashmask)];
@@ -749,10 +739,6 @@ again:
                                s = splhigh();
                                if (!knote_acquire(kn)) {
                                        splx(s);
-                                       if (fp != NULL) {
-                                               FRELE(fp, p);
-                                               fp = NULL;
-                                       }
                                        goto again;
                                }
                                splx(s);
@@ -760,6 +746,21 @@ again:
                        }
                }
        }
+
+       if (kev->flags & EV_ADD && kn == NULL) {
+               newkn = pool_get(&knote_pool, PR_WAITOK | PR_ZERO);
+               if (fops->f_flags & FILTEROP_ISFD) {
+                       if ((fp = fd_getfile(fdp, kev->ident)) == NULL) {
+                               error = EBADF;
+                               goto done;
+                       }
+                       kqueue_expand_list(kq, kev->ident);
+               } else {
+                       kqueue_expand_hash(kq);
+               }
+
+       }
+
        KASSERT(kn == NULL || (kn->kn_status & KN_PROCESSING) != 0);
 
        if (kn == NULL && ((kev->flags & EV_ADD) == 0)) {

Reply via email to