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 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 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 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 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 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