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