xref: /openbsd/sys/sys/event.h (revision 0747e3d2)
1 /*	$OpenBSD: event.h,v 1.73 2024/08/06 08:44:54 claudio 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.11 2001/02/24 01:41:31 jlemon Exp $
29  */
30 
31 #ifndef _SYS_EVENT_H_
32 #define _SYS_EVENT_H_
33 
34 #define EVFILT_READ		(-1)
35 #define EVFILT_WRITE		(-2)
36 #define EVFILT_AIO		(-3)	/* attached to aio requests */
37 #define EVFILT_VNODE		(-4)	/* attached to vnodes */
38 #define EVFILT_PROC		(-5)	/* attached to struct process */
39 #define EVFILT_SIGNAL		(-6)	/* attached to struct process */
40 #define EVFILT_TIMER		(-7)	/* timers */
41 #define EVFILT_DEVICE		(-8)	/* devices */
42 #define EVFILT_EXCEPT		(-9)	/* exceptional conditions */
43 
44 #define EVFILT_SYSCOUNT		9
45 
46 #define EV_SET(kevp, a, b, c, d, e, f) do {	\
47 	struct kevent *__kevp = (kevp);		\
48 	(__kevp)->ident = (a);			\
49 	(__kevp)->filter = (b);			\
50 	(__kevp)->flags = (c);			\
51 	(__kevp)->fflags = (d);			\
52 	(__kevp)->data = (e);			\
53 	(__kevp)->udata = (f);			\
54 } while(0)
55 
56 struct kevent {
57 	__uintptr_t	ident;		/* identifier for this event */
58 	short		filter;		/* filter for event */
59 	unsigned short	flags;		/* action flags for kqueue */
60 	unsigned int	fflags;		/* filter flag value */
61 	__int64_t	data;		/* filter data value */
62 	void		*udata;		/* opaque user data identifier */
63 };
64 
65 /* actions */
66 #define EV_ADD		0x0001		/* add event to kq (implies enable) */
67 #define EV_DELETE	0x0002		/* delete event from kq */
68 #define EV_ENABLE	0x0004		/* enable event */
69 #define EV_DISABLE	0x0008		/* disable event (not reported) */
70 
71 /* flags */
72 #define EV_ONESHOT	0x0010		/* only report one occurrence */
73 #define EV_CLEAR	0x0020		/* clear event state after reporting */
74 #define EV_RECEIPT	0x0040          /* force EV_ERROR on success, data=0 */
75 #define EV_DISPATCH	0x0080          /* disable event after reporting */
76 
77 #define EV_SYSFLAGS	0xf800		/* reserved by system */
78 #define EV_FLAG1	0x2000		/* filter-specific flag */
79 
80 /* returned values */
81 #define EV_EOF		0x8000		/* EOF detected */
82 #define EV_ERROR	0x4000		/* error, data contains errno */
83 
84 /*
85  * data/hint flags for EVFILT_{READ|WRITE}, shared with userspace
86  */
87 #define NOTE_LOWAT	0x0001			/* low water mark */
88 #define NOTE_EOF	0x0002			/* return on EOF */
89 
90 /*
91  * data/hint flags for EVFILT_EXCEPT, shared with userspace and with
92  * EVFILT_{READ|WRITE}
93  */
94 #define NOTE_OOB	0x0004			/* OOB data on a socket */
95 
96 /*
97  * data/hint flags for EVFILT_VNODE, shared with userspace
98  */
99 #define	NOTE_DELETE	0x0001			/* vnode was removed */
100 #define	NOTE_WRITE	0x0002			/* data contents changed */
101 #define	NOTE_EXTEND	0x0004			/* size increased */
102 #define	NOTE_ATTRIB	0x0008			/* attributes changed */
103 #define	NOTE_LINK	0x0010			/* link count changed */
104 #define	NOTE_RENAME	0x0020			/* vnode was renamed */
105 #define	NOTE_REVOKE	0x0040			/* vnode access was revoked */
106 #define	NOTE_TRUNCATE   0x0080			/* vnode was truncated */
107 
108 /*
109  * data/hint flags for EVFILT_PROC, shared with userspace
110  */
111 #define	NOTE_EXIT	0x80000000		/* process exited */
112 #define	NOTE_FORK	0x40000000		/* process forked */
113 #define	NOTE_EXEC	0x20000000		/* process exec'd */
114 #define	NOTE_PCTRLMASK	0xf0000000		/* mask for hint bits */
115 #define	NOTE_PDATAMASK	0x000fffff		/* mask for pid */
116 
117 /* additional flags for EVFILT_PROC */
118 #define	NOTE_TRACK	0x00000001		/* follow across forks */
119 #define	NOTE_TRACKERR	0x00000002		/* could not track child */
120 #define	NOTE_CHILD	0x00000004		/* am a child process */
121 
122 /* data/hint flags for EVFILT_DEVICE, shared with userspace */
123 #define NOTE_CHANGE	0x00000001		/* device change event */
124 
125 /* additional flags for EVFILT_TIMER */
126 #define NOTE_MSECONDS	0x00000000		/* data is milliseconds */
127 #define NOTE_SECONDS	0x00000001		/* data is seconds */
128 #define NOTE_USECONDS	0x00000002		/* data is microseconds */
129 #define NOTE_NSECONDS	0x00000003		/* data is nanoseconds */
130 #define NOTE_ABSTIME	0x00000010		/* timeout is absolute */
131 
132 /*
133  * This is currently visible to userland to work around broken
134  * programs which pull in <sys/proc.h> or <sys/selinfo.h>.
135  */
136 #include <sys/queue.h>
137 
138 struct klistops;
139 struct knote;
140 SLIST_HEAD(knlist, knote);
141 
142 struct klist {
143 	struct knlist		 kl_list;
144 	const struct klistops	*kl_ops;
145 	void			*kl_arg;
146 };
147 
148 #ifdef _KERNEL
149 
150 /* kernel-only flags */
151 #define __EV_SELECT	0x0800		/* match behavior of select */
152 #define __EV_POLL	0x1000		/* match behavior of poll */
153 #define __EV_HUP	EV_FLAG1	/* device or socket disconnected */
154 
155 #define EVFILT_MARKER	0xf			/* placemarker for tailq */
156 
157 /*
158  * hint flag for in-kernel use - must not equal any existing note
159  */
160 #define NOTE_SUBMIT	0x01000000		/* initial knote submission */
161 
162 #define	KN_HASHSIZE		64		/* XXX should be tunable */
163 
164 /*
165  * Flag indicating hint is a signal.  Used by EVFILT_SIGNAL, and also
166  * shared by EVFILT_PROC  (all knotes attached to p->p_klist)
167  */
168 #define NOTE_SIGNAL	0x08000000
169 
170 /*
171  * = Event filter interface
172  *
173  * == .f_flags
174  *
175  * Defines properties of the event filter:
176  *
177  * - FILTEROP_ISFD      Each knote of this filter is associated
178  *                      with a file descriptor.
179  *
180  * - FILTEROP_MPSAFE    The kqueue subsystem can invoke .f_attach(),
181  *                      .f_detach(), .f_modify() and .f_process() without
182  *                      the kernel lock.
183  *
184  * == .f_attach()
185  *
186  * Attaches the knote to the object.
187  *
188  * == .f_detach()
189  *
190  * Detaches the knote from the object. The object must not use this knote
191  * for delivering events after this callback has returned.
192  *
193  * == .f_event()
194  *
195  * Notifies the filter about an event. Called through knote().
196  *
197  * == .f_modify()
198  *
199  * Modifies the knote with new state from the user.
200  *
201  * Returns non-zero if the knote has become active.
202  *
203  * == .f_process()
204  *
205  * Checks if the event is active and returns non-zero if the event should be
206  * returned to the user.
207  *
208  * If kev is non-NULL and the event is active, the callback should store
209  * the event's state in kev for delivery to the user.
210  *
211  * == Concurrency control
212  *
213  * The kqueue subsystem serializes calls of .f_attach(), .f_detach(),
214  * .f_modify() and .f_process().
215  */
216 
217 #define FILTEROP_ISFD		0x00000001	/* ident == filedescriptor */
218 #define FILTEROP_MPSAFE		0x00000002	/* safe without kernel lock */
219 
220 struct filterops {
221 	int	f_flags;
222 	int	(*f_attach)(struct knote *kn);
223 	void	(*f_detach)(struct knote *kn);
224 	int	(*f_event)(struct knote *kn, long hint);
225 	int	(*f_modify)(struct kevent *kev, struct knote *kn);
226 	int	(*f_process)(struct knote *kn, struct kevent *kev);
227 };
228 
229 /*
230  * Locking:
231  *	I	immutable after creation
232  *	o	object lock
233  *	q	kn_kq->kq_lock
234  */
235 struct knote {
236 	SLIST_ENTRY(knote)	kn_link;	/* for fd */
237 	SLIST_ENTRY(knote)	kn_selnext;	/* for struct selinfo */
238 	TAILQ_ENTRY(knote)	kn_tqe;
239 	struct			kqueue *kn_kq;	/* [I] which queue we are on */
240 	struct			kevent kn_kevent;
241 	int			kn_status;	/* [q] */
242 	int			kn_sfflags;	/* [o] saved filter flags */
243 	__int64_t		kn_sdata;	/* [o] saved data field */
244 	union {
245 		struct		file *p_fp;	/* file data pointer */
246 		struct		process *p_process;	/* process pointer */
247 	} kn_ptr;
248 	const struct		filterops *kn_fop;
249 	void			*kn_hook;	/* [o] */
250 	unsigned int		kn_pollid;	/* [I] */
251 
252 #define KN_ACTIVE	0x0001			/* event has been triggered */
253 #define KN_QUEUED	0x0002			/* event is on queue */
254 #define KN_DISABLED	0x0004			/* event is disabled */
255 #define KN_DETACHED	0x0008			/* knote is detached */
256 #define KN_PROCESSING	0x0010			/* knote is being processed */
257 #define KN_WAITING	0x0020			/* waiting on processing */
258 
259 #define kn_id		kn_kevent.ident		/* [I] */
260 #define kn_filter	kn_kevent.filter	/* [I] */
261 #define kn_flags	kn_kevent.flags		/* [o] */
262 #define kn_fflags	kn_kevent.fflags	/* [o] */
263 #define kn_data		kn_kevent.data		/* [o] */
264 #define kn_udata	kn_kevent.udata		/* [o] */
265 #define kn_fp		kn_ptr.p_fp		/* [o] */
266 };
267 
268 struct klistops {
269 	void	(*klo_assertlk)(void *);
270 	int	(*klo_lock)(void *);
271 	void	(*klo_unlock)(void *, int);
272 };
273 
274 struct kqueue_scan_state {
275 	struct kqueue	*kqs_kq;		/* kqueue of this scan */
276 	struct knote	 kqs_start;		/* start marker */
277 	struct knote	 kqs_end;		/* end marker */
278 	int		 kqs_nevent;		/* number of events collected */
279 	int		 kqs_queued;		/* if set, end marker is
280 						 * in queue */
281 };
282 
283 struct mutex;
284 struct proc;
285 struct rwlock;
286 struct timespec;
287 
288 extern const struct filterops dead_filtops;
289 
290 extern void	kqpoll_init(unsigned int);
291 extern void	kqpoll_done(unsigned int);
292 extern void	kqpoll_exit(void);
293 extern void	knote(struct klist *list, long hint);
294 extern void	knote_locked(struct klist *list, long hint);
295 extern void	knote_fdclose(struct proc *p, int fd);
296 extern void	knote_processexit(struct process *);
297 extern void	knote_processfork(struct process *, pid_t);
298 extern void	knote_assign(const struct kevent *, struct knote *);
299 extern void	knote_submit(struct knote *, struct kevent *);
300 extern void	kqueue_init(void);
301 extern void	kqueue_init_percpu(void);
302 extern int	kqueue_register(struct kqueue *kq, struct kevent *kev,
303 		    unsigned int pollid, struct proc *p);
304 extern int	kqueue_scan(struct kqueue_scan_state *, int, struct kevent *,
305 		    struct timespec *, struct proc *, int *);
306 extern void	kqueue_scan_setup(struct kqueue_scan_state *, struct kqueue *);
307 extern void	kqueue_scan_finish(struct kqueue_scan_state *);
308 extern int	filt_seltrue(struct knote *kn, long hint);
309 extern int	seltrue_kqfilter(dev_t, struct knote *);
310 extern void	klist_init(struct klist *, const struct klistops *, void *);
311 extern void	klist_init_mutex(struct klist *, struct mutex *);
312 extern void	klist_init_rwlock(struct klist *, struct rwlock *);
313 extern void	klist_free(struct klist *);
314 extern void	klist_insert(struct klist *, struct knote *);
315 extern void	klist_insert_locked(struct klist *, struct knote *);
316 extern void	klist_remove(struct klist *, struct knote *);
317 extern void	klist_remove_locked(struct klist *, struct knote *);
318 extern void	klist_invalidate(struct klist *);
319 
320 static inline int
knote_modify_fn(const struct kevent * kev,struct knote * kn,int (* f_event)(struct knote *,long))321 knote_modify_fn(const struct kevent *kev, struct knote *kn,
322     int (*f_event)(struct knote *, long))
323 {
324 	knote_assign(kev, kn);
325 	return ((*f_event)(kn, 0));
326 }
327 
328 static inline int
knote_modify(const struct kevent * kev,struct knote * kn)329 knote_modify(const struct kevent *kev, struct knote *kn)
330 {
331 	return (knote_modify_fn(kev, kn, kn->kn_fop->f_event));
332 }
333 
334 static inline int
knote_process_fn(struct knote * kn,struct kevent * kev,int (* f_event)(struct knote *,long))335 knote_process_fn(struct knote *kn, struct kevent *kev,
336     int (*f_event)(struct knote *, long))
337 {
338 	int active;
339 
340 	/*
341 	 * If called from kqueue_scan(), skip f_event
342 	 * when EV_ONESHOT is set, to preserve old behaviour.
343 	 */
344 	if (kev != NULL && (kn->kn_flags & EV_ONESHOT))
345 		active = 1;
346 	else
347 		active = (*f_event)(kn, 0);
348 	if (active)
349 		knote_submit(kn, kev);
350 	return (active);
351 }
352 
353 static inline int
knote_process(struct knote * kn,struct kevent * kev)354 knote_process(struct knote *kn, struct kevent *kev)
355 {
356 	return (knote_process_fn(kn, kev, kn->kn_fop->f_event));
357 }
358 
359 static inline int
klist_empty(struct klist * klist)360 klist_empty(struct klist *klist)
361 {
362 	return (SLIST_EMPTY(&klist->kl_list));
363 }
364 
365 #else	/* !_KERNEL */
366 
367 #include <sys/cdefs.h>
368 struct timespec;
369 
370 __BEGIN_DECLS
371 int	kqueue(void);
372 int	kqueue1(int flags);
373 int	kevent(int kq, const struct kevent *changelist, int nchanges,
374 		    struct kevent *eventlist, int nevents,
375 		    const struct timespec *timeout);
376 __END_DECLS
377 
378 #endif /* !_KERNEL */
379 
380 #endif /* !_SYS_EVENT_H_ */
381