| 1 | /*	$NetBSD: event.h,v 1.55 2023/07/28 18:19:01 christos Exp $	*/ |
| 2 | |
| 3 | /*- |
| 4 | * Copyright (c) 1999,2000,2001 Jonathan Lemon <jlemon@FreeBSD.org> |
| 5 | * All rights reserved. |
| 6 | * |
| 7 | * Redistribution and use in source and binary forms, with or without |
| 8 | * modification, are permitted provided that the following conditions |
| 9 | * are met: |
| 10 | * 1. Redistributions of source code must retain the above copyright |
| 11 | * notice, this list of conditions and the following disclaimer. |
| 12 | * 2. Redistributions in binary form must reproduce the above copyright |
| 13 | * notice, this list of conditions and the following disclaimer in the |
| 14 | * documentation and/or other materials provided with the distribution. |
| 15 | * |
| 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND |
| 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
| 20 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| 21 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
| 22 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
| 23 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
| 24 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
| 25 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
| 26 | * SUCH DAMAGE. |
| 27 | * |
| 28 | *	$FreeBSD: src/sys/sys/event.h,v 1.12 2001/02/24 01:44:03 jlemon Exp $ |
| 29 | */ |
| 30 | |
| 31 | #ifndef _SYS_EVENT_H_ |
| 32 | #define	_SYS_EVENT_H_ |
| 33 | |
| 34 | #include <sys/featuretest.h> |
| 35 | #include <sys/types.h>			/* for size_t */ |
| 36 | #include <sys/inttypes.h>		/* for uintptr_t */ |
| 37 | #include <sys/null.h>			/* for NULL */ |
| 38 | |
| 39 | #define	EVFILT_READ		0U |
| 40 | #define	EVFILT_WRITE		1U |
| 41 | #define	EVFILT_AIO		2U	/* attached to aio requests */ |
| 42 | #define	EVFILT_VNODE		3U	/* attached to vnodes */ |
| 43 | #define	EVFILT_PROC		4U	/* attached to struct proc */ |
| 44 | #define	EVFILT_SIGNAL		5U	/* attached to struct proc */ |
| 45 | #define	EVFILT_TIMER		6U	/* arbitrary timer (in ms) */ |
| 46 | #define	EVFILT_FS		7U	/* filesystem events */ |
| 47 | #define	EVFILT_USER		8U	/* user events */ |
| 48 | #define	EVFILT_EMPTY		9U |
| 49 | #define	EVFILT_SYSCOUNT		10U	/* number of filters */ |
| 50 | |
| 51 | #ifdef EVFILT_NAMES |
| 52 | static const char *evfiltnames[] = { |
| 53 | 	"EVFILT_READ", |
| 54 | 	"EVFILT_WRITE", |
| 55 | 	"EVFILT_AIO", |
| 56 | 	"EVFILT_VNODE", |
| 57 | 	"EVFILT_PROC", |
| 58 | 	"EVFILT_SIGNAL", |
| 59 | 	"EVFILT_TIMER", |
| 60 | 	"EVFILT_FS", |
| 61 | 	"EVFILT_USER", |
| 62 | 	"EVFILT_EMPTY", |
| 63 | }; |
| 64 | #endif |
| 65 | |
| 66 | struct kevent { |
| 67 | 	uintptr_t	ident;		/* identifier for this event */ |
| 68 | 	uint32_t	filter;		/* filter for event */ |
| 69 | 	uint32_t	flags;		/* action flags for kqueue */ |
| 70 | 	uint32_t	fflags;		/* filter flag value */ |
| 71 | 	int64_t		data;		/* filter data value */ |
| 72 | 	void		*udata;		/* opaque user data identifier */ |
| 73 | 	uint64_t	ext[4];		/* extensions */ |
| 74 | }; |
| 75 | |
| 76 | static __inline void |
| 77 | _EV_SET(struct kevent *_kevp, uintptr_t _ident, uint32_t _filter, |
| 78 | uint32_t _flags, uint32_t _fflags, int64_t _data, void *_udata) |
| 79 | { |
| 80 | 	_kevp->ident = _ident; |
| 81 | 	_kevp->filter = _filter; |
| 82 | 	_kevp->flags = _flags; |
| 83 | 	_kevp->fflags = _fflags; |
| 84 | 	_kevp->data = _data; |
| 85 | 	_kevp->udata = _udata; |
| 86 | } |
| 87 | |
| 88 | #define EV_SET(kevp, ident, filter, flags, fflags, data, udata)	\ |
| 89 | _EV_SET((kevp), __CAST(uintptr_t, (ident)), (filter), (flags), \ |
| 90 | (fflags), (data), __CAST(void *, (udata))) |
| 91 | |
| 92 | /* actions */ |
| 93 | #define	EV_ADD		0x0001U		/* add event to kq (implies ENABLE) */ |
| 94 | #define	EV_DELETE	0x0002U		/* delete event from kq */ |
| 95 | #define	EV_ENABLE	0x0004U		/* enable event */ |
| 96 | #define	EV_DISABLE	0x0008U		/* disable event (not reported) */ |
| 97 | |
| 98 | /* flags */ |
| 99 | #define	EV_ONESHOT	0x0010U		/* only report one occurrence */ |
| 100 | #define	EV_CLEAR	0x0020U		/* clear event state after reporting */ |
| 101 | #define EV_RECEIPT	0x0040U		/* force EV_ERROR on success, data=0 */ |
| 102 | #define EV_DISPATCH	0x0080U		/* disable event after reporting */ |
| 103 | |
| 104 | #define	EV_SYSFLAGS	0xF000U		/* reserved by system */ |
| 105 | #define	EV_FLAG1	0x2000U		/* filter-specific flag */ |
| 106 | |
| 107 | /* returned values */ |
| 108 | #define	EV_EOF		0x8000U		/* EOF detected */ |
| 109 | #define	EV_ERROR	0x4000U		/* error, data contains errno */ |
| 110 | |
| 111 | /* |
| 112 | * data/hint flags/masks for EVFILT_USER, shared with userspace |
| 113 | * |
| 114 | * On input, the top two bits of fflags specifies how the lower twenty four |
| 115 | * bits should be applied to the stored value of fflags. |
| 116 | * |
| 117 | * On output, the top two bits will always be set to NOTE_FFNOP and the |
| 118 | * remaining twenty four bits will contain the stored fflags value. |
| 119 | */ |
| 120 | #define	NOTE_FFNOP	0x00000000U		/* ignore input fflags */ |
| 121 | #define	NOTE_FFAND	0x40000000U		/* AND fflags */ |
| 122 | #define	NOTE_FFOR	0x80000000U		/* OR fflags */ |
| 123 | #define	NOTE_FFCOPY	0xc0000000U		/* copy fflags */ |
| 124 | |
| 125 | #define	NOTE_FFCTRLMASK	0xc0000000U		/* masks for operations */ |
| 126 | #define	NOTE_FFLAGSMASK	0x00ffffffU |
| 127 | |
| 128 | #define	NOTE_TRIGGER	0x01000000U		/* Cause the event to be |
| 129 | 						 triggered for output. */ |
| 130 | /* |
| 131 | * hint flag for in-kernel use - must not equal any existing note |
| 132 | */ |
| 133 | #ifdef _KERNEL |
| 134 | #define NOTE_SUBMIT	0x01000000U		/* initial knote submission */ |
| 135 | #endif |
| 136 | /* |
| 137 | * data/hint flags for EVFILT_{READ|WRITE}, shared with userspace |
| 138 | */ |
| 139 | #define	NOTE_LOWAT	0x0001U			/* low water mark */ |
| 140 | |
| 141 | /* |
| 142 | * data/hint flags for EVFILT_VNODE, shared with userspace |
| 143 | */ |
| 144 | #define	NOTE_DELETE	0x0001U			/* vnode was removed */ |
| 145 | #define	NOTE_WRITE	0x0002U			/* data contents changed */ |
| 146 | #define	NOTE_EXTEND	0x0004U			/* size increased */ |
| 147 | #define	NOTE_ATTRIB	0x0008U			/* attributes changed */ |
| 148 | #define	NOTE_LINK	0x0010U			/* link count changed */ |
| 149 | #define	NOTE_RENAME	0x0020U			/* vnode was renamed */ |
| 150 | #define	NOTE_REVOKE	0x0040U			/* vnode access was revoked */ |
| 151 | #define	NOTE_OPEN	0x0080U			/* vnode was opened */ |
| 152 | #define	NOTE_CLOSE	0x0100U			/* file closed (no FWRITE) */ |
| 153 | #define	NOTE_CLOSE_WRITE 0x0200U		/* file closed (FWRITE) */ |
| 154 | #define	NOTE_READ	0x0400U			/* file was read */ |
| 155 | |
| 156 | /* |
| 157 | * data/hint flags for EVFILT_PROC, shared with userspace |
| 158 | */ |
| 159 | #define	NOTE_EXIT	0x80000000U		/* process exited */ |
| 160 | #define	NOTE_FORK	0x40000000U		/* process forked */ |
| 161 | #define	NOTE_EXEC	0x20000000U		/* process exec'd */ |
| 162 | #define	NOTE_PCTRLMASK	0xf0000000U		/* mask for hint bits */ |
| 163 | #define	NOTE_PDATAMASK	0x000fffffU		/* mask for pid */ |
| 164 | |
| 165 | /* additional flags for EVFILT_PROC */ |
| 166 | #define	NOTE_TRACK	0x00000001U		/* follow across forks */ |
| 167 | #define	NOTE_TRACKERR	0x00000002U		/* could not track child */ |
| 168 | #define	NOTE_CHILD	0x00000004U		/* am a child process */ |
| 169 | |
| 170 | /* additional flags for EVFILT_TIMER */ |
| 171 | #define	NOTE_MSECONDS	0x00000000U		/* data is milliseconds */ |
| 172 | #define	NOTE_SECONDS	0x00000001U		/* data is seconds */ |
| 173 | #define	NOTE_USECONDS	0x00000002U		/* data is microseconds */ |
| 174 | #define	NOTE_NSECONDS	0x00000003U		/* data is nanoseconds */ |
| 175 | #define	NOTE_ABSTIME	0x00000010U		/* timeout is absolute */ |
| 176 | #ifdef _KERNEL |
| 177 | #define	NOTE_TIMER_UNITMASK 0x0003U |
| 178 | #endif /* _KERNEL */ |
| 179 | |
| 180 | /* |
| 181 | * This is currently visible to userland to work around broken |
| 182 | * programs which pull in <sys/proc.h> or <sys/select.h>. |
| 183 | */ |
| 184 | #include <sys/queue.h> |
| 185 | struct knote; |
| 186 | SLIST_HEAD(klist, knote); |
| 187 | |
| 188 | |
| 189 | /* |
| 190 | * ioctl(2)s supported on kqueue descriptors. |
| 191 | */ |
| 192 | #include <sys/ioctl.h> |
| 193 | |
| 194 | struct kfilter_mapping { |
| 195 | 	char		*name;		/* name to lookup or return */ |
| 196 | 	size_t		len;		/* length of name */ |
| 197 | 	uint32_t	filter;		/* filter to lookup or return */ |
| 198 | }; |
| 199 | |
| 200 | /* map filter to name (max size len) */ |
| 201 | #define KFILTER_BYFILTER	_IOWR('k', 0, struct kfilter_mapping) |
| 202 | /* map name to filter (len ignored) */ |
| 203 | #define KFILTER_BYNAME		_IOWR('k', 1, struct kfilter_mapping) |
| 204 | |
| 205 | #ifdef _KERNEL |
| 206 | |
| 207 | #define	KNOTE(list, hint)	if (!SLIST_EMPTY(list)) knote(list, hint) |
| 208 | |
| 209 | /* |
| 210 | * Flag indicating hint is a signal. Used by EVFILT_SIGNAL, and also |
| 211 | * shared by EVFILT_PROC (all knotes attached to p->p_klist) |
| 212 | */ |
| 213 | #define	NOTE_SIGNAL	0x08000000U |
| 214 | |
| 215 | /* |
| 216 | * Hint values for the optional f_touch event filter. If f_touch is not set |
| 217 | * to NULL and f_isfd is zero the f_touch filter will be called with the type |
| 218 | * argument set to EVENT_REGISTER during a kevent() system call. It is also |
| 219 | * called under the same conditions with the type argument set to EVENT_PROCESS |
| 220 | * when the event has been triggered. |
| 221 | */ |
| 222 | #define	EVENT_REGISTER	1 |
| 223 | #define	EVENT_PROCESS	2 |
| 224 | |
| 225 | /* |
| 226 | * Callback methods for each filter type. |
| 227 | */ |
| 228 | struct filterops { |
| 229 | 	int	f_flags;		/* flags; see below */ |
| 230 | 	int	(*f_attach)	(struct knote *); |
| 231 | 					/* called when knote is ADDed */ |
| 232 | 	void	(*f_detach)	(struct knote *); |
| 233 | 					/* called when knote is DELETEd */ |
| 234 | 	int	(*f_event)	(struct knote *, long); |
| 235 | 					/* called when event is triggered */ |
| 236 | 	int	(*f_touch)	(struct knote *, struct kevent *, long); |
| 237 | }; |
| 238 | |
| 239 | /* filterops flags */ |
| 240 | #define	FILTEROP_ISFD	__BIT(0)	/* ident == file descriptor */ |
| 241 | #define	FILTEROP_MPSAFE	__BIT(1)	/* does not require KERNEL_LOCK */ |
| 242 | |
| 243 | /* |
| 244 | * Field locking: |
| 245 | * |
| 246 | * f	kn_kq->kq_fdp->fd_lock |
| 247 | * q	kn_kq->kq_lock |
| 248 | * o	object mutex (e.g. device driver or vnode interlock) |
| 249 | */ |
| 250 | struct kfilter; |
| 251 | |
| 252 | struct knote { |
| 253 | 	SLIST_ENTRY(knote)	kn_link;	/* f: for fd */ |
| 254 | 	SLIST_ENTRY(knote)	kn_selnext;	/* o: for struct selinfo */ |
| 255 | 	TAILQ_ENTRY(knote)	kn_tqe;		/* q: for struct kqueue */ |
| 256 | 	struct kqueue		*kn_kq;		/* q: which queue we are on */ |
| 257 | 	struct kevent		kn_kevent;	/* (see below for locking) */ |
| 258 | 	uint32_t		kn_status;	/* q: flags below */ |
| 259 | 	uint32_t		kn_sfflags;	/* saved filter flags */ |
| 260 | 	uintptr_t		kn_sdata;	/* saved data field */ |
| 261 | 	void			*kn_obj;	/* monitored obj */ |
| 262 | 	const struct filterops	*kn_fop; |
| 263 | 	struct kfilter		*kn_kfilter; |
| 264 | 	void 			*kn_hook; |
| 265 | 	int			kn_hookid; |
| 266 | |
| 267 | #define	KN_ACTIVE	0x01U			/* event has been triggered */ |
| 268 | #define	KN_QUEUED	0x02U			/* event is on queue */ |
| 269 | #define	KN_DISABLED	0x04U			/* event is disabled */ |
| 270 | #define	KN_DETACHED	0x08U			/* knote is detached */ |
| 271 | #define	KN_MARKER	0x10U			/* is a marker */ |
| 272 | #define	KN_BUSY		0x20U			/* is being scanned */ |
| 273 | #define	KN_WILLDETACH	0x40U			/* being detached imminently */ |
| 274 | /* Toggling KN_BUSY also requires kn_kq->kq_fdp->fd_lock. */ |
| 275 | #define __KN_FLAG_BITS \ |
| 276 | "\20" \ |
| 277 | "\1ACTIVE" \ |
| 278 | "\2QUEUED" \ |
| 279 | "\3DISABLED" \ |
| 280 | "\4DETACHED" \ |
| 281 | "\5MARKER" \ |
| 282 | "\6BUSY" \ |
| 283 | "\7WILLDETACH" |
| 284 | |
| 285 | |
| 286 | /* |
| 287 | * The only time knote::kn_flags can be modified without synchronization |
| 288 | * is during filter attach, because the knote has not yet been published. |
| 289 | * This is usually to set EV_CLEAR or EV_ONESHOT as mandatory flags for |
| 290 | * that filter. |
| 291 | */ |
| 292 | #define	kn_id		kn_kevent.ident |
| 293 | #define	kn_filter	kn_kevent.filter |
| 294 | #define	kn_flags	kn_kevent.flags		/* q */ |
| 295 | #define	kn_fflags	kn_kevent.fflags	/* o */ |
| 296 | #define	kn_data		kn_kevent.data		/* o */ |
| 297 | }; |
| 298 | |
| 299 | #include <sys/systm.h>	/* for copyin_t */ |
| 300 | |
| 301 | struct lwp; |
| 302 | struct timespec; |
| 303 | |
| 304 | void	kqueue_init(void); |
| 305 | void	knote(struct klist *, long); |
| 306 | void	knote_fdclose(int); |
| 307 | void	knote_set_eof(struct knote *, uint32_t); |
| 308 | void	knote_clear_eof(struct knote *); |
| 309 | |
| 310 | typedef	int (*kevent_fetch_changes_t)(void *, const struct kevent *, |
| 311 | struct kevent *, size_t, int); |
| 312 | typedef	int (*kevent_put_events_t)(void *, struct kevent *, struct kevent *, |
| 313 | size_t, int); |
| 314 | |
| 315 | struct kevent_ops { |
| 316 | 	void *keo_private; |
| 317 | 	copyin_t keo_fetch_timeout; |
| 318 | 	kevent_fetch_changes_t keo_fetch_changes; |
| 319 | 	kevent_put_events_t keo_put_events; |
| 320 | }; |
| 321 | |
| 322 | |
| 323 | int	kevent_fetch_changes(void *, const struct kevent *, struct kevent *, |
| 324 | size_t, int); |
| 325 | int 	kevent_put_events(void *, struct kevent *, struct kevent *, size_t, |
| 326 | int); |
| 327 | int	kevent1(register_t *, int, const struct kevent *, |
| 328 | size_t, struct kevent *, size_t, const struct timespec *, |
| 329 | const struct kevent_ops *); |
| 330 | |
| 331 | int	kfilter_register(const char *, const struct filterops *, int *); |
| 332 | int	kfilter_unregister(const char *); |
| 333 | |
| 334 | int	filt_seltrue(struct knote *, long); |
| 335 | extern const struct filterops seltrue_filtops; |
| 336 | |
| 337 | void	klist_init(struct klist *); |
| 338 | void	klist_fini(struct klist *); |
| 339 | void	klist_insert(struct klist *, struct knote *); |
| 340 | bool	klist_remove(struct klist *, struct knote *); |
| 341 | |
| 342 | #else 	/* !_KERNEL */ |
| 343 | |
| 344 | #include <sys/cdefs.h> |
| 345 | struct timespec; |
| 346 | |
| 347 | __BEGIN_DECLS |
| 348 | #if defined(_NETBSD_SOURCE) |
| 349 | int	kqueue(void); |
| 350 | int	kqueue1(int); |
| 351 | #ifndef __LIBC12_SOURCE__ |
| 352 | int	kevent(int, const struct kevent *, size_t, struct kevent *, size_t, |
| 353 | 		 const struct timespec *) __RENAME(__kevent100); |
| 354 | #endif |
| 355 | #endif /* !_POSIX_C_SOURCE */ |
| 356 | __END_DECLS |
| 357 | |
| 358 | #endif /* !_KERNEL */ |
| 359 | |
| 360 | #endif /* !_SYS_EVENT_H_ */ |