sys_kevent() and kqueue_scan() consume a relatively large amount of kernel stack space, 352 and 544 bytes, respectively, on amd64. The portion of kqueue_scan() can be reduced by 256 bytes to 288 bytes by reusing sys_kevent()'s kev[] array.
This diff overlaps with the non-committed kqueue_scan() refactoring. However, there is an unsolved system hang issue with the related kqueue_scan_state patch. The change below reduces the likelihood of kernel stack exhaustion, though it is unlikely that it would help with the hang. I think the reduction of stack usage is useful in itself, however. The added asserts state that the retry branch should be taken only if no events have been collected. OK? Index: kern/kern_event.c =================================================================== RCS file: src/sys/kern/kern_event.c,v retrieving revision 1.141 diff -u -p -r1.141 kern_event.c --- kern/kern_event.c 4 Jul 2020 08:33:43 -0000 1.141 +++ kern/kern_event.c 9 Aug 2020 14:51:35 -0000 @@ -66,7 +66,7 @@ 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); + struct kevent *kev, struct proc *p, int *retval); int kqueue_read(struct file *, struct uio *, int); int kqueue_write(struct file *, struct uio *, int); @@ -638,7 +638,7 @@ sys_kevent(struct proc *p, void *v, regi KQREF(kq); FRELE(fp, p); error = kqueue_scan(kq, SCARG(uap, nevents), SCARG(uap, eventlist), - tsp, p, &n); + tsp, kev, p, &n); KQRELE(kq); *retval = n; return (error); @@ -896,12 +896,14 @@ kqueue_sleep(struct kqueue *kq, struct t int kqueue_scan(struct kqueue *kq, int maxevents, struct kevent *ulistp, - struct timespec *tsp, struct proc *p, int *retval) + struct timespec *tsp, struct kevent *kev, struct proc *p, int *retval) { struct kevent *kevp; struct knote mend, mstart, *kn; - int s, count, nkev = 0, error = 0; - struct kevent kev[KQ_NEVENTS]; + int s, count, nkev, error = 0; + + nkev = 0; + kevp = kev; count = maxevents; if (count == 0) @@ -911,12 +913,14 @@ kqueue_scan(struct kqueue *kq, int maxev memset(&mend, 0, sizeof(mend)); retry: + KASSERT(count == maxevents); + KASSERT(nkev == 0); + if (kq->kq_state & KQ_DYING) { error = EBADF; goto done; } - kevp = &kev[0]; s = splhigh(); if (kq->kq_count == 0) { if (tsp != NULL && !timespecisset(tsp)) { @@ -1019,7 +1023,7 @@ retry: sizeof(struct kevent) * nkev); ulistp += nkev; nkev = 0; - kevp = &kev[0]; + kevp = kev; s = splhigh(); if (error) break;