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