Sat Oct 31 01:08:32 2020 UTC ()
PR/55663: Ruslan Nikolaev: Add support for EVFILT_USER in kqueue(2)


(christos)
diff -r1.50 -r1.51 src/lib/libc/sys/kqueue.2
diff -r1.107 -r1.108 src/sys/kern/kern_event.c
diff -r1.38 -r1.39 src/sys/sys/event.h
diff -r1.8 -r1.9 src/tests/lib/libc/sys/t_kevent.c

cvs diff -r1.50 -r1.51 src/lib/libc/sys/kqueue.2 (expand / switch to unified diff)

--- src/lib/libc/sys/kqueue.2 2019/12/23 01:46:09 1.50
+++ src/lib/libc/sys/kqueue.2 2020/10/31 01:08:31 1.51
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1.\" $NetBSD: kqueue.2,v 1.50 2019/12/23 01:46:09 kamil Exp $ 1.\" $NetBSD: kqueue.2,v 1.51 2020/10/31 01:08:31 christos Exp $
2.\" 2.\"
3.\" Copyright (c) 2000 Jonathan Lemon 3.\" Copyright (c) 2000 Jonathan Lemon
4.\" All rights reserved. 4.\" All rights reserved.
5.\" 5.\"
6.\" Copyright (c) 2001, 2002, 2003 The NetBSD Foundation, Inc. 6.\" Copyright (c) 2001, 2002, 2003 The NetBSD Foundation, Inc.
7.\" All rights reserved. 7.\" All rights reserved.
8.\" 8.\"
9.\" Portions of this documentation is derived from text contributed by 9.\" Portions of this documentation is derived from text contributed by
10.\" Luke Mewburn. 10.\" Luke Mewburn.
11.\" 11.\"
12.\" Redistribution and use in source and binary forms, with or without 12.\" Redistribution and use in source and binary forms, with or without
13.\" modification, are permitted provided that the following conditions 13.\" modification, are permitted provided that the following conditions
14.\" are met: 14.\" are met:
@@ -22,185 +22,208 @@ @@ -22,185 +22,208 @@
22.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 24.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
25.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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 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 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 30.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31.\" SUCH DAMAGE. 31.\" SUCH DAMAGE.
32.\" 32.\"
33.\" $FreeBSD: src/lib/libc/sys/kqueue.2,v 1.22 2001/06/27 19:55:57 dd Exp $ 33.\" $FreeBSD: src/lib/libc/sys/kqueue.2,v 1.22 2001/06/27 19:55:57 dd Exp $
34.\" 34.\"
35.Dd December 22, 2019 35.Dd October 30, 2020
36.Dt KQUEUE 2 36.Dt KQUEUE 2
37.Os 37.Os
38.Sh NAME 38.Sh NAME
39.Nm kqueue , 39.Nm kqueue ,
40.Nm kqueue1 , 40.Nm kqueue1 ,
41.Nm kevent , 41.Nm kevent ,
42.Nm EV_SET 42.Nm EV_SET
43.Nd kernel event notification mechanism 43.Nd kernel event notification mechanism
44.Sh LIBRARY 44.Sh LIBRARY
45.Lb libc 45.Lb libc
46.Sh SYNOPSIS 46.Sh SYNOPSIS
47.In sys/event.h 47.In sys/event.h
48.In sys/time.h 48.In sys/time.h
49.Ft int 49.Ft int
50.Fn kqueue "void" 50.Fn kqueue "void"
51.Ft int 51.Ft int
52.Fn kqueue1 "int flags" 52.Fn kqueue1 "int flags"
53.Ft int 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" 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 55.Fn EV_SET "&kev" ident filter flags fflags data udata
56.Sh DESCRIPTION 56.Sh DESCRIPTION
 57The
57.Fn kqueue 58.Fn kqueue
 59system call
58provides a generic method of notifying the user when an event 60provides a generic method of notifying the user when an event
59happens or a condition holds, based on the results of small 61happens or a condition holds, based on the results of small
60pieces of kernel code termed filters. 62pieces of kernel code termed filters.
61A kevent is identified by the (ident, filter) pair; there may only 63A kevent is identified by the (ident, filter) pair; there may only
62be one unique kevent per kqueue. 64be one unique kevent per kqueue.
63.Pp 65.Pp
64The filter is executed upon the initial registration of a kevent 66The filter is executed upon the initial registration of a kevent
65in order to detect whether a preexisting condition is present, and is also 67in order to detect whether a preexisting condition is present, and is also
66executed whenever an event is passed to the filter for evaluation. 68executed whenever an event is passed to the filter for evaluation.
67If the filter determines that the condition should be reported, 69If the filter determines that the condition should be reported,
68then the kevent is placed on the kqueue for the user to retrieve. 70then the kevent is placed on the kqueue for the user to retrieve.
69.Pp 71.Pp
70The filter is also run when the user attempts to retrieve the kevent 72The filter is also run when the user attempts to retrieve the kevent
71from the kqueue. 73from the kqueue.
72If the filter indicates that the condition that triggered 74If the filter indicates that the condition that triggered
73the event no longer holds, the kevent is removed from the kqueue and 75the event no longer holds, the kevent is removed from the kqueue and
74is not returned. 76is not returned.
75.Pp 77.Pp
76Multiple events which trigger the filter do not result in multiple 78Multiple events which trigger the filter do not result in multiple
77kevents being placed on the kqueue; instead, the filter will aggregate 79kevents being placed on the kqueue; instead, the filter will aggregate
78the events into a single struct kevent. 80the events into a single struct kevent.
79Calling 81Calling
80.Xr close 2 82.Xr close 2
81on a file descriptor will remove any kevents that reference the descriptor. 83on a file descriptor will remove any kevents that reference the descriptor.
82.Pp 84.Pp
 85The
83.Fn kqueue 86.Fn kqueue
 87system call
84creates a new kernel event queue and returns a descriptor. 88creates a new kernel event queue and returns a descriptor.
85.Pp 89.Pp
86The 90The
87.Fn kqueue1 91.Fn kqueue1
88function also allows to set the following 92system call also allows to set the following
89.Fa flags 93.Fa flags
90on the returned file descriptor: 94on the returned file descriptor:
91.Bl -column O_NONBLOCK -offset indent 95.Bl -column O_NONBLOCK -offset indent
92.It Dv O_CLOEXEC 96.It Dv O_CLOEXEC
93Set the close on exec property. 97Set the close on exec property.
94.It Dv O_NONBLOCK 98.It Dv O_NONBLOCK
95Set non-blocking I/O. 99Set non-blocking I/O.
96.It Dv O_NOSIGPIPE 100.It Dv O_NOSIGPIPE
97Return 101Return
98.Er EPIPE 102.Er EPIPE
99instead of raising 103instead of raising
100.Dv SIGPIPE . 104.Dv SIGPIPE .
101.El 105.El
102.Pp 106.Pp
103The queue is not inherited by a child created with 107The queue is not inherited by a child created with
104.Xr fork 2 . 108.Xr fork 2 .
105.\" However, if 109.\" However, if
106.\" .Xr rfork 2 110.\" .Xr rfork 2
107.\" is called without the 111.\" is called without the
108.\" .Dv RFFDG 112.\" .Dv RFFDG
109.\" flag, then the descriptor table is shared, 113.\" flag, then the descriptor table is shared,
110.\" which will allow sharing of the kqueue between two processes. 114.\" which will allow sharing of the kqueue between two processes.
111.Pp 115.Pp
 116The
112.Fn kevent 117.Fn kevent
 118system call
113is used to register events with the queue, and return any pending 119is used to register events with the queue, and return any pending
114events to the user. 120events to the user.
 121The
115.Fa changelist 122.Fa changelist
 123argument
116is a pointer to an array of 124is a pointer to an array of
117.Va kevent 125.Va kevent
118structures, as defined in 126structures, as defined in
119.In sys/event.h . 127.In sys/event.h .
120All changes contained in the 128All changes contained in the
121.Fa changelist 129.Fa changelist
122are applied before any pending events are read from the queue. 130are applied before any pending events are read from the queue.
 131The
123.Fa nchanges 132.Fa nchanges
 133argument
124gives the size of 134gives the size of
125.Fa changelist . 135.Fa changelist .
 136The
126.Fa eventlist 137.Fa eventlist
 138argument
127is a pointer to an array of kevent structures. 139is a pointer to an array of kevent structures.
 140The
128.Fa nevents 141.Fa nevents
 142argument
129determines the size of 143determines the size of
130.Fa eventlist . 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 .
131If 153If
132.Fa timeout 154.Fa timeout
133is a 155is a
134.No non- Ns Dv NULL 156.No non- Ns Dv NULL
135pointer, it specifies a maximum interval to wait 157pointer, it specifies a maximum interval to wait
136for an event, which will be interpreted as a 158for an event, which will be interpreted as a
137.Li struct timespec . 159.Li struct timespec .
138If 160If
139.Fa timeout 161.Fa timeout
140is a 162is a
141.Dv NULL 163.Dv NULL
142pointer, 164pointer,
143.Fn kevent 165.Fn kevent
144waits indefinitely. 166waits indefinitely.
145To effect a poll, the 167To effect a poll, the
146.Fa timeout 168.Fa timeout
147argument should be 169argument should be
148.No non- Ns Dv NULL , 170.No non- Ns Dv NULL ,
149pointing to a zero-valued 171pointing to a zero-valued
150.Xr timespec 3 172.Xr timespec 3
151structure. 173structure.
152The same array may be used for the 174The same array may be used for the
153.Fa changelist 175.Fa changelist
154and 176and
155.Fa eventlist . 177.Fa eventlist .
156.Pp 178.Pp
 179The
157.Fn EV_SET 180.Fn EV_SET
158is a macro which is provided for ease of initializing a kevent structure. 181macro is provided for ease of initializing a kevent structure.
159This macro does not evaluate its parameters multiple times. 182This macro does not evaluate its parameters multiple times.
160.Pp 183.Pp
161The 184The
162.Va kevent 185.Va kevent
163structure is defined as: 186structure is defined as:
164.Bd -literal 187.Bd -literal
165struct kevent { 188struct kevent {
166 uintptr_t ident; /* identifier for this event */ 189 uintptr_t ident; /* identifier for this event */
167 uint32_t filter; /* filter for event */ 190 uint32_t filter; /* filter for event */
168 uint32_t flags; /* action flags for kqueue */ 191 uint32_t flags; /* action flags for kqueue */
169 uint32_t fflags; /* filter flag value */ 192 uint32_t fflags; /* filter flag value */
170 int64_t data; /* filter data value */ 193 int64_t data; /* filter data value */
171 void *udata; /* opaque user data identifier */ 194 void *udata; /* opaque user data identifier */
172}; 195};
173.Ed 196.Ed
174.Pp 197.Pp
175The fields of 198The fields of
176.Fa struct kevent 199.Fa struct kevent
177are: 200are:
178.Bl -tag -width XXXfilter -offset indent 201.Bl -tag -width "Fa filter" -offset indent
179.It ident 202.It ident
180Value used to identify this event. 203Value used to identify this event.
181The exact interpretation is determined by the attached filter, 204The exact interpretation is determined by the attached filter,
182but often is a file descriptor. 205but often is a file descriptor.
183.It filter 206.It Fa filter
184Identifies the kernel filter used to process this event. 207Identifies the kernel filter used to process this event.
185There are pre-defined system filters (which are described below), and 208There are pre-defined system filters (which are described below), and
186other filters may be added by kernel subsystems as necessary. 209other filters may be added by kernel subsystems as necessary.
187.It flags 210.It Fa flags
188Actions to perform on the event. 211Actions to perform on the event.
189.It fflags 212.It Fa fflags
190Filter-specific flags. 213Filter-specific flags.
191.It data 214.It Fa data
192Filter-specific data value. 215Filter-specific data value.
193.It udata 216.It Fa udata
194Opaque user-defined value passed through the kernel unchanged. 217Opaque user-defined value passed through the kernel unchanged.
195.El 218.El
196.Pp 219.Pp
197The 220The
198.Va flags 221.Va flags
199field can contain the following values: 222field can contain the following values:
200.Bl -tag -width XXXEV_ONESHOT -offset indent 223.Bl -tag -width XXXEV_ONESHOT -offset indent
201.It Dv EV_ADD 224.It Dv EV_ADD
202Adds the event to the kqueue. 225Adds the event to the kqueue.
203Re-adding an existing event will modify the parameters of the original 226Re-adding an existing event will modify the parameters of the original
204event, and not result in a duplicate entry. 227event, and not result in a duplicate entry.
205Adding an event automatically enables it, 228Adding an event automatically enables it,
206unless overridden by the EV_DISABLE flag. 229unless overridden by the EV_DISABLE flag.
@@ -221,26 +244,31 @@ above. @@ -221,26 +244,31 @@ above.
221.It Dv EV_DELETE 244.It Dv EV_DELETE
222Removes the event from the kqueue. 245Removes the event from the kqueue.
223Events which are attached to file descriptors are automatically deleted 246Events which are attached to file descriptors are automatically deleted
224on the last close of the descriptor. 247on the last close of the descriptor.
225.It Dv EV_RECEIPT 248.It Dv EV_RECEIPT
226This flag is useful for making bulk changes to a kqueue without draining 249This flag is useful for making bulk changes to a kqueue without draining
227any pending events. 250any pending events.
228When passed as input, it forces 251When passed as input, it forces
229.Dv EV_ERROR 252.Dv EV_ERROR
230to always be returned. 253to always be returned.
231When a filter is successfully added the 254When a filter is successfully added the
232.Va data 255.Va data
233field will be zero. 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.
234.It Dv EV_ONESHOT 262.It Dv EV_ONESHOT
235Causes the event to return only the first occurrence of the filter 263Causes the event to return only the first occurrence of the filter
236being triggered. 264being triggered.
237After the user retrieves the event from the kqueue, it is deleted. 265After the user retrieves the event from the kqueue, it is deleted.
238.It Dv EV_CLEAR 266.It Dv EV_CLEAR
239After the event is retrieved by the user, its state is reset. 267After the event is retrieved by the user, its state is reset.
240This is useful for filters which report state transitions 268This is useful for filters which report state transitions
241instead of the current state. 269instead of the current state.
242Note that some filters may automatically set this flag internally. 270Note that some filters may automatically set this flag internally.
243.It Dv EV_EOF 271.It Dv EV_EOF
244Filters may set this flag to indicate filter-specific EOF condition. 272Filters may set this flag to indicate filter-specific EOF condition.
245.It Dv EV_ERROR 273.It Dv EV_ERROR
246See 274See
@@ -279,26 +307,27 @@ to @@ -279,26 +307,27 @@ to
279is ignored. 307is ignored.
280.El 308.El
281.Pp 309.Pp
282The following structure is used to pass arguments in and out of the 310The following structure is used to pass arguments in and out of the
283.Xr ioctl 2 : 311.Xr ioctl 2 :
284.Bd -literal -offset indent 312.Bd -literal -offset indent
285struct kfilter_mapping { 313struct kfilter_mapping {
286 char *name; /* name to lookup or return */ 314 char *name; /* name to lookup or return */
287 size_t len; /* length of name */ 315 size_t len; /* length of name */
288 uint32_t filter; /* filter to lookup or return */ 316 uint32_t filter; /* filter to lookup or return */
289}; 317};
290.Ed 318.Ed
291.Pp 319.Pp
 320The predefined system filters are listed below.
292Arguments may be passed to and from the filter via the 321Arguments may be passed to and from the filter via the
293.Va fflags 322.Va fflags
294and 323and
295.Va data 324.Va data
296fields in the kevent structure. 325fields in the kevent structure.
297.Pp 326.Pp
298The predefined system filters are: 327The predefined system filters are:
299.Bl -tag -width EVFILT_SIGNAL 328.Bl -tag -width EVFILT_SIGNAL
300.It Dv EVFILT_READ 329.It Dv EVFILT_READ
301Takes a descriptor as the identifier, and returns whenever 330Takes a descriptor as the identifier, and returns whenever
302there is data available to read. 331there is data available to read.
303The behavior of the filter is slightly different depending 332The behavior of the filter is slightly different depending
304on the descriptor type. 333on the descriptor type.
@@ -329,36 +358,50 @@ contains the number of bytes in the sock @@ -329,36 +358,50 @@ contains the number of bytes in the sock
329.Pp 358.Pp
330If the read direction of the socket has shutdown, then the filter 359If the read direction of the socket has shutdown, then the filter
331also sets EV_EOF in 360also sets EV_EOF in
332.Va flags , 361.Va flags ,
333and returns the socket error (if any) in 362and returns the socket error (if any) in
334.Va fflags . 363.Va fflags .
335It is possible for EOF to be returned (indicating the connection is gone) 364It is possible for EOF to be returned (indicating the connection is gone)
336while there is still data pending in the socket buffer. 365while there is still data pending in the socket buffer.
337.It Vnodes 366.It Vnodes
338Returns when the file pointer is not at the end of file. 367Returns when the file pointer is not at the end of file.
339.Va data 368.Va data
340contains the offset from current position to end of file, 369contains the offset from current position to end of file,
341and may be negative. 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 .
342.It "Fifos, Pipes" 379.It "Fifos, Pipes"
343Returns when there is data to read; 380Returns when there is data to read;
344.Va data 381.Va data
345contains the number of bytes available. 382contains the number of bytes available.
346.Pp 383.Pp
347When the last writer disconnects, the filter will set EV_EOF in 384When the last writer disconnects, the filter will set EV_EOF in
348.Va flags . 385.Va flags .
349This may be cleared by passing in EV_CLEAR, at which point the 386This may be cleared by passing in EV_CLEAR, at which point the
350filter will resume waiting for data to become available before 387filter will resume waiting for data to become available before
351returning. 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
352.El 395.El
353.It Dv EVFILT_WRITE 396.It Dv EVFILT_WRITE
354Takes a descriptor as the identifier, and returns whenever 397Takes a descriptor as the identifier, and returns whenever
355it is possible to write to the descriptor. 398it is possible to write to the descriptor.
356For sockets, pipes, fifos, and ttys, 399For sockets, pipes, fifos, and ttys,
357.Va data 400.Va data
358will contain the amount of space remaining in the write buffer. 401will contain the amount of space remaining in the write buffer.
359The filter will set EV_EOF when the reader disconnects, and for 402The filter will set EV_EOF when the reader disconnects, and for
360the fifo case, this may be cleared by use of EV_CLEAR. 403the fifo case, this may be cleared by use of EV_CLEAR.
361Note that this filter is not supported for vnodes. 404Note that this filter is not supported for vnodes.
362.Pp 405.Pp
363For sockets, the low water mark and socket error handling is 406For sockets, the low water mark and socket error handling is
364identical to the EVFILT_READ case. 407identical to the EVFILT_READ case.
@@ -477,36 +520,88 @@ Establishes an arbitrary timer identifie @@ -477,36 +520,88 @@ Establishes an arbitrary timer identifie
477.Va ident . 520.Va ident .
478When adding a timer, 521When adding a timer,
479.Va data 522.Va data
480specifies the timeout period in milliseconds. 523specifies the timeout period in milliseconds.
481The timer will be periodic unless EV_ONESHOT is specified. 524The timer will be periodic unless EV_ONESHOT is specified.
482On return, 525On return,
483.Va data 526.Va data
484contains the number of times the timeout has expired since the last call to 527contains the number of times the timeout has expired since the last call to
485.Fn kevent . 528.Fn kevent .
486This filter automatically sets the EV_CLEAR flag internally. 529This filter automatically sets the EV_CLEAR flag internally.
487.It Dv EVFILT_FS 530.It Dv EVFILT_FS
488Establishes a file system monitor. 531Establishes a file system monitor.
489Currently it only monitors file system mount and unmount actions. 532Currently it only monitors file system mount and unmount actions.
 533.It Dv EVFILT_USER
 534Establishes a user event identified by
 535.Va ident
 536which is not associated with any kernel mechanism but is triggered by
 537user level code.
 538The lower 24 bits of the
 539.Va fflags
 540may be used for user defined flags and manipulated using the following:
 541.Bl -tag -width "Dv NOTE_FFLAGSMASK"
 542.It Dv NOTE_FFNOP
 543Ignore the input
 544.Va fflags .
 545.It Dv NOTE_FFAND
 546Bitwise AND
 547.Va fflags .
 548.It Dv NOTE_FFOR
 549Bitwise OR
 550.Va fflags .
 551.It Dv NOTE_FFCOPY
 552Copy
 553.Va fflags .
 554.It Dv NOTE_FFCTRLMASK
 555Control mask for
 556.Va fflags .
 557.It Dv NOTE_FFLAGSMASK
 558User defined flag mask for
 559.Va fflags .
 560.El
 561.Pp
 562A user event is triggered for output with the following:
 563.Bl -tag -width "Dv NOTE_FFLAGSMASK"
 564.It Dv NOTE_TRIGGER
 565Cause the event to be triggered.
 566.El
 567.Pp
 568On return,
 569.Va fflags
 570contains the users defined flags in the lower 24 bits.
490.El 571.El
 572.Sh CANCELLATION BEHAVIOUR
 573If
 574.Fa nevents
 575is non-zero, i.e., the function is potentially blocking, the call
 576is a cancellation point.
 577Otherwise, i.e., if
 578.Fa nevents
 579is zero, the call is not cancellable.
 580Cancellation can only occur before any changes are made to the kqueue,
 581or when the call was blocked and no changes to the queue were requested.
491.Sh RETURN VALUES 582.Sh RETURN VALUES
 583The
492.Fn kqueue 584.Fn kqueue
 585system call
493creates a new kernel event queue and returns a file descriptor. 586creates a new kernel event queue and returns a file descriptor.
494If there was an error creating the kernel event queue, a value of \-1 is 587If there was an error creating the kernel event queue, a value of \-1 is
495returned and 588returned and
496.Dv errno 589.Dv errno
497is set. 590is set.
498.Pp 591.Pp
 592The
499.Fn kevent 593.Fn kevent
 594system call
500returns the number of events placed in the 595returns the number of events placed in the
501.Fa eventlist , 596.Fa eventlist ,
502up to the value given by 597up to the value given by
503.Fa nevents . 598.Fa nevents .
504If an error occurs while processing an element of the 599If an error occurs while processing an element of the
505.Fa changelist 600.Fa changelist
506and there is enough room in the 601and there is enough room in the
507.Fa eventlist , 602.Fa eventlist ,
508then the event will be placed in the 603then the event will be placed in the
509.Fa eventlist 604.Fa eventlist
510with 605with
511.Dv EV_ERROR 606.Dv EV_ERROR
512set in 607set in

cvs diff -r1.107 -r1.108 src/sys/kern/kern_event.c (expand / switch to unified diff)

--- src/sys/kern/kern_event.c 2020/05/23 23:42:43 1.107
+++ src/sys/kern/kern_event.c 2020/10/31 01:08:32 1.108
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: kern_event.c,v 1.107 2020/05/23 23:42:43 ad Exp $ */ 1/* $NetBSD: kern_event.c,v 1.108 2020/10/31 01:08:32 christos Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc. 4 * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to The NetBSD Foundation 7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Andrew Doran. 8 * by Andrew Doran.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
@@ -21,26 +21,27 @@ @@ -21,26 +21,27 @@
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE. 29 * POSSIBILITY OF SUCH DAMAGE.
30 */ 30 */
31 31
32/*- 32/*-
33 * Copyright (c) 1999,2000,2001 Jonathan Lemon <jlemon@FreeBSD.org> 33 * Copyright (c) 1999,2000,2001 Jonathan Lemon <jlemon@FreeBSD.org>
 34 * Copyright (c) 2009 Apple, Inc
34 * All rights reserved. 35 * All rights reserved.
35 * 36 *
36 * Redistribution and use in source and binary forms, with or without 37 * Redistribution and use in source and binary forms, with or without
37 * modification, are permitted provided that the following conditions 38 * modification, are permitted provided that the following conditions
38 * are met: 39 * are met:
39 * 1. Redistributions of source code must retain the above copyright 40 * 1. Redistributions of source code must retain the above copyright
40 * notice, this list of conditions and the following disclaimer. 41 * notice, this list of conditions and the following disclaimer.
41 * 2. Redistributions in binary form must reproduce the above copyright 42 * 2. Redistributions in binary form must reproduce the above copyright
42 * notice, this list of conditions and the following disclaimer in the 43 * notice, this list of conditions and the following disclaimer in the
43 * documentation and/or other materials provided with the distribution. 44 * documentation and/or other materials provided with the distribution.
44 * 45 *
45 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 46 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
46 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 47 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
@@ -48,27 +49,27 @@ @@ -48,27 +49,27 @@
48 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 49 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
49 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 50 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
50 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 51 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
51 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 52 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
52 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 53 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
53 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 54 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
54 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 55 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
55 * SUCH DAMAGE. 56 * SUCH DAMAGE.
56 * 57 *
57 * FreeBSD: src/sys/kern/kern_event.c,v 1.27 2001/07/05 17:10:44 rwatson Exp 58 * FreeBSD: src/sys/kern/kern_event.c,v 1.27 2001/07/05 17:10:44 rwatson Exp
58 */ 59 */
59 60
60#include <sys/cdefs.h> 61#include <sys/cdefs.h>
61__KERNEL_RCSID(0, "$NetBSD: kern_event.c,v 1.107 2020/05/23 23:42:43 ad Exp $"); 62__KERNEL_RCSID(0, "$NetBSD: kern_event.c,v 1.108 2020/10/31 01:08:32 christos Exp $");
62 63
63#include <sys/param.h> 64#include <sys/param.h>
64#include <sys/systm.h> 65#include <sys/systm.h>
65#include <sys/kernel.h> 66#include <sys/kernel.h>
66#include <sys/wait.h> 67#include <sys/wait.h>
67#include <sys/proc.h> 68#include <sys/proc.h>
68#include <sys/file.h> 69#include <sys/file.h>
69#include <sys/select.h> 70#include <sys/select.h>
70#include <sys/queue.h> 71#include <sys/queue.h>
71#include <sys/event.h> 72#include <sys/event.h>
72#include <sys/eventvar.h> 73#include <sys/eventvar.h>
73#include <sys/poll.h> 74#include <sys/poll.h>
74#include <sys/kmem.h> 75#include <sys/kmem.h>
@@ -99,26 +100,30 @@ static void knote_activate(struct knote  @@ -99,26 +100,30 @@ static void knote_activate(struct knote
99static void filt_kqdetach(struct knote *); 100static void filt_kqdetach(struct knote *);
100static int filt_kqueue(struct knote *, long hint); 101static int filt_kqueue(struct knote *, long hint);
101static int filt_procattach(struct knote *); 102static int filt_procattach(struct knote *);
102static void filt_procdetach(struct knote *); 103static void filt_procdetach(struct knote *);
103static int filt_proc(struct knote *, long hint); 104static int filt_proc(struct knote *, long hint);
104static int filt_fileattach(struct knote *); 105static int filt_fileattach(struct knote *);
105static void filt_timerexpire(void *x); 106static void filt_timerexpire(void *x);
106static int filt_timerattach(struct knote *); 107static int filt_timerattach(struct knote *);
107static void filt_timerdetach(struct knote *); 108static void filt_timerdetach(struct knote *);
108static int filt_timer(struct knote *, long hint); 109static int filt_timer(struct knote *, long hint);
109static int filt_fsattach(struct knote *kn); 110static int filt_fsattach(struct knote *kn);
110static void filt_fsdetach(struct knote *kn); 111static void filt_fsdetach(struct knote *kn);
111static int filt_fs(struct knote *kn, long hint); 112static int filt_fs(struct knote *kn, long hint);
 113static int filt_userattach(struct knote *);
 114static void filt_userdetach(struct knote *);
 115static int filt_user(struct knote *, long hint);
 116static void filt_usertouch(struct knote *, struct kevent *, long type);
112 117
113static const struct fileops kqueueops = { 118static const struct fileops kqueueops = {
114 .fo_name = "kqueue", 119 .fo_name = "kqueue",
115 .fo_read = (void *)enxio, 120 .fo_read = (void *)enxio,
116 .fo_write = (void *)enxio, 121 .fo_write = (void *)enxio,
117 .fo_ioctl = kqueue_ioctl, 122 .fo_ioctl = kqueue_ioctl,
118 .fo_fcntl = kqueue_fcntl, 123 .fo_fcntl = kqueue_fcntl,
119 .fo_poll = kqueue_poll, 124 .fo_poll = kqueue_poll,
120 .fo_stat = kqueue_stat, 125 .fo_stat = kqueue_stat,
121 .fo_close = kqueue_close, 126 .fo_close = kqueue_close,
122 .fo_kqfilter = kqueue_kqfilter, 127 .fo_kqfilter = kqueue_kqfilter,
123 .fo_restart = fnullop_restart, 128 .fo_restart = fnullop_restart,
124}; 129};
@@ -148,26 +153,34 @@ static const struct filterops timer_filt @@ -148,26 +153,34 @@ static const struct filterops timer_filt
148 .f_isfd = 0, 153 .f_isfd = 0,
149 .f_attach = filt_timerattach, 154 .f_attach = filt_timerattach,
150 .f_detach = filt_timerdetach, 155 .f_detach = filt_timerdetach,
151 .f_event = filt_timer, 156 .f_event = filt_timer,
152}; 157};
153 158
154static const struct filterops fs_filtops = { 159static const struct filterops fs_filtops = {
155 .f_isfd = 0, 160 .f_isfd = 0,
156 .f_attach = filt_fsattach, 161 .f_attach = filt_fsattach,
157 .f_detach = filt_fsdetach, 162 .f_detach = filt_fsdetach,
158 .f_event = filt_fs, 163 .f_event = filt_fs,
159}; 164};
160 165
 166static const struct filterops user_filtops = {
 167 .f_isfd = 0,
 168 .f_attach = filt_userattach,
 169 .f_detach = filt_userdetach,
 170 .f_event = filt_user,
 171 .f_touch = filt_usertouch,
 172};
 173
161static u_int kq_ncallouts = 0; 174static u_int kq_ncallouts = 0;
162static int kq_calloutmax = (4 * 1024); 175static int kq_calloutmax = (4 * 1024);
163 176
164#define KN_HASHSIZE 64 /* XXX should be tunable */ 177#define KN_HASHSIZE 64 /* XXX should be tunable */
165#define KN_HASH(val, mask) (((val) ^ (val >> 8)) & (mask)) 178#define KN_HASH(val, mask) (((val) ^ (val >> 8)) & (mask))
166 179
167extern const struct filterops sig_filtops; 180extern const struct filterops sig_filtops;
168 181
169/* 182/*
170 * Table for for all system-defined filters. 183 * Table for for all system-defined filters.
171 * These should be listed in the numeric order of the EVFILT_* defines. 184 * These should be listed in the numeric order of the EVFILT_* defines.
172 * If filtops is NULL, the filter isn't implemented in NetBSD. 185 * If filtops is NULL, the filter isn't implemented in NetBSD.
173 * End of list is when name is NULL. 186 * End of list is when name is NULL.
@@ -182,26 +195,27 @@ struct kfilter { @@ -182,26 +195,27 @@ struct kfilter {
182 size_t namelen; /* length of name string */ 195 size_t namelen; /* length of name string */
183}; 196};
184 197
185/* System defined filters */ 198/* System defined filters */
186static struct kfilter sys_kfilters[] = { 199static struct kfilter sys_kfilters[] = {
187 { "EVFILT_READ", EVFILT_READ, 0, &file_filtops, 0 }, 200 { "EVFILT_READ", EVFILT_READ, 0, &file_filtops, 0 },
188 { "EVFILT_WRITE", EVFILT_WRITE, 0, &file_filtops, 0, }, 201 { "EVFILT_WRITE", EVFILT_WRITE, 0, &file_filtops, 0, },
189 { "EVFILT_AIO", EVFILT_AIO, 0, NULL, 0 }, 202 { "EVFILT_AIO", EVFILT_AIO, 0, NULL, 0 },
190 { "EVFILT_VNODE", EVFILT_VNODE, 0, &file_filtops, 0 }, 203 { "EVFILT_VNODE", EVFILT_VNODE, 0, &file_filtops, 0 },
191 { "EVFILT_PROC", EVFILT_PROC, 0, &proc_filtops, 0 }, 204 { "EVFILT_PROC", EVFILT_PROC, 0, &proc_filtops, 0 },
192 { "EVFILT_SIGNAL", EVFILT_SIGNAL, 0, &sig_filtops, 0 }, 205 { "EVFILT_SIGNAL", EVFILT_SIGNAL, 0, &sig_filtops, 0 },
193 { "EVFILT_TIMER", EVFILT_TIMER, 0, &timer_filtops, 0 }, 206 { "EVFILT_TIMER", EVFILT_TIMER, 0, &timer_filtops, 0 },
194 { "EVFILT_FS", EVFILT_FS, 0, &fs_filtops, 0 }, 207 { "EVFILT_FS", EVFILT_FS, 0, &fs_filtops, 0 },
 208 { "EVFILT_USER", EVFILT_USER, 0, &user_filtops, 0 },
195 { NULL, 0, 0, NULL, 0 }, 209 { NULL, 0, 0, NULL, 0 },
196}; 210};
197 211
198/* User defined kfilters */ 212/* User defined kfilters */
199static struct kfilter *user_kfilters; /* array */ 213static struct kfilter *user_kfilters; /* array */
200static int user_kfilterc; /* current offset */ 214static int user_kfilterc; /* current offset */
201static int user_kfiltermaxc; /* max size so far */ 215static int user_kfiltermaxc; /* max size so far */
202static size_t user_kfiltersz; /* size of allocated memory */ 216static size_t user_kfiltersz; /* size of allocated memory */
203 217
204/* 218/*
205 * Global Locks. 219 * Global Locks.
206 * 220 *
207 * Lock order: 221 * Lock order:
@@ -766,26 +780,126 @@ filt_fsdetach(struct knote *kn) @@ -766,26 +780,126 @@ filt_fsdetach(struct knote *kn)
766static int 780static int
767filt_fs(struct knote *kn, long hint) 781filt_fs(struct knote *kn, long hint)
768{ 782{
769 int rv; 783 int rv;
770 784
771 mutex_enter(&kqueue_misc_lock); 785 mutex_enter(&kqueue_misc_lock);
772 kn->kn_fflags |= hint; 786 kn->kn_fflags |= hint;
773 rv = (kn->kn_fflags != 0); 787 rv = (kn->kn_fflags != 0);
774 mutex_exit(&kqueue_misc_lock); 788 mutex_exit(&kqueue_misc_lock);
775 789
776 return rv; 790 return rv;
777} 791}
778 792
 793static int
 794filt_userattach(struct knote *kn)
 795{
 796 struct kqueue *kq = kn->kn_kq;
 797
 798 /*
 799 * EVFILT_USER knotes are not attached to anything in the kernel.
 800 */
 801 mutex_spin_enter(&kq->kq_lock);
 802 kn->kn_hook = NULL;
 803 if (kn->kn_fflags & NOTE_TRIGGER)
 804 kn->kn_hookid = 1;
 805 else
 806 kn->kn_hookid = 0;
 807 mutex_spin_exit(&kq->kq_lock);
 808 return (0);
 809}
 810
 811static void
 812filt_userdetach(struct knote *kn)
 813{
 814
 815 /*
 816 * EVFILT_USER knotes are not attached to anything in the kernel.
 817 */
 818}
 819
 820static int
 821filt_user(struct knote *kn, long hint)
 822{
 823 struct kqueue *kq = kn->kn_kq;
 824 int hookid;
 825
 826 mutex_spin_enter(&kq->kq_lock);
 827 hookid = kn->kn_hookid;
 828 mutex_spin_exit(&kq->kq_lock);
 829
 830 return hookid;
 831}
 832
 833static void
 834filt_usertouch(struct knote *kn, struct kevent *kev, long type)
 835{
 836 struct kqueue *kq = kn->kn_kq;
 837 int ffctrl;
 838
 839 mutex_spin_enter(&kq->kq_lock);
 840 switch (type) {
 841 case EVENT_REGISTER:
 842 if (kev->fflags & NOTE_TRIGGER)
 843 kn->kn_hookid = 1;
 844
 845 ffctrl = kev->fflags & NOTE_FFCTRLMASK;
 846 kev->fflags &= NOTE_FFLAGSMASK;
 847 switch (ffctrl) {
 848 case NOTE_FFNOP:
 849 break;
 850
 851 case NOTE_FFAND:
 852 kn->kn_sfflags &= kev->fflags;
 853 break;
 854
 855 case NOTE_FFOR:
 856 kn->kn_sfflags |= kev->fflags;
 857 break;
 858
 859 case NOTE_FFCOPY:
 860 kn->kn_sfflags = kev->fflags;
 861 break;
 862
 863 default:
 864 /* XXX Return error? */
 865 break;
 866 }
 867 kn->kn_sdata = kev->data;
 868 if (kev->flags & EV_CLEAR) {
 869 kn->kn_hookid = 0;
 870 kn->kn_data = 0;
 871 kn->kn_fflags = 0;
 872 }
 873 break;
 874
 875 case EVENT_PROCESS:
 876 *kev = kn->kn_kevent;
 877 kev->fflags = kn->kn_sfflags;
 878 kev->data = kn->kn_sdata;
 879 if (kn->kn_flags & EV_CLEAR) {
 880 kn->kn_hookid = 0;
 881 kn->kn_data = 0;
 882 kn->kn_fflags = 0;
 883 }
 884 break;
 885
 886 default:
 887 panic("filt_usertouch() - invalid type (%ld)", type);
 888 break;
 889 }
 890 mutex_spin_exit(&kq->kq_lock);
 891}
 892
779/* 893/*
780 * filt_seltrue: 894 * filt_seltrue:
781 * 895 *
782 * This filter "event" routine simulates seltrue(). 896 * This filter "event" routine simulates seltrue().
783 */ 897 */
784int 898int
785filt_seltrue(struct knote *kn, long hint) 899filt_seltrue(struct knote *kn, long hint)
786{ 900{
787 901
788 /* 902 /*
789 * We don't know how much data can be read/written, 903 * We don't know how much data can be read/written,
790 * but we know that it *can* be. This is about as 904 * but we know that it *can* be. This is about as
791 * good as select/poll does as well. 905 * good as select/poll does as well.
@@ -799,26 +913,27 @@ filt_seltrue(struct knote *kn, long hint @@ -799,26 +913,27 @@ filt_seltrue(struct knote *kn, long hint
799 * has same effect as filter using filt_seltrue() as filter method. 913 * has same effect as filter using filt_seltrue() as filter method.
800 */ 914 */
801static void 915static void
802filt_seltruedetach(struct knote *kn) 916filt_seltruedetach(struct knote *kn)
803{ 917{
804 /* Nothing to do */ 918 /* Nothing to do */
805} 919}
806 920
807const struct filterops seltrue_filtops = { 921const struct filterops seltrue_filtops = {
808 .f_isfd = 1, 922 .f_isfd = 1,
809 .f_attach = NULL, 923 .f_attach = NULL,
810 .f_detach = filt_seltruedetach, 924 .f_detach = filt_seltruedetach,
811 .f_event = filt_seltrue, 925 .f_event = filt_seltrue,
 926 .f_touch = NULL,
812}; 927};
813 928
814int 929int
815seltrue_kqfilter(dev_t dev, struct knote *kn) 930seltrue_kqfilter(dev_t dev, struct knote *kn)
816{ 931{
817 switch (kn->kn_filter) { 932 switch (kn->kn_filter) {
818 case EVFILT_READ: 933 case EVFILT_READ:
819 case EVFILT_WRITE: 934 case EVFILT_WRITE:
820 kn->kn_fop = &seltrue_filtops; 935 kn->kn_fop = &seltrue_filtops;
821 break; 936 break;
822 default: 937 default:
823 return (EINVAL); 938 return (EINVAL);
824 } 939 }
@@ -1062,28 +1177,28 @@ kqueue_register(struct kqueue *kq, struc @@ -1062,28 +1177,28 @@ kqueue_register(struct kqueue *kq, struc
1062 KN_HASH((u_long)kev->ident, fdp->fd_knhashmask)]; 1177 KN_HASH((u_long)kev->ident, fdp->fd_knhashmask)];
1063 SLIST_FOREACH(kn, list, kn_link) { 1178 SLIST_FOREACH(kn, list, kn_link) {
1064 if (kev->ident == kn->kn_id && 1179 if (kev->ident == kn->kn_id &&
1065 kq == kn->kn_kq && 1180 kq == kn->kn_kq &&
1066 kev->filter == kn->kn_filter) 1181 kev->filter == kn->kn_filter)
1067 break; 1182 break;
1068 } 1183 }
1069 } 1184 }
1070 } 1185 }
1071 1186
1072 /* 1187 /*
1073 * kn now contains the matching knote, or NULL if no match 1188 * kn now contains the matching knote, or NULL if no match
1074 */ 1189 */
1075 if (kev->flags & EV_ADD) { 1190 if (kn == NULL) {
1076 if (kn == NULL) { 1191 if (kev->flags & EV_ADD) {
1077 /* create new knote */ 1192 /* create new knote */
1078 kn = newkn; 1193 kn = newkn;
1079 newkn = NULL; 1194 newkn = NULL;
1080 kn->kn_obj = fp; 1195 kn->kn_obj = fp;
1081 kn->kn_id = kev->ident; 1196 kn->kn_id = kev->ident;
1082 kn->kn_kq = kq; 1197 kn->kn_kq = kq;
1083 kn->kn_fop = kfilter->filtops; 1198 kn->kn_fop = kfilter->filtops;
1084 kn->kn_kfilter = kfilter; 1199 kn->kn_kfilter = kfilter;
1085 kn->kn_sfflags = kev->fflags; 1200 kn->kn_sfflags = kev->fflags;
1086 kn->kn_sdata = kev->data; 1201 kn->kn_sdata = kev->data;
1087 kev->fflags = 0; 1202 kev->fflags = 0;
1088 kev->data = 0; 1203 kev->data = 0;
1089 kn->kn_kevent = *kev; 1204 kn->kn_kevent = *kev;
@@ -1127,61 +1242,71 @@ kqueue_register(struct kqueue *kq, struc @@ -1127,61 +1242,71 @@ kqueue_register(struct kqueue *kq, struc
1127 printf("%s: %s[%d]: event type %d not " 1242 printf("%s: %s[%d]: event type %d not "
1128 "supported for file type %d/%s " 1243 "supported for file type %d/%s "
1129 "(error %d)\n", __func__, 1244 "(error %d)\n", __func__,
1130 p->p_comm, p->p_pid, 1245 p->p_comm, p->p_pid,
1131 kn->kn_filter, ft ? ft->f_type : -1, 1246 kn->kn_filter, ft ? ft->f_type : -1,
1132 ft ? ft->f_ops->fo_name : "?", error); 1247 ft ? ft->f_ops->fo_name : "?", error);
1133#endif 1248#endif
1134 1249
1135 /* knote_detach() drops fdp->fd_lock */ 1250 /* knote_detach() drops fdp->fd_lock */
1136 knote_detach(kn, fdp, false); 1251 knote_detach(kn, fdp, false);
1137 goto done; 1252 goto done;
1138 } 1253 }
1139 atomic_inc_uint(&kfilter->refcnt); 1254 atomic_inc_uint(&kfilter->refcnt);
 1255 goto done_ev_add;
1140 } else { 1256 } else {
1141 /* 1257 /* No matching knote and the EV_ADD flag is not set. */
1142 * The user may change some filter values after the 1258 error = ENOENT;
1143 * initial EV_ADD, but doing so will not reset any 1259 goto doneunlock;
1144 * filter which have already been triggered. 
1145 */ 
1146 kn->kn_sfflags = kev->fflags; 
1147 kn->kn_sdata = kev->data; 
1148 kn->kn_kevent.udata = kev->udata; 
1149 } 1260 }
1150 /* 1261 }
1151 * We can get here if we are trying to attach 1262
1152 * an event to a file descriptor that does not 1263 if (kev->flags & EV_DELETE) {
1153 * support events, and the attach routine is 1264 /* knote_detach() drops fdp->fd_lock */
1154 * broken and does not return an error. 1265 knote_detach(kn, fdp, true);
1155 */ 1266 goto done;
1156 KASSERT(kn->kn_fop != NULL); 1267 }
1157 KASSERT(kn->kn_fop->f_event != NULL); 1268
 1269 /*
 1270 * The user may change some filter values after the
 1271 * initial EV_ADD, but doing so will not reset any
 1272 * filter which have already been triggered.
 1273 */
 1274 kn->kn_kevent.udata = kev->udata;
 1275 KASSERT(kn->kn_fop != NULL);
 1276 if (!kn->kn_fop->f_isfd && kn->kn_fop->f_touch != NULL) {
1158 KERNEL_LOCK(1, NULL); /* XXXSMP */ 1277 KERNEL_LOCK(1, NULL); /* XXXSMP */
1159 rv = (*kn->kn_fop->f_event)(kn, 0); 1278 (*kn->kn_fop->f_touch)(kn, kev, EVENT_REGISTER);
1160 KERNEL_UNLOCK_ONE(NULL); /* XXXSMP */ 1279 KERNEL_UNLOCK_ONE(NULL); /* XXXSMP */
1161 if (rv) 
1162 knote_activate(kn); 
1163 } else { 1280 } else {
1164 if (kn == NULL) { 1281 kn->kn_sfflags = kev->fflags;
1165 error = ENOENT; 1282 kn->kn_sdata = kev->data;
1166 goto doneunlock; 
1167 } 
1168 if (kev->flags & EV_DELETE) { 
1169 /* knote_detach() drops fdp->fd_lock */ 
1170 knote_detach(kn, fdp, true); 
1171 goto done; 
1172 } 
1173 } 1283 }
1174 1284
 1285 /*
 1286 * We can get here if we are trying to attach
 1287 * an event to a file descriptor that does not
 1288 * support events, and the attach routine is
 1289 * broken and does not return an error.
 1290 */
 1291done_ev_add:
 1292 KASSERT(kn->kn_fop != NULL);
 1293 KASSERT(kn->kn_fop->f_event != NULL);
 1294 KERNEL_LOCK(1, NULL); /* XXXSMP */
 1295 rv = (*kn->kn_fop->f_event)(kn, 0);
 1296 KERNEL_UNLOCK_ONE(NULL); /* XXXSMP */
 1297 if (rv)
 1298 knote_activate(kn);
 1299
1175 /* disable knote */ 1300 /* disable knote */
1176 if ((kev->flags & EV_DISABLE)) { 1301 if ((kev->flags & EV_DISABLE)) {
1177 mutex_spin_enter(&kq->kq_lock); 1302 mutex_spin_enter(&kq->kq_lock);
1178 if ((kn->kn_status & KN_DISABLED) == 0) 1303 if ((kn->kn_status & KN_DISABLED) == 0)
1179 kn->kn_status |= KN_DISABLED; 1304 kn->kn_status |= KN_DISABLED;
1180 mutex_spin_exit(&kq->kq_lock); 1305 mutex_spin_exit(&kq->kq_lock);
1181 } 1306 }
1182 1307
1183 /* enable knote */ 1308 /* enable knote */
1184 if ((kev->flags & EV_ENABLE)) { 1309 if ((kev->flags & EV_ENABLE)) {
1185 knote_enqueue(kn); 1310 knote_enqueue(kn);
1186 } 1311 }
1187doneunlock: 1312doneunlock:
@@ -1261,27 +1386,27 @@ bad: @@ -1261,27 +1386,27 @@ bad:
1261 * as appropriate. 1386 * as appropriate.
1262 */ 1387 */
1263static int 1388static int
1264kqueue_scan(file_t *fp, size_t maxevents, struct kevent *ulistp, 1389kqueue_scan(file_t *fp, size_t maxevents, struct kevent *ulistp,
1265 const struct timespec *tsp, register_t *retval, 1390 const struct timespec *tsp, register_t *retval,
1266 const struct kevent_ops *keops, struct kevent *kevbuf, 1391 const struct kevent_ops *keops, struct kevent *kevbuf,
1267 size_t kevcnt) 1392 size_t kevcnt)
1268{ 1393{
1269 struct kqueue *kq; 1394 struct kqueue *kq;
1270 struct kevent *kevp; 1395 struct kevent *kevp;
1271 struct timespec ats, sleepts; 1396 struct timespec ats, sleepts;
1272 struct knote *kn, *marker, morker; 1397 struct knote *kn, *marker, morker;
1273 size_t count, nkev, nevents; 1398 size_t count, nkev, nevents;
1274 int timeout, error, rv; 1399 int timeout, error, touch, rv;
1275 filedesc_t *fdp; 1400 filedesc_t *fdp;
1276 1401
1277 fdp = curlwp->l_fd; 1402 fdp = curlwp->l_fd;
1278 kq = fp->f_kqueue; 1403 kq = fp->f_kqueue;
1279 count = maxevents; 1404 count = maxevents;
1280 nkev = nevents = error = 0; 1405 nkev = nevents = error = 0;
1281 if (count == 0) { 1406 if (count == 0) {
1282 *retval = 0; 1407 *retval = 0;
1283 return 0; 1408 return 0;
1284 } 1409 }
1285 1410
1286 if (tsp) { /* timeout supplied */ 1411 if (tsp) { /* timeout supplied */
1287 ats = *tsp; 1412 ats = *tsp;
@@ -1372,40 +1497,60 @@ kqueue_scan(file_t *fp, size_t maxevents @@ -1372,40 +1497,60 @@ kqueue_scan(file_t *fp, size_t maxevents
1372 if ((kn->kn_status & KN_QUEUED) != 0) { 1497 if ((kn->kn_status & KN_QUEUED) != 0) {
1373 kn->kn_status &= ~KN_BUSY; 1498 kn->kn_status &= ~KN_BUSY;
1374 continue; 1499 continue;
1375 } 1500 }
1376 if (rv == 0) { 1501 if (rv == 0) {
1377 /* 1502 /*
1378 * non-ONESHOT event that hasn't 1503 * non-ONESHOT event that hasn't
1379 * triggered again, so de-queue. 1504 * triggered again, so de-queue.
1380 */ 1505 */
1381 kn->kn_status &= ~(KN_ACTIVE|KN_BUSY); 1506 kn->kn_status &= ~(KN_ACTIVE|KN_BUSY);
1382 continue; 1507 continue;
1383 } 1508 }
1384 } 1509 }
 1510 KASSERT(kn->kn_fop != NULL);
 1511 touch = (!kn->kn_fop->f_isfd &&
 1512 kn->kn_fop->f_touch != NULL);
1385 /* XXXAD should be got from f_event if !oneshot. */ 1513 /* XXXAD should be got from f_event if !oneshot. */
1386 *kevp++ = kn->kn_kevent; 1514 if (touch) {
 1515 mutex_spin_exit(&kq->kq_lock);
 1516 KERNEL_LOCK(1, NULL); /* XXXSMP */
 1517 (*kn->kn_fop->f_touch)(kn, kevp, EVENT_PROCESS);
 1518 KERNEL_UNLOCK_ONE(NULL); /* XXXSMP */
 1519 mutex_spin_enter(&kq->kq_lock);
 1520 } else {
 1521 *kevp = kn->kn_kevent;
 1522 }
 1523 kevp++;
1387 nkev++; 1524 nkev++;
1388 if (kn->kn_flags & EV_ONESHOT) { 1525 if (kn->kn_flags & EV_ONESHOT) {
1389 /* delete ONESHOT events after retrieval */ 1526 /* delete ONESHOT events after retrieval */
1390 kn->kn_status &= ~KN_BUSY; 1527 kn->kn_status &= ~KN_BUSY;
1391 mutex_spin_exit(&kq->kq_lock); 1528 mutex_spin_exit(&kq->kq_lock);
1392 knote_detach(kn, fdp, true); 1529 knote_detach(kn, fdp, true);
1393 mutex_enter(&fdp->fd_lock); 1530 mutex_enter(&fdp->fd_lock);
1394 mutex_spin_enter(&kq->kq_lock); 1531 mutex_spin_enter(&kq->kq_lock);
1395 } else if (kn->kn_flags & EV_CLEAR) { 1532 } else if (kn->kn_flags & EV_CLEAR) {
1396 /* clear state after retrieval */ 1533 /* clear state after retrieval */
1397 kn->kn_data = 0; 1534 kn->kn_data = 0;
1398 kn->kn_fflags = 0; 1535 kn->kn_fflags = 0;
 1536 /*
 1537 * Manually clear knotes who weren't
 1538 * 'touch'ed.
 1539 */
 1540 if (touch == 0) {
 1541 kn->kn_data = 0;
 1542 kn->kn_fflags = 0;
 1543 }
1399 kn->kn_status &= ~(KN_QUEUED|KN_ACTIVE|KN_BUSY); 1544 kn->kn_status &= ~(KN_QUEUED|KN_ACTIVE|KN_BUSY);
1400 } else if (kn->kn_flags & EV_DISPATCH) { 1545 } else if (kn->kn_flags & EV_DISPATCH) {
1401 kn->kn_status |= KN_DISABLED; 1546 kn->kn_status |= KN_DISABLED;
1402 kn->kn_status &= ~(KN_QUEUED|KN_ACTIVE|KN_BUSY); 1547 kn->kn_status &= ~(KN_QUEUED|KN_ACTIVE|KN_BUSY);
1403 } else { 1548 } else {
1404 /* add event back on list */ 1549 /* add event back on list */
1405 kq_check(kq); 1550 kq_check(kq);
1406 kn->kn_status |= KN_QUEUED; 1551 kn->kn_status |= KN_QUEUED;
1407 kn->kn_status &= ~KN_BUSY; 1552 kn->kn_status &= ~KN_BUSY;
1408 TAILQ_INSERT_TAIL(&kq->kq_head, kn, kn_tqe); 1553 TAILQ_INSERT_TAIL(&kq->kq_head, kn, kn_tqe);
1409 kq->kq_count++; 1554 kq->kq_count++;
1410 kq_check(kq); 1555 kq_check(kq);
1411 } 1556 }

cvs diff -r1.38 -r1.39 src/sys/sys/event.h (expand / switch to unified diff)

--- src/sys/sys/event.h 2019/10/03 22:16:52 1.38
+++ src/sys/sys/event.h 2020/10/31 01:08:32 1.39
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: event.h,v 1.38 2019/10/03 22:16:52 kamil Exp $ */ 1/* $NetBSD: event.h,v 1.39 2020/10/31 01:08:32 christos Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 1999,2000,2001 Jonathan Lemon <jlemon@FreeBSD.org> 4 * Copyright (c) 1999,2000,2001 Jonathan Lemon <jlemon@FreeBSD.org>
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
@@ -34,27 +34,28 @@ @@ -34,27 +34,28 @@
34#include <sys/featuretest.h> 34#include <sys/featuretest.h>
35#include <sys/types.h> /* for size_t */ 35#include <sys/types.h> /* for size_t */
36#include <sys/inttypes.h> /* for uintptr_t */ 36#include <sys/inttypes.h> /* for uintptr_t */
37#include <sys/null.h> /* for NULL */ 37#include <sys/null.h> /* for NULL */
38 38
39#define EVFILT_READ 0U 39#define EVFILT_READ 0U
40#define EVFILT_WRITE 1U 40#define EVFILT_WRITE 1U
41#define EVFILT_AIO 2U /* attached to aio requests */ 41#define EVFILT_AIO 2U /* attached to aio requests */
42#define EVFILT_VNODE 3U /* attached to vnodes */ 42#define EVFILT_VNODE 3U /* attached to vnodes */
43#define EVFILT_PROC 4U /* attached to struct proc */ 43#define EVFILT_PROC 4U /* attached to struct proc */
44#define EVFILT_SIGNAL 5U /* attached to struct proc */ 44#define EVFILT_SIGNAL 5U /* attached to struct proc */
45#define EVFILT_TIMER 6U /* arbitrary timer (in ms) */ 45#define EVFILT_TIMER 6U /* arbitrary timer (in ms) */
46#define EVFILT_FS 7U /* filesystem events */ 46#define EVFILT_FS 7U /* filesystem events */
47#define EVFILT_SYSCOUNT 8U /* number of filters */ 47#define EVFILT_USER 8U /* user events */
 48#define EVFILT_SYSCOUNT 9U /* number of filters */
48 49
49struct kevent { 50struct kevent {
50 uintptr_t ident; /* identifier for this event */ 51 uintptr_t ident; /* identifier for this event */
51 uint32_t filter; /* filter for event */ 52 uint32_t filter; /* filter for event */
52 uint32_t flags; /* action flags for kqueue */ 53 uint32_t flags; /* action flags for kqueue */
53 uint32_t fflags; /* filter flag value */ 54 uint32_t fflags; /* filter flag value */
54 int64_t data; /* filter data value */ 55 int64_t data; /* filter data value */
55 void *udata; /* opaque user data identifier */ 56 void *udata; /* opaque user data identifier */
56}; 57};
57 58
58static __inline void 59static __inline void
59_EV_SET(struct kevent *_kevp, uintptr_t _ident, uint32_t _filter, 60_EV_SET(struct kevent *_kevp, uintptr_t _ident, uint32_t _filter,
60 uint32_t _flags, uint32_t _fflags, int64_t _data, void *_udata) 61 uint32_t _flags, uint32_t _fflags, int64_t _data, void *_udata)
@@ -81,26 +82,45 @@ _EV_SET(struct kevent *_kevp, uintptr_t  @@ -81,26 +82,45 @@ _EV_SET(struct kevent *_kevp, uintptr_t
81#define EV_ONESHOT 0x0010U /* only report one occurrence */ 82#define EV_ONESHOT 0x0010U /* only report one occurrence */
82#define EV_CLEAR 0x0020U /* clear event state after reporting */ 83#define EV_CLEAR 0x0020U /* clear event state after reporting */
83#define EV_RECEIPT 0x0040U /* force EV_ERROR on success, data=0 */ 84#define EV_RECEIPT 0x0040U /* force EV_ERROR on success, data=0 */
84#define EV_DISPATCH 0x0080U /* disable event after reporting */ 85#define EV_DISPATCH 0x0080U /* disable event after reporting */
85 86
86#define EV_SYSFLAGS 0xF000U /* reserved by system */ 87#define EV_SYSFLAGS 0xF000U /* reserved by system */
87#define EV_FLAG1 0x2000U /* filter-specific flag */ 88#define EV_FLAG1 0x2000U /* filter-specific flag */
88 89
89/* returned values */ 90/* returned values */
90#define EV_EOF 0x8000U /* EOF detected */ 91#define EV_EOF 0x8000U /* EOF detected */
91#define EV_ERROR 0x4000U /* error, data contains errno */ 92#define EV_ERROR 0x4000U /* error, data contains errno */
92 93
93/* 94/*
 95 * data/hint flags/masks for EVFILT_USER, shared with userspace
 96 *
 97 * On input, the top two bits of fflags specifies how the lower twenty four
 98 * bits should be applied to the stored value of fflags.
 99 *
 100 * On output, the top two bits will always be set to NOTE_FFNOP and the
 101 * remaining twenty four bits will contain the stored fflags value.
 102 */
 103#define NOTE_FFNOP 0x00000000U /* ignore input fflags */
 104#define NOTE_FFAND 0x40000000U /* AND fflags */
 105#define NOTE_FFOR 0x80000000U /* OR fflags */
 106#define NOTE_FFCOPY 0xc0000000U /* copy fflags */
 107
 108#define NOTE_FFCTRLMASK 0xc0000000U /* masks for operations */
 109#define NOTE_FFLAGSMASK 0x00ffffffU
 110
 111#define NOTE_TRIGGER 0x01000000U /* Cause the event to be
 112 triggered for output. */
 113/*
94 * hint flag for in-kernel use - must not equal any existing note 114 * hint flag for in-kernel use - must not equal any existing note
95 */ 115 */
96#ifdef _KERNEL 116#ifdef _KERNEL
97#define NOTE_SUBMIT 0x01000000U /* initial knote submission */ 117#define NOTE_SUBMIT 0x01000000U /* initial knote submission */
98#endif 118#endif
99/* 119/*
100 * data/hint flags for EVFILT_{READ|WRITE}, shared with userspace 120 * data/hint flags for EVFILT_{READ|WRITE}, shared with userspace
101 */ 121 */
102#define NOTE_LOWAT 0x0001U /* low water mark */ 122#define NOTE_LOWAT 0x0001U /* low water mark */
103 123
104/* 124/*
105 * data/hint flags for EVFILT_VNODE, shared with userspace 125 * data/hint flags for EVFILT_VNODE, shared with userspace
106 */ 126 */
@@ -152,60 +172,72 @@ struct kfilter_mapping { @@ -152,60 +172,72 @@ struct kfilter_mapping {
152#define KFILTER_BYNAME _IOWR('k', 1, struct kfilter_mapping) 172#define KFILTER_BYNAME _IOWR('k', 1, struct kfilter_mapping)
153 173
154#ifdef _KERNEL 174#ifdef _KERNEL
155 175
156#define KNOTE(list, hint) if (!SLIST_EMPTY(list)) knote(list, hint) 176#define KNOTE(list, hint) if (!SLIST_EMPTY(list)) knote(list, hint)
157 177
158/* 178/*
159 * Flag indicating hint is a signal. Used by EVFILT_SIGNAL, and also 179 * Flag indicating hint is a signal. Used by EVFILT_SIGNAL, and also
160 * shared by EVFILT_PROC (all knotes attached to p->p_klist) 180 * shared by EVFILT_PROC (all knotes attached to p->p_klist)
161 */ 181 */
162#define NOTE_SIGNAL 0x08000000U 182#define NOTE_SIGNAL 0x08000000U
163 183
164/* 184/*
 185 * Hint values for the optional f_touch event filter. If f_touch is not set
 186 * to NULL and f_isfd is zero the f_touch filter will be called with the type
 187 * argument set to EVENT_REGISTER during a kevent() system call. It is also
 188 * called under the same conditions with the type argument set to EVENT_PROCESS
 189 * when the event has been triggered.
 190 */
 191#define EVENT_REGISTER 1
 192#define EVENT_PROCESS 2
 193
 194/*
165 * Callback methods for each filter type. 195 * Callback methods for each filter type.
166 */ 196 */
167struct filterops { 197struct filterops {
168 int f_isfd; /* true if ident == filedescriptor */ 198 int f_isfd; /* true if ident == filedescriptor */
169 int (*f_attach) (struct knote *); 199 int (*f_attach) (struct knote *);
170 /* called when knote is ADDed */ 200 /* called when knote is ADDed */
171 void (*f_detach) (struct knote *); 201 void (*f_detach) (struct knote *);
172 /* called when knote is DELETEd */ 202 /* called when knote is DELETEd */
173 int (*f_event) (struct knote *, long); 203 int (*f_event) (struct knote *, long);
174 /* called when event is triggered */ 204 /* called when event is triggered */
 205 void (*f_touch) (struct knote *, struct kevent *, long);
175}; 206};
176 207
177/* 208/*
178 * Field locking: 209 * Field locking:
179 * 210 *
180 * f kn_kq->kq_fdp->fd_lock 211 * f kn_kq->kq_fdp->fd_lock
181 * q kn_kq->kq_lock 212 * q kn_kq->kq_lock
182 * o object mutex (e.g. device driver or vnode interlock) 213 * o object mutex (e.g. device driver or vnode interlock)
183 */ 214 */
184struct kfilter; 215struct kfilter;
185 216
186struct knote { 217struct knote {
187 SLIST_ENTRY(knote) kn_link; /* f: for fd */ 218 SLIST_ENTRY(knote) kn_link; /* f: for fd */
188 SLIST_ENTRY(knote) kn_selnext; /* o: for struct selinfo */ 219 SLIST_ENTRY(knote) kn_selnext; /* o: for struct selinfo */
189 TAILQ_ENTRY(knote) kn_tqe; /* q: for struct kqueue */ 220 TAILQ_ENTRY(knote) kn_tqe; /* q: for struct kqueue */
190 struct kqueue *kn_kq; /* q: which queue we are on */ 221 struct kqueue *kn_kq; /* q: which queue we are on */
191 struct kevent kn_kevent; 222 struct kevent kn_kevent;
192 uint32_t kn_status; /* q: flags below */ 223 uint32_t kn_status; /* q: flags below */
193 uint32_t kn_sfflags; /* saved filter flags */ 224 uint32_t kn_sfflags; /* saved filter flags */
194 uintptr_t kn_sdata; /* saved data field */ 225 uintptr_t kn_sdata; /* saved data field */
195 void *kn_obj; /* monitored obj */ 226 void *kn_obj; /* monitored obj */
196 const struct filterops *kn_fop; 227 const struct filterops *kn_fop;
197 struct kfilter *kn_kfilter; 228 struct kfilter *kn_kfilter;
198 void *kn_hook; 229 void *kn_hook;
 230 int kn_hookid;
199 231
200#define KN_ACTIVE 0x01U /* event has been triggered */ 232#define KN_ACTIVE 0x01U /* event has been triggered */
201#define KN_QUEUED 0x02U /* event is on queue */ 233#define KN_QUEUED 0x02U /* event is on queue */
202#define KN_DISABLED 0x04U /* event is disabled */ 234#define KN_DISABLED 0x04U /* event is disabled */
203#define KN_DETACHED 0x08U /* knote is detached */ 235#define KN_DETACHED 0x08U /* knote is detached */
204#define KN_MARKER 0x10U /* is a marker */ 236#define KN_MARKER 0x10U /* is a marker */
205#define KN_BUSY 0x20U /* is being scanned */ 237#define KN_BUSY 0x20U /* is being scanned */
206/* Toggling KN_BUSY also requires kn_kq->kq_fdp->fd_lock. */ 238/* Toggling KN_BUSY also requires kn_kq->kq_fdp->fd_lock. */
207#define __KN_FLAG_BITS \ 239#define __KN_FLAG_BITS \
208 "\20" \ 240 "\20" \
209 "\1ACTIVE" \ 241 "\1ACTIVE" \
210 "\2QUEUED" \ 242 "\2QUEUED" \
211 "\3DISABLED" \ 243 "\3DISABLED" \

cvs diff -r1.8 -r1.9 src/tests/lib/libc/sys/t_kevent.c (expand / switch to unified diff)

--- src/tests/lib/libc/sys/t_kevent.c 2020/06/25 11:12:03 1.8
+++ src/tests/lib/libc/sys/t_kevent.c 2020/10/31 01:08:32 1.9
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: t_kevent.c,v 1.8 2020/06/25 11:12:03 jruoho Exp $ */ 1/* $NetBSD: t_kevent.c,v 1.9 2020/10/31 01:08:32 christos Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2011 The NetBSD Foundation, Inc. 4 * Copyright (c) 2011 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to The NetBSD Foundatiom 7 * This code is derived from software contributed to The NetBSD Foundatiom
8 * by Christos Zoulas. 8 * by Christos Zoulas.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
@@ -19,27 +19,27 @@ @@ -19,27 +19,27 @@
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE. 29 * POSSIBILITY OF SUCH DAMAGE.
30 */ 30 */
31#include <sys/cdefs.h> 31#include <sys/cdefs.h>
32__RCSID("$NetBSD: t_kevent.c,v 1.8 2020/06/25 11:12:03 jruoho Exp $"); 32__RCSID("$NetBSD: t_kevent.c,v 1.9 2020/10/31 01:08:32 christos Exp $");
33 33
34#include <sys/types.h> 34#include <sys/types.h>
35#include <sys/event.h> 35#include <sys/event.h>
36 36
37#include <atf-c.h> 37#include <atf-c.h>
38#include <errno.h> 38#include <errno.h>
39#include <time.h> 39#include <time.h>
40#include <stdio.h> 40#include <stdio.h>
41#include <stdlib.h> 41#include <stdlib.h>
42#include <string.h> 42#include <string.h>
43#include <unistd.h> 43#include <unistd.h>
44#include <fcntl.h> 44#include <fcntl.h>
45#include <err.h> 45#include <err.h>
@@ -162,25 +162,58 @@ ATF_TC_BODY(kqueue_unsupported_fd, tc) @@ -162,25 +162,58 @@ ATF_TC_BODY(kqueue_unsupported_fd, tc)
162 } 162 }
163 } 163 }
164 ATF_REQUIRE(fd != -1); 164 ATF_REQUIRE(fd != -1);
165 ATF_REQUIRE((kq = kqueue()) != -1); 165 ATF_REQUIRE((kq = kqueue()) != -1);
166 166
167 EV_SET(&ev, fd, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_CLEAR, 167 EV_SET(&ev, fd, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_CLEAR,
168 NOTE_DELETE|NOTE_WRITE|NOTE_EXTEND|NOTE_ATTRIB|NOTE_LINK| 168 NOTE_DELETE|NOTE_WRITE|NOTE_EXTEND|NOTE_ATTRIB|NOTE_LINK|
169 NOTE_RENAME|NOTE_REVOKE, 0, 0); 169 NOTE_RENAME|NOTE_REVOKE, 0, 0);
170 170
171 ATF_REQUIRE(kevent(kq, &ev, 1, NULL, 0, NULL) == -1); 171 ATF_REQUIRE(kevent(kq, &ev, 1, NULL, 0, NULL) == -1);
172 ATF_REQUIRE_ERRNO(EOPNOTSUPP, true); 172 ATF_REQUIRE_ERRNO(EOPNOTSUPP, true);
173 173
174 (void)close(fd); 174 (void)close(fd);
 175 (void)close(kq);
175} 176}
176 177
 178ATF_TC(kqueue_EVFILT_USER);
 179ATF_TC_HEAD(kqueue_EVFILT_USER, tc)
 180{
 181 atf_tc_set_md_var(tc, "descr", "Checks usability of EVFILT_USER");
 182}
 183
 184ATF_TC_BODY(kqueue_EVFILT_USER, tc)
 185{
 186 /* mqueue and semaphore use fnullop_kqueue also */
 187 int kq;
 188 struct kevent ev, rev;
 189
 190 ATF_REQUIRE((kq = kqueue()) != -1);
 191
 192 EV_SET(&ev, 666, EVFILT_USER, EV_ADD | EV_ENABLE, 0, 0, 0);
 193 ATF_REQUIRE(kevent(kq, &ev, 1, NULL, 0, NULL) == 0);
 194 EV_SET(&ev, 666, EVFILT_USER, 0, NOTE_FFCOPY | NOTE_TRIGGER | 8, 0, 0);
 195 ATF_REQUIRE(kevent(kq, &ev, 1, NULL, 0, NULL) == 0);
 196 const struct timespec timeout = {
 197 .tv_sec = 1,
 198 .tv_nsec = 0,
 199 };
 200
 201 ATF_REQUIRE(kevent(kq, NULL, 0, &rev, 1, &timeout) == 1);
 202 ATF_REQUIRE(rev.ident == 666);
 203 ATF_REQUIRE(rev.filter == EVFILT_USER);
 204 ATF_REQUIRE(rev.fflags == 8);
 205 (void)close(kq);
 206}
 207
 208
177 209
178ATF_TP_ADD_TCS(tp) 210ATF_TP_ADD_TCS(tp)
179{ 211{
180 212
181 ATF_TP_ADD_TC(tp, kevent_zerotimer); 213 ATF_TP_ADD_TC(tp, kevent_zerotimer);
182 ATF_TP_ADD_TC(tp, kqueue_desc_passing); 214 ATF_TP_ADD_TC(tp, kqueue_desc_passing);
183 ATF_TP_ADD_TC(tp, kqueue_unsupported_fd); 215 ATF_TP_ADD_TC(tp, kqueue_unsupported_fd);
 216 ATF_TP_ADD_TC(tp, kqueue_EVFILT_USER);
184 217
185 return atf_no_error(); 218 return atf_no_error();
186} 219}