This is the first step to allow kqueue_scan() to be executed in
parallel. I'm currently focusing on data structure ownership with
regard to sleep. I don't plan to get rid of the KERNEL_LOCK() for
the moment. I don't think it makes sense unless we can unlock the
kevent(2) syscall.
The diff below move 'struct kevent' storage to the stack. This is
the simplest way to make it mp-safe.
This has been tested as part of a larger diff by many.
Ok?
Index: kern/kern_event.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_event.c,v
retrieving revision 1.79
diff -u -p -r1.79 kern_event.c
--- kern/kern_event.c 31 May 2017 14:52:05 -0000 1.79
+++ kern/kern_event.c 9 Oct 2017 09:02:48 -0000
@@ -476,6 +476,7 @@ sys_kevent(struct proc *p, void *v, regi
struct file *fp;
struct timespec ts;
int i, n, nerrors, error;
+ struct kevent kev[KQ_NEVENTS];
if ((fp = fd_getfile(fdp, SCARG(uap, fd))) == NULL ||
(fp->f_type != DTYPE_KQUEUE))
@@ -500,16 +501,16 @@ sys_kevent(struct proc *p, void *v, regi
while (SCARG(uap, nchanges) > 0) {
n = SCARG(uap, nchanges) > KQ_NEVENTS ?
KQ_NEVENTS : SCARG(uap, nchanges);
- error = copyin(SCARG(uap, changelist), kq->kq_kev,
+ error = copyin(SCARG(uap, changelist), kev,
n * sizeof(struct kevent));
if (error)
goto done;
#ifdef KTRACE
if (KTRPOINT(p, KTR_STRUCT))
- ktrevent(p, kq->kq_kev, n);
+ ktrevent(p, kev, n);
#endif
for (i = 0; i < n; i++) {
- kevp = &kq->kq_kev[i];
+ kevp = &kev[i];
kevp->flags &= ~EV_SYSFLAGS;
error = kqueue_register(kq, kevp, p);
if (error || (kevp->flags & EV_RECEIPT)) {
@@ -691,6 +692,7 @@ kqueue_scan(struct kqueue *kq, int maxev
struct timeval atv, rtv, ttv;
struct knote *kn, marker;
int s, count, timeout, nkev = 0, error = 0;
+ struct kevent kev[KQ_NEVENTS];
count = maxevents;
if (count == 0)
@@ -737,7 +739,7 @@ start:
goto done;
}
- kevp = kq->kq_kev;
+ kevp = &kev[0];
s = splhigh();
if (kq->kq_count == 0) {
if (timeout < 0) {
@@ -805,13 +807,13 @@ start:
splx(s);
#ifdef KTRACE
if (KTRPOINT(p, KTR_STRUCT))
- ktrevent(p, kq->kq_kev, nkev);
+ ktrevent(p, kev, nkev);
#endif
- error = copyout(kq->kq_kev, ulistp,
+ error = copyout(kev, ulistp,
sizeof(struct kevent) * nkev);
ulistp += nkev;
nkev = 0;
- kevp = kq->kq_kev;
+ kevp = &kev[0];
s = splhigh();
if (error)
break;
@@ -823,9 +825,9 @@ done:
if (nkev != 0) {
#ifdef KTRACE
if (KTRPOINT(p, KTR_STRUCT))
- ktrevent(p, kq->kq_kev, nkev);
+ ktrevent(p, kev, nkev);
#endif
- error = copyout(kq->kq_kev, ulistp,
+ error = copyout(kev, ulistp,
sizeof(struct kevent) * nkev);
}
*retval = maxevents - count;
Index: sys/eventvar.h
===================================================================
RCS file: /cvs/src/sys/sys/eventvar.h,v
retrieving revision 1.3
diff -u -p -r1.3 eventvar.h
--- sys/eventvar.h 25 Mar 2012 20:33:52 -0000 1.3
+++ sys/eventvar.h 9 Oct 2017 09:02:48 -0000
@@ -44,7 +44,6 @@ struct kqueue {
#define KQ_SEL 0x01
#define KQ_SLEEP 0x02
#define KQ_DYING 0x04
- struct kevent kq_kev[KQ_NEVENTS];
};
#endif /* !_SYS_EVENTVAR_H_ */