xref: /netbsd-src/lib/libc/sys/kqueue.2 (revision 627f7eb200a4419d89b531d55fccd2ee3ffdcde0)
1.\"	$NetBSD: kqueue.2,v 1.53 2020/10/31 14:35:28 christos Exp $
2.\"
3.\" Copyright (c) 2000 Jonathan Lemon
4.\" All rights reserved.
5.\"
6.\" Copyright (c) 2001, 2002, 2003 The NetBSD Foundation, Inc.
7.\" All rights reserved.
8.\"
9.\" Portions of this documentation is derived from text contributed by
10.\" Luke Mewburn.
11.\"
12.\" Redistribution and use in source and binary forms, with or without
13.\" modification, are permitted provided that the following conditions
14.\" are met:
15.\" 1. Redistributions of source code must retain the above copyright
16.\"    notice, this list of conditions and the following disclaimer.
17.\" 2. Redistributions in binary form must reproduce the above copyright
18.\"    notice, this list of conditions and the following disclaimer in the
19.\"    documentation and/or other materials provided with the distribution.
20.\"
21.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND
22.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
25.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31.\" SUCH DAMAGE.
32.\"
33.\" $FreeBSD: src/lib/libc/sys/kqueue.2,v 1.22 2001/06/27 19:55:57 dd Exp $
34.\"
35.Dd October 30, 2020
36.Dt KQUEUE 2
37.Os
38.Sh NAME
39.Nm kqueue ,
40.Nm kqueue1 ,
41.Nm kevent ,
42.Nm EV_SET
43.Nd kernel event notification mechanism
44.Sh LIBRARY
45.Lb libc
46.Sh SYNOPSIS
47.In sys/event.h
48.In sys/time.h
49.Ft int
50.Fn kqueue "void"
51.Ft int
52.Fn kqueue1 "int flags"
53.Ft int
54.Fn kevent "int kq" "const struct kevent *changelist" "size_t nchanges" "struct kevent *eventlist" "size_t nevents" "const struct timespec *timeout"
55.Fn EV_SET "&kev" ident filter flags fflags data udata
56.Sh DESCRIPTION
57The
58.Fn kqueue
59system call
60provides a generic method of notifying the user when an event
61happens or a condition holds, based on the results of small
62pieces of kernel code termed filters.
63A kevent is identified by the (ident, filter) pair; there may only
64be one unique kevent per kqueue.
65.Pp
66The filter is executed upon the initial registration of a kevent
67in order to detect whether a preexisting condition is present, and is also
68executed whenever an event is passed to the filter for evaluation.
69If the filter determines that the condition should be reported,
70then the kevent is placed on the kqueue for the user to retrieve.
71.Pp
72The filter is also run when the user attempts to retrieve the kevent
73from the kqueue.
74If the filter indicates that the condition that triggered
75the event no longer holds, the kevent is removed from the kqueue and
76is not returned.
77.Pp
78Multiple events which trigger the filter do not result in multiple
79kevents being placed on the kqueue; instead, the filter will aggregate
80the events into a single struct kevent.
81Calling
82.Xr close 2
83on a file descriptor will remove any kevents that reference the descriptor.
84.Pp
85The
86.Fn kqueue
87system call
88creates a new kernel event queue and returns a descriptor.
89.Pp
90The
91.Fn kqueue1
92system call also allows to set the following
93.Fa flags
94on the returned file descriptor:
95.Bl -column O_NONBLOCK -offset indent
96.It Dv O_CLOEXEC
97Set the close on exec property.
98.It Dv O_NONBLOCK
99Set non-blocking I/O.
100.It Dv O_NOSIGPIPE
101Return
102.Er EPIPE
103instead of raising
104.Dv SIGPIPE .
105.El
106.Pp
107The queue is not inherited by a child created with
108.Xr fork 2 .
109.\" However, if
110.\" .Xr rfork 2
111.\" is called without the
112.\" .Dv RFFDG
113.\" flag, then the descriptor table is shared,
114.\" which will allow sharing of the kqueue between two processes.
115.Pp
116The
117.Fn kevent
118system call
119is used to register events with the queue, and return any pending
120events to the user.
121The
122.Fa changelist
123argument
124is a pointer to an array of
125.Va kevent
126structures, as defined in
127.In sys/event.h .
128All changes contained in the
129.Fa changelist
130are applied before any pending events are read from the queue.
131The
132.Fa nchanges
133argument
134gives the size of
135.Fa changelist .
136The
137.Fa eventlist
138argument
139is a pointer to an array of kevent structures.
140The
141.Fa nevents
142argument
143determines the size of
144.Fa eventlist .
145When
146.Fa nevents
147is zero,
148.Fn kevent
149will return immediately even if there is a
150.Fa timeout
151specified unlike
152.Xr select 2 .
153If
154.Fa timeout
155is a
156.No non- Ns Dv NULL
157pointer, it specifies a maximum interval to wait
158for an event, which will be interpreted as a
159.Li struct timespec .
160If
161.Fa timeout
162is a
163.Dv NULL
164pointer,
165.Fn kevent
166waits indefinitely.
167To effect a poll, the
168.Fa timeout
169argument should be
170.No non- Ns Dv NULL ,
171pointing to a zero-valued
172.Xr timespec 3
173structure.
174The same array may be used for the
175.Fa changelist
176and
177.Fa eventlist .
178.Pp
179The
180.Fn EV_SET
181macro is provided for ease of initializing a kevent structure.
182This macro does not evaluate its parameters multiple times.
183.Pp
184The
185.Va kevent
186structure is defined as:
187.Bd -literal
188struct kevent {
189	uintptr_t ident;	/* identifier for this event */
190	uint32_t  filter;	/* filter for event */
191	uint32_t  flags;	/* action flags for kqueue */
192	uint32_t  fflags;	/* filter flag value */
193	int64_t   data;		/* filter data value */
194	void     *udata;	/* opaque user data identifier */
195};
196.Ed
197.Pp
198The fields of
199.Fa struct kevent
200are:
201.Bl -tag -width "Fa filter" -offset indent
202.It ident
203Value used to identify this event.
204The exact interpretation is determined by the attached filter,
205but often is a file descriptor.
206.It Fa filter
207Identifies the kernel filter used to process this event.
208There are pre-defined system filters (which are described below), and
209other filters may be added by kernel subsystems as necessary.
210.It Fa flags
211Actions to perform on the event.
212.It Fa fflags
213Filter-specific flags.
214.It Fa data
215Filter-specific data value.
216.It Fa udata
217Opaque user-defined value passed through the kernel unchanged.
218.El
219.Pp
220The
221.Va flags
222field can contain the following values:
223.Bl -tag -width XXXEV_ONESHOT -offset indent
224.It Dv EV_ADD
225Adds the event to the kqueue.
226Re-adding an existing event will modify the parameters of the original
227event, and not result in a duplicate entry.
228Adding an event automatically enables it,
229unless overridden by the EV_DISABLE flag.
230.It Dv EV_ENABLE
231Permit
232.Fn kevent
233to return the event if it is triggered.
234.It Dv EV_DISABLE
235Disable the event so
236.Fn kevent
237will not return it.
238The filter itself is not disabled.
239.It Dv EV_DISPATCH
240Disable the event source immediately after delivery of an event.
241See
242.Dv EV_DISABLE
243above.
244.It Dv EV_DELETE
245Removes the event from the kqueue.
246Events which are attached to file descriptors are automatically deleted
247on the last close of the descriptor.
248.It Dv EV_RECEIPT
249This flag is useful for making bulk changes to a kqueue without draining
250any pending events.
251When passed as input, it forces
252.Dv EV_ERROR
253to always be returned.
254When a filter is successfully added the
255.Va data
256field will be zero.
257Note that if this flag is encountered and there is no remaining space in
258.Fa eventlist
259to hold the
260.Dv EV_ERROR
261event, then subsequent changes will not get processed.
262.It Dv EV_ONESHOT
263Causes the event to return only the first occurrence of the filter
264being triggered.
265After the user retrieves the event from the kqueue, it is deleted.
266.It Dv EV_CLEAR
267After the event is retrieved by the user, its state is reset.
268This is useful for filters which report state transitions
269instead of the current state.
270Note that some filters may automatically set this flag internally.
271.It Dv EV_EOF
272Filters may set this flag to indicate filter-specific EOF condition.
273.It Dv EV_ERROR
274See
275.Sx RETURN VALUES
276below.
277.El
278.Ss Filters
279Filters are identified by a number.
280There are two types of filters; pre-defined filters which
281are described below, and third-party filters that may be added with
282.Xr kfilter_register 9
283by kernel sub-systems, third-party device drivers, or loadable
284kernel modules.
285.Pp
286As a third-party filter is referenced by a well-known name instead
287of a statically assigned number, two
288.Xr ioctl 2 Ns s
289are supported on the file descriptor returned by
290.Fn kqueue
291to map a filter name to a filter number, and vice-versa (passing
292arguments in a structure described below):
293.Bl -tag -width KFILTER_BYFILTER -offset indent
294.It Dv KFILTER_BYFILTER
295Map
296.Va filter
297to
298.Va name ,
299which is of size
300.Va len .
301.It Dv KFILTER_BYNAME
302Map
303.Va name
304to
305.Va filter .
306.Va len
307is ignored.
308.El
309.Pp
310The following structure is used to pass arguments in and out of the
311.Xr ioctl 2 :
312.Bd -literal -offset indent
313struct kfilter_mapping {
314	char	 *name;		/* name to lookup or return */
315	size_t	 len;		/* length of name */
316	uint32_t filter;	/* filter to lookup or return */
317};
318.Ed
319.Pp
320The predefined system filters are listed below.
321Arguments may be passed to and from the filter via the
322.Va fflags
323and
324.Va data
325fields in the kevent structure.
326.Pp
327The predefined system filters are:
328.Bl -tag -width EVFILT_SIGNAL
329.It Dv EVFILT_READ
330Takes a descriptor as the identifier, and returns whenever
331there is data available to read.
332The behavior of the filter is slightly different depending
333on the descriptor type.
334.Bl -tag -width 2n
335.It Sockets
336Sockets which have previously been passed to
337.Xr listen 2
338return when there is an incoming connection pending.
339.Va data
340contains the size of the listen backlog (i.e., the number of
341connections ready to be accepted with
342.Xr accept 2 . )
343.Pp
344Other socket descriptors return when there is data to be read,
345subject to the
346.Dv SO_RCVLOWAT
347value of the socket buffer.
348This may be overridden with a per-filter low water mark at the
349time the filter is added by setting the
350NOTE_LOWAT
351flag in
352.Va fflags ,
353and specifying the new low water mark in
354.Va data .
355On return,
356.Va data
357contains the number of bytes in the socket buffer.
358.Pp
359If the read direction of the socket has shutdown, then the filter
360also sets EV_EOF in
361.Va flags ,
362and returns the socket error (if any) in
363.Va fflags .
364It is possible for EOF to be returned (indicating the connection is gone)
365while there is still data pending in the socket buffer.
366.It Vnodes
367Returns when the file pointer is not at the end of file.
368.Va data
369contains the offset from current position to end of file,
370and may be negative.
371.\" .Pp
372.\" This behavior is different from
373.\" .Xr poll 2 ,
374.\" where read events are triggered for regular files unconditionally.
375.\" This event can be triggered unconditionally by setting the
376.\" .Dv NOTE_FILE_POLL
377.\" flag in
378.\" .Va fflags .
379.It "Fifos, Pipes"
380Returns when there is data to read;
381.Va data
382contains the number of bytes available.
383.Pp
384When the last writer disconnects, the filter will set EV_EOF in
385.Va flags .
386This may be cleared by passing in EV_CLEAR, at which point the
387filter will resume waiting for data to become available before
388returning.
389.It "BPF devices"
390Returns when the BPF buffer is full, the BPF timeout has expired, or
391when the BPF has
392.Dq immediate mode
393enabled and there is any data to read;
394.Va data
395contains the number of bytes available.
396.El
397.It Dv EVFILT_WRITE
398Takes a descriptor as the identifier, and returns whenever
399it is possible to write to the descriptor.
400For sockets, pipes, fifos, and ttys,
401.Va data
402will contain the amount of space remaining in the write buffer.
403The filter will set EV_EOF when the reader disconnects, and for
404the fifo case, this may be cleared by use of EV_CLEAR.
405Note that this filter is not supported for vnodes.
406.Pp
407For sockets, the low water mark and socket error handling is
408identical to the EVFILT_READ case.
409.It Dv EVFILT_AIO
410This is not implemented in
411.Nx .
412.ig
413The sigevent portion of the AIO request is filled in, with
414.Va sigev_notify_kqueue
415containing the descriptor of the kqueue that the event should
416be attached to,
417.Va sigev_value
418containing the udata value, and
419.Va sigev_notify
420set to SIGEV_EVENT.
421When the aio_* function is called, the event will be registered
422with the specified kqueue, and the
423.Va ident
424argument set to the
425.Fa struct aiocb
426returned by the aio_* function.
427The filter returns under the same conditions as aio_error.
428.Pp
429Alternatively, a kevent structure may be initialized, with
430.Va ident
431containing the descriptor of the kqueue, and the
432address of the kevent structure placed in the
433.Va aio_lio_opcode
434field of the AIO request.
435However, this approach will not work on
436architectures with 64-bit pointers, and should be considered deprecated.
437..
438.It Dv EVFILT_VNODE
439Takes a file descriptor as the identifier and the events to watch for in
440.Va fflags ,
441and returns when one or more of the requested events occurs on the descriptor.
442The events to monitor are:
443.Bl -tag -width XXNOTE_RENAME
444.It Dv NOTE_DELETE
445.Xr unlink 2
446was called on the file referenced by the descriptor.
447.It Dv NOTE_WRITE
448A write occurred on the file referenced by the descriptor.
449.It Dv NOTE_EXTEND
450The file referenced by the descriptor was extended.
451.It Dv NOTE_ATTRIB
452The file referenced by the descriptor had its attributes changed.
453.It Dv NOTE_LINK
454The link count on the file changed.
455.It Dv NOTE_RENAME
456The file referenced by the descriptor was renamed.
457.It Dv NOTE_REVOKE
458Access to the file was revoked via
459.Xr revoke 2
460or the underlying file system was unmounted.
461.El
462.Pp
463On return,
464.Va fflags
465contains the events which triggered the filter.
466.It Dv EVFILT_PROC
467Takes the process ID to monitor as the identifier and the events to watch for
468in
469.Va fflags ,
470and returns when the process performs one or more of the requested events.
471If a process can normally see another process, it can attach an event to it.
472The events to monitor are:
473.Bl -tag -width XXNOTE_TRACKERR
474.It Dv NOTE_EXIT
475The process has exited.
476The exit code of the process is stored in
477.Va data .
478.It Dv NOTE_FORK
479The process has called
480.Xr fork 2 .
481.It Dv NOTE_EXEC
482The process has executed a new process via
483.Xr execve 2
484or similar call.
485.It Dv NOTE_TRACK
486Follow a process across
487.Xr fork 2
488calls.
489The parent process will return with NOTE_TRACK set in the
490.Va fflags
491field, while the child process will return with NOTE_CHILD set in
492.Va fflags
493and the parent PID in
494.Va data .
495.It Dv NOTE_TRACKERR
496This flag is returned if the system was unable to attach an event to
497the child process, usually due to resource limitations.
498.El
499.Pp
500On return,
501.Va fflags
502contains the events which triggered the filter.
503.It Dv EVFILT_SIGNAL
504Takes the signal number to monitor as the identifier and returns
505when the given signal is delivered to the current process.
506This coexists with the
507.Xr signal 3
508and
509.Xr sigaction 2
510facilities, and has a lower precedence.
511The filter will record
512all attempts to deliver a signal to a process, even if the signal has
513been marked as SIG_IGN.
514Event notification happens after normal signal delivery processing.
515.Va data
516returns the number of times the signal has occurred since the last call to
517.Fn kevent .
518This filter automatically sets the EV_CLEAR flag internally.
519.It Dv EVFILT_TIMER
520Establishes an arbitrary timer identified by
521.Va ident .
522When adding a timer,
523.Va data
524specifies the timeout period in milliseconds.
525The timer will be periodic unless EV_ONESHOT is specified.
526On return,
527.Va data
528contains the number of times the timeout has expired since the last call to
529.Fn kevent .
530This filter automatically sets the EV_CLEAR flag internally.
531.It Dv EVFILT_FS
532Establishes a file system monitor.
533Currently it only monitors file system mount and unmount actions.
534.It Dv EVFILT_USER
535Establishes a user event identified by
536.Va ident
537which is not associated with any kernel mechanism but is triggered by
538user level code.
539The lower 24 bits of the
540.Va fflags
541may be used for user defined flags and manipulated using the following:
542.Bl -tag -width "Dv NOTE_FFLAGSMASK"
543.It Dv NOTE_FFNOP
544Ignore the input
545.Va fflags .
546.It Dv NOTE_FFAND
547Bitwise AND
548.Va fflags .
549.It Dv NOTE_FFOR
550Bitwise OR
551.Va fflags .
552.It Dv NOTE_FFCOPY
553Copy
554.Va fflags .
555.It Dv NOTE_FFCTRLMASK
556Control mask for
557.Va fflags .
558.It Dv NOTE_FFLAGSMASK
559User defined flag mask for
560.Va fflags .
561.El
562.Pp
563A user event is triggered for output with the following:
564.Bl -tag -width "Dv NOTE_FFLAGSMASK"
565.It Dv NOTE_TRIGGER
566Cause the event to be triggered.
567.El
568.Pp
569On return,
570.Va fflags
571contains the users defined flags in the lower 24 bits.
572.El
573.Sh CANCELLATION BEHAVIOUR
574If
575.Fa nevents
576is non-zero, i.e., the function is potentially blocking, the call
577is a cancellation point.
578Otherwise, i.e., if
579.Fa nevents
580is zero, the call is not cancellable.
581Cancellation can only occur before any changes are made to the kqueue,
582or when the call was blocked and no changes to the queue were requested.
583.Sh RETURN VALUES
584The
585.Fn kqueue
586system call
587creates a new kernel event queue and returns a file descriptor.
588If there was an error creating the kernel event queue, a value of \-1 is
589returned and
590.Dv errno
591is set.
592.Pp
593The
594.Fn kevent
595system call
596returns the number of events placed in the
597.Fa eventlist ,
598up to the value given by
599.Fa nevents .
600If an error occurs while processing an element of the
601.Fa changelist
602and there is enough room in the
603.Fa eventlist ,
604then the event will be placed in the
605.Fa eventlist
606with
607.Dv EV_ERROR
608set in
609.Va flags
610and the system error in
611.Va data .
612Otherwise,
613.Dv \-1
614will be returned, and
615.Dv errno
616will be set to indicate the error condition.
617If the time limit expires, then
618.Fn kevent
619returns 0.
620.Sh EXAMPLES
621The following example program monitors a file (provided to it as the first
622argument) and prints information about some common events it receives
623notifications for:
624.Bd -literal -offset indent
625#include <sys/types.h>
626#include <sys/event.h>
627#include <sys/time.h>
628#include <stdio.h>
629#include <unistd.h>
630#include <stdlib.h>
631#include <fcntl.h>
632#include <err.h>
633
634int
635main(int argc, char *argv[])
636{
637        int fd, kq, nev;
638        struct kevent ev;
639        static const struct timespec tout = { 1, 0 };
640
641        if ((fd = open(argv[1], O_RDONLY)) == -1)
642                err(1, "Cannot open `%s'", argv[1]);
643
644        if ((kq = kqueue()) == -1)
645                err(1, "Cannot create kqueue");
646
647        EV_SET(&ev, fd, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_CLEAR,
648            NOTE_DELETE|NOTE_WRITE|NOTE_EXTEND|NOTE_ATTRIB|NOTE_LINK|
649            NOTE_RENAME|NOTE_REVOKE, 0, 0);
650        if (kevent(kq, &ev, 1, NULL, 0, &tout) == -1)
651                err(1, "kevent");
652        for (;;) {
653                nev = kevent(kq, NULL, 0, &ev, 1, &tout);
654                if (nev == -1)
655                        err(1, "kevent");
656                if (nev == 0)
657                        continue;
658                if (ev.fflags & NOTE_DELETE) {
659                        printf("deleted ");
660                        ev.fflags &= ~NOTE_DELETE;
661                }
662                if (ev.fflags & NOTE_WRITE) {
663                        printf("written ");
664                        ev.fflags &= ~NOTE_WRITE;
665                }
666                if (ev.fflags & NOTE_EXTEND) {
667                        printf("extended ");
668                        ev.fflags &= ~NOTE_EXTEND;
669                }
670                if (ev.fflags & NOTE_ATTRIB) {
671                        printf("chmod/chown/utimes ");
672                        ev.fflags &= ~NOTE_ATTRIB;
673                }
674                if (ev.fflags & NOTE_LINK) {
675                        printf("hardlinked ");
676                        ev.fflags &= ~NOTE_LINK;
677                }
678                if (ev.fflags & NOTE_RENAME) {
679                        printf("renamed ");
680                        ev.fflags &= ~NOTE_RENAME;
681                }
682                if (ev.fflags & NOTE_REVOKE) {
683                        printf("revoked ");
684                        ev.fflags &= ~NOTE_REVOKE;
685                }
686                printf("\\n");
687                if (ev.fflags)
688                        warnx("unknown event 0x%x\\n", ev.fflags);
689        }
690}
691.Ed
692.Sh ERRORS
693The
694.Fn kqueue
695function fails if:
696.Bl -tag -width Er
697.It Bq Er EMFILE
698The per-process descriptor table is full.
699.It Bq Er ENFILE
700The system file table is full.
701.It Bq Er ENOMEM
702The kernel failed to allocate enough memory for the kernel queue.
703.El
704.Pp
705The
706.Fn kevent
707function fails if:
708.Bl -tag -width Er
709.It Bq Er EACCES
710The process does not have permission to register a filter.
711.It Bq Er EBADF
712The specified descriptor is invalid.
713.It Bq Er EFAULT
714There was an error reading or writing the
715.Va kevent
716structure.
717.It Bq Er EINTR
718A signal was delivered before the timeout expired and before any
719events were placed on the kqueue for return.
720All changes contained in the
721.Fa changelist
722are applied before returning this error.
723.It Bq Er EINVAL
724The specified time limit or filter is invalid.
725.It Bq Er ENOENT
726The event could not be found to be modified or deleted.
727.It Bq Er ENOMEM
728No memory was available to register the event.
729.It Bq Er EOPNOTSUPP
730This type of file descriptor is not supported for
731.Fn kevent
732operations.
733.It Bq Er ESRCH
734The specified process to attach to does not exist.
735.El
736.Sh SEE ALSO
737.\" .Xr aio_error 2 ,
738.\" .Xr aio_read 2 ,
739.\" .Xr aio_return 2 ,
740.Xr fork 2 ,
741.Xr ioctl 2 ,
742.Xr listen 2 ,
743.Xr poll 2 ,
744.Xr read 2 ,
745.Xr select 2 ,
746.Xr sigaction 2 ,
747.Xr unlink 2 ,
748.Xr write 2 ,
749.Xr signal 3 ,
750.Xr timespec 3 ,
751.Xr kfilter_register 9 ,
752.Xr knote 9
753.Rs
754.%A Jonathan Lemon
755.%T "Kqueue: A Generic and Scalable Event Notification Facility"
756.%I USENIX Association
757.%B Proceedings of the FREENIX Track: 2001 USENIX Annual Technical Conference
758.%D June 25-30, 2001
759.%U http://www.usenix.org/event/usenix01/freenix01/full_papers/lemon/lemon.pdf
760.Re
761.Sh HISTORY
762The
763.Fn kqueue
764and
765.Fn kevent
766functions first appeared in
767.Fx 4.1 ,
768and then in
769.Nx 2.0 .
770The
771.Fn kqueue1
772function first appeared in
773.Nx 6.0 .
774.Pp
775The
776.Fn EV_SET
777macro was protected from evaluating multiple times the first argument in
778.Nx 8.0 .
779.Pp
780The
781.Va udata
782type was changed from intptr_t to void * in
783.Nx 10.0 .
784