| 1 | /*	$NetBSD: event.h,v 1.32 2018/01/09 03:31:13 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_SYSCOUNT		8U	/* number of filters */ | 
| 48 |  | 
| 49 | struct kevent { | 
| 50 | 	uintptr_t	ident;		/* identifier for this event */ | 
| 51 | 	uint32_t	filter;		/* filter for event */ | 
| 52 | 	uint32_t	flags;		/* action flags for kqueue */ | 
| 53 | 	uint32_t	fflags;		/* filter flag value */ | 
| 54 | 	int64_t		data;		/* filter data value */ | 
| 55 | 	intptr_t	udata;		/* opaque user data identifier */ | 
| 56 | }; | 
| 57 |  | 
| 58 | #define EV_SET(kevp, ident, filter, flags, fflags, data, udata)	\ | 
| 59 |     _EV_SET((kevp), __CAST(uintptr_t, (ident)), (filter), (flags), \ | 
| 60 |     (fflags), (data), __CAST(intptr_t, (udata))) | 
| 61 |  | 
| 62 | static __inline void | 
| 63 | _EV_SET(struct kevent *_kevp, uintptr_t _ident, uint32_t _filter, | 
| 64 |     uint32_t _flags, uint32_t _fflags, int64_t _data, intptr_t _udata) | 
| 65 | { | 
| 66 | 	_kevp->ident = _ident; | 
| 67 | 	_kevp->filter = _filter; | 
| 68 | 	_kevp->flags = _flags; | 
| 69 | 	_kevp->fflags = _fflags; | 
| 70 | 	_kevp->data = _data; | 
| 71 | 	_kevp->udata = _udata; | 
| 72 | } | 
| 73 |  | 
| 74 | /* actions */ | 
| 75 | #define	EV_ADD		0x0001U		/* add event to kq (implies ENABLE) */ | 
| 76 | #define	EV_DELETE	0x0002U		/* delete event from kq */ | 
| 77 | #define	EV_ENABLE	0x0004U		/* enable event */ | 
| 78 | #define	EV_DISABLE	0x0008U		/* disable event (not reported) */ | 
| 79 |  | 
| 80 | /* flags */ | 
| 81 | #define	EV_ONESHOT	0x0010U		/* only report one occurrence */ | 
| 82 | #define	EV_CLEAR	0x0020U		/* clear event state after reporting */ | 
| 83 | #define EV_RECEIPT	0x0040U		/* force EV_ERROR on success, data=0 */ | 
| 84 | #define EV_DISPATCH	0x0080U		/* disable event after reporting */ | 
| 85 |  | 
| 86 | #define	EV_SYSFLAGS	0xF000U		/* reserved by system */ | 
| 87 | #define	EV_FLAG1	0x2000U		/* filter-specific flag */ | 
| 88 |  | 
| 89 | /* returned values */ | 
| 90 | #define	EV_EOF		0x8000U		/* EOF detected */ | 
| 91 | #define	EV_ERROR	0x4000U		/* error, data contains errno */ | 
| 92 |  | 
| 93 | /* | 
| 94 |  * hint flag for in-kernel use - must not equal any existing note | 
| 95 |  */ | 
| 96 | #ifdef _KERNEL | 
| 97 | #define NOTE_SUBMIT	0x01000000U		/* initial knote submission */ | 
| 98 | #endif | 
| 99 | /* | 
| 100 |  * data/hint flags for EVFILT_{READ|WRITE}, shared with userspace | 
| 101 |  */ | 
| 102 | #define	NOTE_LOWAT	0x0001U			/* low water mark */ | 
| 103 |  | 
| 104 | /* | 
| 105 |  * data/hint flags for EVFILT_VNODE, shared with userspace | 
| 106 |  */ | 
| 107 | #define	NOTE_DELETE	0x0001U			/* vnode was removed */ | 
| 108 | #define	NOTE_WRITE	0x0002U			/* data contents changed */ | 
| 109 | #define	NOTE_EXTEND	0x0004U			/* size increased */ | 
| 110 | #define	NOTE_ATTRIB	0x0008U			/* attributes changed */ | 
| 111 | #define	NOTE_LINK	0x0010U			/* link count changed */ | 
| 112 | #define	NOTE_RENAME	0x0020U			/* vnode was renamed */ | 
| 113 | #define	NOTE_REVOKE	0x0040U			/* vnode access was revoked */ | 
| 114 |  | 
| 115 | /* | 
| 116 |  * data/hint flags for EVFILT_PROC, shared with userspace | 
| 117 |  */ | 
| 118 | #define	NOTE_EXIT	0x80000000U		/* process exited */ | 
| 119 | #define	NOTE_FORK	0x40000000U		/* process forked */ | 
| 120 | #define	NOTE_EXEC	0x20000000U		/* process exec'd */ | 
| 121 | #define	NOTE_PCTRLMASK	0xf0000000U		/* mask for hint bits */ | 
| 122 | #define	NOTE_PDATAMASK	0x000fffffU		/* mask for pid */ | 
| 123 |  | 
| 124 | /* additional flags for EVFILT_PROC */ | 
| 125 | #define	NOTE_TRACK	0x00000001U		/* follow across forks */ | 
| 126 | #define	NOTE_TRACKERR	0x00000002U		/* could not track child */ | 
| 127 | #define	NOTE_CHILD	0x00000004U		/* am a child process */ | 
| 128 |  | 
| 129 | /* | 
| 130 |  * This is currently visible to userland to work around broken | 
| 131 |  * programs which pull in <sys/proc.h> or <sys/select.h>. | 
| 132 |  */ | 
| 133 | #include <sys/queue.h> | 
| 134 | struct knote; | 
| 135 | SLIST_HEAD(klist, knote); | 
| 136 |  | 
| 137 |  | 
| 138 | /* | 
| 139 |  * ioctl(2)s supported on kqueue descriptors. | 
| 140 |  */ | 
| 141 | #include <sys/ioctl.h> | 
| 142 |  | 
| 143 | struct kfilter_mapping { | 
| 144 | 	char		*name;		/* name to lookup or return */ | 
| 145 | 	size_t		len;		/* length of name */ | 
| 146 | 	uint32_t	filter;		/* filter to lookup or return */ | 
| 147 | }; | 
| 148 |  | 
| 149 | /* map filter to name (max size len) */ | 
| 150 | #define KFILTER_BYFILTER	_IOWR('k', 0, struct kfilter_mapping) | 
| 151 | /* map name to filter (len ignored) */ | 
| 152 | #define KFILTER_BYNAME		_IOWR('k', 1, struct kfilter_mapping) | 
| 153 |  | 
| 154 | #ifdef _KERNEL | 
| 155 |  | 
| 156 | #define	KNOTE(list, hint)	if (!SLIST_EMPTY(list)) knote(list, hint) | 
| 157 |  | 
| 158 | /* | 
| 159 |  * Flag indicating hint is a signal.  Used by EVFILT_SIGNAL, and also | 
| 160 |  * shared by EVFILT_PROC  (all knotes attached to p->p_klist) | 
| 161 |  */ | 
| 162 | #define	NOTE_SIGNAL	0x08000000U | 
| 163 |  | 
| 164 | /* | 
| 165 |  * Callback methods for each filter type. | 
| 166 |  */ | 
| 167 | struct filterops { | 
| 168 | 	int	f_isfd;			/* true if ident == filedescriptor */ | 
| 169 | 	int	(*f_attach)	(struct knote *); | 
| 170 | 					/* called when knote is ADDed */ | 
| 171 | 	void	(*f_detach)	(struct knote *); | 
| 172 | 					/* called when knote is DELETEd */ | 
| 173 | 	int	(*f_event)	(struct knote *, long); | 
| 174 | 					/* called when event is triggered */ | 
| 175 | }; | 
| 176 |  | 
| 177 | /* | 
| 178 |  * Field locking: | 
| 179 |  * | 
| 180 |  * f	kn_kq->kq_fdp->fd_lock | 
| 181 |  * q	kn_kq->kq_lock | 
| 182 |  * o	object mutex (e.g. device driver or vnode interlock) | 
| 183 |  */ | 
| 184 | struct kfilter; | 
| 185 |  | 
| 186 | struct knote { | 
| 187 | 	SLIST_ENTRY(knote)	kn_link;	/* f: for fd */ | 
| 188 | 	SLIST_ENTRY(knote)	kn_selnext;	/* o: for struct selinfo */ | 
| 189 | 	TAILQ_ENTRY(knote)	kn_tqe;		/* q: for struct kqueue */ | 
| 190 | 	struct kqueue		*kn_kq;		/* q: which queue we are on */ | 
| 191 | 	struct kevent		kn_kevent; | 
| 192 | 	uint32_t		kn_status;	/* q: flags below */ | 
| 193 | 	uint32_t		kn_sfflags;	/*    saved filter flags */ | 
| 194 | 	uintptr_t		kn_sdata;	/*    saved data field */ | 
| 195 | 	void			*kn_obj;	/*    monitored obj */ | 
| 196 | 	const struct filterops	*kn_fop; | 
| 197 | 	struct kfilter		*kn_kfilter; | 
| 198 | 	void 			*kn_hook; | 
| 199 |  | 
| 200 | #define	KN_ACTIVE	0x01U			/* event has been triggered */ | 
| 201 | #define	KN_QUEUED	0x02U			/* event is on queue */ | 
| 202 | #define	KN_DISABLED	0x04U			/* event is disabled */ | 
| 203 | #define	KN_DETACHED	0x08U			/* knote is detached */ | 
| 204 | #define	KN_MARKER	0x10U			/* is a marker */ | 
| 205 | #define	KN_BUSY		0x20U			/* is being scanned */ | 
| 206 | /* Toggling KN_BUSY also requires kn_kq->kq_fdp->fd_lock. */ | 
| 207 | #define __KN_FLAG_BITS \ | 
| 208 |     "\20" \ | 
| 209 |     "\1ACTIVE" \ | 
| 210 |     "\2QUEUED" \ | 
| 211 |     "\3DISABLED" \ | 
| 212 |     "\4DETACHED" \ | 
| 213 |     "\5MARKER" \ | 
| 214 |     "\6BUSY" | 
| 215 |  | 
| 216 |  | 
| 217 | #define	kn_id		kn_kevent.ident | 
| 218 | #define	kn_filter	kn_kevent.filter | 
| 219 | #define	kn_flags	kn_kevent.flags | 
| 220 | #define	kn_fflags	kn_kevent.fflags | 
| 221 | #define	kn_data		kn_kevent.data | 
| 222 | }; | 
| 223 |  | 
| 224 | #include <sys/systm.h> /* for copyin_t */ | 
| 225 |  | 
| 226 | struct lwp; | 
| 227 | struct timespec; | 
| 228 |  | 
| 229 | void	kqueue_init(void); | 
| 230 | void	knote(struct klist *, long); | 
| 231 | void	knote_fdclose(int); | 
| 232 |  | 
| 233 | typedef	int (*kevent_fetch_changes_t)(void *, const struct kevent *, | 
| 234 |     struct kevent *, size_t, int); | 
| 235 | typedef	int (*kevent_put_events_t)(void *, struct kevent *, struct kevent *, | 
| 236 |     size_t, int); | 
| 237 |  | 
| 238 | struct kevent_ops { | 
| 239 | 	void *keo_private; | 
| 240 | 	copyin_t keo_fetch_timeout; | 
| 241 | 	kevent_fetch_changes_t keo_fetch_changes; | 
| 242 | 	kevent_put_events_t keo_put_events; | 
| 243 | }; | 
| 244 |  | 
| 245 |  | 
| 246 | int	kevent_fetch_changes(void *, const struct kevent *, struct kevent *, | 
| 247 |     size_t, int); | 
| 248 | int 	kevent_put_events(void *, struct kevent *, struct kevent *, size_t, | 
| 249 |     int); | 
| 250 | int	kevent1(register_t *, int, const struct kevent *, | 
| 251 |     size_t, struct kevent *, size_t, const struct timespec *, | 
| 252 |     const struct kevent_ops *); | 
| 253 |  | 
| 254 | int	kfilter_register(const char *, const struct filterops *, int *); | 
| 255 | int	kfilter_unregister(const char *); | 
| 256 |  | 
| 257 | int	filt_seltrue(struct knote *, long); | 
| 258 | extern const struct filterops seltrue_filtops; | 
| 259 |  | 
| 260 | extern struct klist fs_klist;	/* EVFILT_FS */ | 
| 261 |  | 
| 262 | #else 	/* !_KERNEL */ | 
| 263 |  | 
| 264 | #include <sys/cdefs.h> | 
| 265 | struct timespec; | 
| 266 |  | 
| 267 | __BEGIN_DECLS | 
| 268 | #if defined(_NETBSD_SOURCE) | 
| 269 | int	kqueue(void); | 
| 270 | int	kqueue1(int); | 
| 271 | #ifndef __LIBC12_SOURCE__ | 
| 272 | int	kevent(int, const struct kevent *, size_t, struct kevent *, size_t, | 
| 273 | 		    const struct timespec *) __RENAME(__kevent50); | 
| 274 | #endif | 
| 275 | #endif /* !_POSIX_C_SOURCE */ | 
| 276 | __END_DECLS | 
| 277 |  | 
| 278 | #endif /* !_KERNEL */ | 
| 279 |  | 
| 280 | #endif /* !_SYS_EVENT_H_ */ | 
| 281 |  |