diff options
author | visa <visa@openbsd.org> | 2021-02-24 14:59:52 +0000 |
---|---|---|
committer | visa <visa@openbsd.org> | 2021-02-24 14:59:52 +0000 |
commit | 6d57c564656ee8c1c46a869a92c0b1fe7532302b (patch) | |
tree | 1ae10c8f9bcbdf6d953bdf197aad8be7b21ea53c /sys/sys/event.h | |
parent | Various fixes from emails Joachim Nilsson sent to tech@ many moons (diff) | |
download | wireguard-openbsd-6d57c564656ee8c1c46a869a92c0b1fe7532302b.tar.xz wireguard-openbsd-6d57c564656ee8c1c46a869a92c0b1fe7532302b.zip |
kqueue: Revise filterops interface
Extend kqueue's filterops interface with new callbacks so that it
becomes easier to use with fine-grained locking. The new interface
delegates the serialization of kn_event access to event sources. Now
kqueue uses filterops callbacks to read or write kn_event. This hides
event sources' locking patterns from kqueue, and allows clean
implementation of atomic read-and-clear for EV_CLEAR, for instance.
There are so many existing filterops instances that converting all of
them in one go is tricky. This patch adds a wrapper mechanism that
kqueue uses when the new callbacks are missing.
The new filterops interface has been influenced by XNU's kqueue.
OK mpi@ semarie@
Diffstat (limited to 'sys/sys/event.h')
-rw-r--r-- | sys/sys/event.h | 80 |
1 files changed, 69 insertions, 11 deletions
diff --git a/sys/sys/event.h b/sys/sys/event.h index b01bfde3780..105f7e5376f 100644 --- a/sys/sys/event.h +++ b/sys/sys/event.h @@ -1,4 +1,4 @@ -/* $OpenBSD: event.h,v 1.53 2021/01/17 05:56:32 visa Exp $ */ +/* $OpenBSD: event.h,v 1.54 2021/02/24 14:59:52 visa Exp $ */ /*- * Copyright (c) 1999,2000,2001 Jonathan Lemon <jlemon@FreeBSD.org> @@ -165,30 +165,85 @@ struct klist { */ #define NOTE_SIGNAL 0x08000000 +/* + * = Event filter interface + * + * == .f_flags + * + * Defines properties of the event filter: + * + * - FILTEROP_ISFD Each knote of this filter is associated + * with a file descriptor. + * + * - FILTEROP_MPSAFE The kqueue subsystem can invoke .f_attach(), + * .f_detach(), .f_modify() and .f_process() without + * the kernel lock. + * + * == .f_attach() + * + * Attaches the knote to the object. + * + * == .f_detach() + * + * Detaches the knote from the object. The object must not use this knote + * for delivering events after this callback has returned. + * + * == .f_event() + * + * Notifies the filter about an event. Called through knote(). + * + * == .f_modify() + * + * Modifies the knote with new state from the user. + * + * Returns non-zero if the knote has become active. + * + * == .f_process() + * + * Checks if the event is active and returns non-zero if the event should be + * returned to the user. + * + * If kev is non-NULL and the event is active, the callback should store + * the event's state in kev for delivery to the user. + * + * == Concurrency control + * + * The kqueue subsystem serializes calls of .f_attach(), .f_detach(), + * .f_modify() and .f_process(). + */ + #define FILTEROP_ISFD 0x00000001 /* ident == filedescriptor */ +#define FILTEROP_MPSAFE 0x00000002 /* safe without kernel lock */ struct filterops { int f_flags; int (*f_attach)(struct knote *kn); void (*f_detach)(struct knote *kn); int (*f_event)(struct knote *kn, long hint); + int (*f_modify)(struct kevent *kev, struct knote *kn); + int (*f_process)(struct knote *kn, struct kevent *kev); }; +/* + * Locking: + * I immutable after creation + * o object lock + */ struct knote { SLIST_ENTRY(knote) kn_link; /* for fd */ SLIST_ENTRY(knote) kn_selnext; /* for struct selinfo */ TAILQ_ENTRY(knote) kn_tqe; - struct kqueue *kn_kq; /* which queue we are on */ + struct kqueue *kn_kq; /* [I] which queue we are on */ struct kevent kn_kevent; int kn_status; - int kn_sfflags; /* saved filter flags */ - __int64_t kn_sdata; /* saved data field */ + int kn_sfflags; /* [o] saved filter flags */ + __int64_t kn_sdata; /* [o] saved data field */ union { struct file *p_fp; /* file data pointer */ struct process *p_process; /* process pointer */ } kn_ptr; const struct filterops *kn_fop; - void *kn_hook; + void *kn_hook; /* [o] */ #define KN_ACTIVE 0x0001 /* event has been triggered */ #define KN_QUEUED 0x0002 /* event is on queue */ #define KN_DISABLED 0x0004 /* event is disabled */ @@ -198,12 +253,13 @@ struct knote { #define KN_ATTACHED 0x0040 /* knote is attached to * a knlist of the kqueue */ -#define kn_id kn_kevent.ident -#define kn_filter kn_kevent.filter -#define kn_flags kn_kevent.flags -#define kn_fflags kn_kevent.fflags -#define kn_data kn_kevent.data -#define kn_fp kn_ptr.p_fp +#define kn_id kn_kevent.ident /* [I] */ +#define kn_filter kn_kevent.filter /* [I] */ +#define kn_flags kn_kevent.flags /* [o] */ +#define kn_fflags kn_kevent.fflags /* [o] */ +#define kn_data kn_kevent.data /* [o] */ +#define kn_udata kn_kevent.udata /* [o] */ +#define kn_fp kn_ptr.p_fp /* [o] */ }; struct klistops { @@ -234,6 +290,8 @@ extern void kqpoll_exit(void); extern void knote(struct klist *list, long hint); extern void knote_fdclose(struct proc *p, int fd); extern void knote_processexit(struct proc *); +extern void knote_modify(const struct kevent *, struct knote *); +extern void knote_submit(struct knote *, struct kevent *); extern int kqueue_register(struct kqueue *kq, struct kevent *kev, struct proc *p); extern int kqueue_scan(struct kqueue_scan_state *, int, struct kevent *, |