Diff below adds a per-thread kqueue that will be initialized during the
first select(2) or poll(2) syscall and freed upon exit.
Along with this queue a per-thread serial number is used to check the
integrity of events enqueued during a given syscall. This could also
later be used to perform lazy removal of events.
Ok?
Index: kern/kern_event.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_event.c,v
retrieving revision 1.146
diff -u -p -r1.146 kern_event.c
--- kern/kern_event.c 7 Dec 2020 11:15:50 -0000 1.146
+++ kern/kern_event.c 7 Dec 2020 17:00:13 -0000
@@ -57,6 +57,7 @@
#include <sys/timeout.h>
#include <sys/wait.h>
+struct kqueue *kqueue_alloc(struct filedesc *);
void kqueue_terminate(struct proc *p, struct kqueue *);
void kqueue_free(struct kqueue *);
void kqueue_init(void);
@@ -504,6 +505,31 @@ const struct filterops dead_filtops = {
.f_event = filt_dead,
};
+void
+kqpoll_init(void)
+{
+ struct proc *p = curproc;
+
+ if (p->p_kq != NULL)
+ return;
+
+ p->p_kq = kqueue_alloc(p->p_fd);
+ p->p_kq_serial = arc4random();
+}
+
+void
+kqpoll_exit(void)
+{
+ struct proc *p = curproc;
+
+ if (p->p_kq == NULL)
+ return;
+
+ kqueue_terminate(p, p->p_kq);
+ kqueue_free(p->p_kq);
+ p->p_kq = NULL;
+}
+
struct kqueue *
kqueue_alloc(struct filedesc *fdp)
{
@@ -1144,7 +1170,7 @@ kqueue_stat(struct file *fp, struct stat
}
void
-kqueue_terminate(struct proc *p, struct kqueue *kq)
+kqueue_purge(struct proc *p, struct kqueue *kq)
{
int i;
@@ -1156,6 +1182,12 @@ kqueue_terminate(struct proc *p, struct
for (i = 0; i < kq->kq_knhashmask + 1; i++)
knote_remove(p, &kq->kq_knhash[i]);
}
+}
+
+void
+kqueue_terminate(struct proc *p, struct kqueue *kq)
+{
+ kqueue_purge(p, kq);
kq->kq_state |= KQ_DYING;
kqueue_wakeup(kq);
Index: kern/kern_exit.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_exit.c,v
retrieving revision 1.191
diff -u -p -r1.191 kern_exit.c
--- kern/kern_exit.c 16 Nov 2020 18:37:06 -0000 1.191
+++ kern/kern_exit.c 7 Dec 2020 17:03:50 -0000
@@ -184,6 +184,8 @@ exit1(struct proc *p, int xexit, int xsi
if ((p->p_flag & P_THREAD) == 0)
pr->ps_siglist = 0;
+ kqpoll_exit();
+
#if NKCOV > 0
kcov_exit(p);
#endif
Index: sys/event.h
===================================================================
RCS file: /cvs/src/sys/sys/event.h,v
retrieving revision 1.48
diff -u -p -r1.48 event.h
--- sys/event.h 7 Dec 2020 11:15:50 -0000 1.48
+++ sys/event.h 7 Dec 2020 17:01:10 -0000
@@ -215,6 +215,8 @@ struct timespec;
extern const struct filterops sig_filtops;
extern const struct filterops dead_filtops;
+extern void kqpoll_init(void);
+extern void kqpoll_exit(void);
extern void knote(struct klist *list, long hint);
extern void knote_activate(struct knote *);
extern void knote_remove(struct proc *p, struct knlist *list);
@@ -226,6 +228,7 @@ extern int kqueue_scan(struct kqueue_sca
struct timespec *, struct proc *, int *);
extern void kqueue_scan_setup(struct kqueue_scan_state *, struct kqueue *);
extern void kqueue_scan_finish(struct kqueue_scan_state *);
+extern void kqueue_purge(struct proc *, struct kqueue *);
extern int filt_seltrue(struct knote *kn, long hint);
extern int seltrue_kqfilter(dev_t, struct knote *);
extern void klist_insert(struct klist *, struct knote *);
Index: sys/proc.h
===================================================================
RCS file: /cvs/src/sys/sys/proc.h,v
retrieving revision 1.301
diff -u -p -r1.301 proc.h
--- sys/proc.h 10 Nov 2020 17:26:54 -0000 1.301
+++ sys/proc.h 7 Dec 2020 17:03:17 -0000
@@ -320,6 +320,7 @@ struct process {
struct kcov_dev;
struct lock_list_entry;
+struct kqueue;
struct p_inentry {
u_long ie_serial;
@@ -382,6 +383,8 @@ struct proc {
struct plimit *p_limit; /* [l] read ref. of p_p->ps_limit */
struct kcov_dev *p_kd; /* kcov device handle */
struct lock_list_entry *p_sleeplocks; /* WITNESS lock tracking */
+ struct kqueue *p_kq; /* [o] select/poll queue of evts */
+ unsigned long p_kq_serial; /* [o] to check against enqueued evts */
int p_siglist; /* [a] Signals arrived & not delivered*/