PR/55663: Ruslan Nikolaev: Add support for EVFILT_USER in kqueue(2)diff -r1.50 -r1.51 src/lib/libc/sys/kqueue.2
(christos)
--- 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 | |
57 | The | |||
57 | .Fn kqueue | 58 | .Fn kqueue | |
59 | system call | |||
58 | provides a generic method of notifying the user when an event | 60 | provides a generic method of notifying the user when an event | |
59 | happens or a condition holds, based on the results of small | 61 | happens or a condition holds, based on the results of small | |
60 | pieces of kernel code termed filters. | 62 | pieces of kernel code termed filters. | |
61 | A kevent is identified by the (ident, filter) pair; there may only | 63 | A kevent is identified by the (ident, filter) pair; there may only | |
62 | be one unique kevent per kqueue. | 64 | be one unique kevent per kqueue. | |
63 | .Pp | 65 | .Pp | |
64 | The filter is executed upon the initial registration of a kevent | 66 | The filter is executed upon the initial registration of a kevent | |
65 | in order to detect whether a preexisting condition is present, and is also | 67 | in order to detect whether a preexisting condition is present, and is also | |
66 | executed whenever an event is passed to the filter for evaluation. | 68 | executed whenever an event is passed to the filter for evaluation. | |
67 | If the filter determines that the condition should be reported, | 69 | If the filter determines that the condition should be reported, | |
68 | then the kevent is placed on the kqueue for the user to retrieve. | 70 | then the kevent is placed on the kqueue for the user to retrieve. | |
69 | .Pp | 71 | .Pp | |
70 | The filter is also run when the user attempts to retrieve the kevent | 72 | The filter is also run when the user attempts to retrieve the kevent | |
71 | from the kqueue. | 73 | from the kqueue. | |
72 | If the filter indicates that the condition that triggered | 74 | If the filter indicates that the condition that triggered | |
73 | the event no longer holds, the kevent is removed from the kqueue and | 75 | the event no longer holds, the kevent is removed from the kqueue and | |
74 | is not returned. | 76 | is not returned. | |
75 | .Pp | 77 | .Pp | |
76 | Multiple events which trigger the filter do not result in multiple | 78 | Multiple events which trigger the filter do not result in multiple | |
77 | kevents being placed on the kqueue; instead, the filter will aggregate | 79 | kevents being placed on the kqueue; instead, the filter will aggregate | |
78 | the events into a single struct kevent. | 80 | the events into a single struct kevent. | |
79 | Calling | 81 | Calling | |
80 | .Xr close 2 | 82 | .Xr close 2 | |
81 | on a file descriptor will remove any kevents that reference the descriptor. | 83 | on a file descriptor will remove any kevents that reference the descriptor. | |
82 | .Pp | 84 | .Pp | |
85 | The | |||
83 | .Fn kqueue | 86 | .Fn kqueue | |
87 | system call | |||
84 | creates a new kernel event queue and returns a descriptor. | 88 | creates a new kernel event queue and returns a descriptor. | |
85 | .Pp | 89 | .Pp | |
86 | The | 90 | The | |
87 | .Fn kqueue1 | 91 | .Fn kqueue1 | |
88 | function also allows to set the following | 92 | system call also allows to set the following | |
89 | .Fa flags | 93 | .Fa flags | |
90 | on the returned file descriptor: | 94 | on 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 | |
93 | Set the close on exec property. | 97 | Set the close on exec property. | |
94 | .It Dv O_NONBLOCK | 98 | .It Dv O_NONBLOCK | |
95 | Set non-blocking I/O. | 99 | Set non-blocking I/O. | |
96 | .It Dv O_NOSIGPIPE | 100 | .It Dv O_NOSIGPIPE | |
97 | Return | 101 | Return | |
98 | .Er EPIPE | 102 | .Er EPIPE | |
99 | instead of raising | 103 | instead of raising | |
100 | .Dv SIGPIPE . | 104 | .Dv SIGPIPE . | |
101 | .El | 105 | .El | |
102 | .Pp | 106 | .Pp | |
103 | The queue is not inherited by a child created with | 107 | The 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 | |
116 | The | |||
112 | .Fn kevent | 117 | .Fn kevent | |
118 | system call | |||
113 | is used to register events with the queue, and return any pending | 119 | is used to register events with the queue, and return any pending | |
114 | events to the user. | 120 | events to the user. | |
121 | The | |||
115 | .Fa changelist | 122 | .Fa changelist | |
123 | argument | |||
116 | is a pointer to an array of | 124 | is a pointer to an array of | |
117 | .Va kevent | 125 | .Va kevent | |
118 | structures, as defined in | 126 | structures, as defined in | |
119 | .In sys/event.h . | 127 | .In sys/event.h . | |
120 | All changes contained in the | 128 | All changes contained in the | |
121 | .Fa changelist | 129 | .Fa changelist | |
122 | are applied before any pending events are read from the queue. | 130 | are applied before any pending events are read from the queue. | |
131 | The | |||
123 | .Fa nchanges | 132 | .Fa nchanges | |
133 | argument | |||
124 | gives the size of | 134 | gives the size of | |
125 | .Fa changelist . | 135 | .Fa changelist . | |
136 | The | |||
126 | .Fa eventlist | 137 | .Fa eventlist | |
138 | argument | |||
127 | is a pointer to an array of kevent structures. | 139 | is a pointer to an array of kevent structures. | |
140 | The | |||
128 | .Fa nevents | 141 | .Fa nevents | |
142 | argument | |||
129 | determines the size of | 143 | determines the size of | |
130 | .Fa eventlist . | 144 | .Fa eventlist . | |
145 | When | |||
146 | .Fa nevents | |||
147 | is zero, | |||
148 | .Fn kevent | |||
149 | will return immediately even if there is a | |||
150 | .Fa timeout | |||
151 | specified unlike | |||
152 | .Xr select 2 . | |||
131 | If | 153 | If | |
132 | .Fa timeout | 154 | .Fa timeout | |
133 | is a | 155 | is a | |
134 | .No non- Ns Dv NULL | 156 | .No non- Ns Dv NULL | |
135 | pointer, it specifies a maximum interval to wait | 157 | pointer, it specifies a maximum interval to wait | |
136 | for an event, which will be interpreted as a | 158 | for an event, which will be interpreted as a | |
137 | .Li struct timespec . | 159 | .Li struct timespec . | |
138 | If | 160 | If | |
139 | .Fa timeout | 161 | .Fa timeout | |
140 | is a | 162 | is a | |
141 | .Dv NULL | 163 | .Dv NULL | |
142 | pointer, | 164 | pointer, | |
143 | .Fn kevent | 165 | .Fn kevent | |
144 | waits indefinitely. | 166 | waits indefinitely. | |
145 | To effect a poll, the | 167 | To effect a poll, the | |
146 | .Fa timeout | 168 | .Fa timeout | |
147 | argument should be | 169 | argument should be | |
148 | .No non- Ns Dv NULL , | 170 | .No non- Ns Dv NULL , | |
149 | pointing to a zero-valued | 171 | pointing to a zero-valued | |
150 | .Xr timespec 3 | 172 | .Xr timespec 3 | |
151 | structure. | 173 | structure. | |
152 | The same array may be used for the | 174 | The same array may be used for the | |
153 | .Fa changelist | 175 | .Fa changelist | |
154 | and | 176 | and | |
155 | .Fa eventlist . | 177 | .Fa eventlist . | |
156 | .Pp | 178 | .Pp | |
179 | The | |||
157 | .Fn EV_SET | 180 | .Fn EV_SET | |
158 | is a macro which is provided for ease of initializing a kevent structure. | 181 | macro is provided for ease of initializing a kevent structure. | |
159 | This macro does not evaluate its parameters multiple times. | 182 | This macro does not evaluate its parameters multiple times. | |
160 | .Pp | 183 | .Pp | |
161 | The | 184 | The | |
162 | .Va kevent | 185 | .Va kevent | |
163 | structure is defined as: | 186 | structure is defined as: | |
164 | .Bd -literal | 187 | .Bd -literal | |
165 | struct kevent { | 188 | struct 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 | |
175 | The fields of | 198 | The fields of | |
176 | .Fa struct kevent | 199 | .Fa struct kevent | |
177 | are: | 200 | are: | |
178 | .Bl -tag -width XXXfilter -offset indent | 201 | .Bl -tag -width "Fa filter" -offset indent | |
179 | .It ident | 202 | .It ident | |
180 | Value used to identify this event. | 203 | Value used to identify this event. | |
181 | The exact interpretation is determined by the attached filter, | 204 | The exact interpretation is determined by the attached filter, | |
182 | but often is a file descriptor. | 205 | but often is a file descriptor. | |
183 | .It filter | 206 | .It Fa filter | |
184 | Identifies the kernel filter used to process this event. | 207 | Identifies the kernel filter used to process this event. | |
185 | There are pre-defined system filters (which are described below), and | 208 | There are pre-defined system filters (which are described below), and | |
186 | other filters may be added by kernel subsystems as necessary. | 209 | other filters may be added by kernel subsystems as necessary. | |
187 | .It flags | 210 | .It Fa flags | |
188 | Actions to perform on the event. | 211 | Actions to perform on the event. | |
189 | .It fflags | 212 | .It Fa fflags | |
190 | Filter-specific flags. | 213 | Filter-specific flags. | |
191 | .It data | 214 | .It Fa data | |
192 | Filter-specific data value. | 215 | Filter-specific data value. | |
193 | .It udata | 216 | .It Fa udata | |
194 | Opaque user-defined value passed through the kernel unchanged. | 217 | Opaque user-defined value passed through the kernel unchanged. | |
195 | .El | 218 | .El | |
196 | .Pp | 219 | .Pp | |
197 | The | 220 | The | |
198 | .Va flags | 221 | .Va flags | |
199 | field can contain the following values: | 222 | field 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 | |
202 | Adds the event to the kqueue. | 225 | Adds the event to the kqueue. | |
203 | Re-adding an existing event will modify the parameters of the original | 226 | Re-adding an existing event will modify the parameters of the original | |
204 | event, and not result in a duplicate entry. | 227 | event, and not result in a duplicate entry. | |
205 | Adding an event automatically enables it, | 228 | Adding an event automatically enables it, | |
206 | unless overridden by the EV_DISABLE flag. | 229 | unless 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 | |
222 | Removes the event from the kqueue. | 245 | Removes the event from the kqueue. | |
223 | Events which are attached to file descriptors are automatically deleted | 246 | Events which are attached to file descriptors are automatically deleted | |
224 | on the last close of the descriptor. | 247 | on the last close of the descriptor. | |
225 | .It Dv EV_RECEIPT | 248 | .It Dv EV_RECEIPT | |
226 | This flag is useful for making bulk changes to a kqueue without draining | 249 | This flag is useful for making bulk changes to a kqueue without draining | |
227 | any pending events. | 250 | any pending events. | |
228 | When passed as input, it forces | 251 | When passed as input, it forces | |
229 | .Dv EV_ERROR | 252 | .Dv EV_ERROR | |
230 | to always be returned. | 253 | to always be returned. | |
231 | When a filter is successfully added the | 254 | When a filter is successfully added the | |
232 | .Va data | 255 | .Va data | |
233 | field will be zero. | 256 | field will be zero. | |
257 | Note that if this flag is encountered and there is no remaining space in | |||
258 | .Fa eventlist | |||
259 | to hold the | |||
260 | .Dv EV_ERROR | |||
261 | event, then subsequent changes will not get processed. | |||
234 | .It Dv EV_ONESHOT | 262 | .It Dv EV_ONESHOT | |
235 | Causes the event to return only the first occurrence of the filter | 263 | Causes the event to return only the first occurrence of the filter | |
236 | being triggered. | 264 | being triggered. | |
237 | After the user retrieves the event from the kqueue, it is deleted. | 265 | After the user retrieves the event from the kqueue, it is deleted. | |
238 | .It Dv EV_CLEAR | 266 | .It Dv EV_CLEAR | |
239 | After the event is retrieved by the user, its state is reset. | 267 | After the event is retrieved by the user, its state is reset. | |
240 | This is useful for filters which report state transitions | 268 | This is useful for filters which report state transitions | |
241 | instead of the current state. | 269 | instead of the current state. | |
242 | Note that some filters may automatically set this flag internally. | 270 | Note that some filters may automatically set this flag internally. | |
243 | .It Dv EV_EOF | 271 | .It Dv EV_EOF | |
244 | Filters may set this flag to indicate filter-specific EOF condition. | 272 | Filters may set this flag to indicate filter-specific EOF condition. | |
245 | .It Dv EV_ERROR | 273 | .It Dv EV_ERROR | |
246 | See | 274 | See | |
@@ -279,26 +307,27 @@ to | @@ -279,26 +307,27 @@ to | |||
279 | is ignored. | 307 | is ignored. | |
280 | .El | 308 | .El | |
281 | .Pp | 309 | .Pp | |
282 | The following structure is used to pass arguments in and out of the | 310 | The 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 | |
285 | struct kfilter_mapping { | 313 | struct 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 | |
320 | The predefined system filters are listed below. | |||
292 | Arguments may be passed to and from the filter via the | 321 | Arguments may be passed to and from the filter via the | |
293 | .Va fflags | 322 | .Va fflags | |
294 | and | 323 | and | |
295 | .Va data | 324 | .Va data | |
296 | fields in the kevent structure. | 325 | fields in the kevent structure. | |
297 | .Pp | 326 | .Pp | |
298 | The predefined system filters are: | 327 | The 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 | |
301 | Takes a descriptor as the identifier, and returns whenever | 330 | Takes a descriptor as the identifier, and returns whenever | |
302 | there is data available to read. | 331 | there is data available to read. | |
303 | The behavior of the filter is slightly different depending | 332 | The behavior of the filter is slightly different depending | |
304 | on the descriptor type. | 333 | on 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 | |
330 | If the read direction of the socket has shutdown, then the filter | 359 | If the read direction of the socket has shutdown, then the filter | |
331 | also sets EV_EOF in | 360 | also sets EV_EOF in | |
332 | .Va flags , | 361 | .Va flags , | |
333 | and returns the socket error (if any) in | 362 | and returns the socket error (if any) in | |
334 | .Va fflags . | 363 | .Va fflags . | |
335 | It is possible for EOF to be returned (indicating the connection is gone) | 364 | It is possible for EOF to be returned (indicating the connection is gone) | |
336 | while there is still data pending in the socket buffer. | 365 | while there is still data pending in the socket buffer. | |
337 | .It Vnodes | 366 | .It Vnodes | |
338 | Returns when the file pointer is not at the end of file. | 367 | Returns when the file pointer is not at the end of file. | |
339 | .Va data | 368 | .Va data | |
340 | contains the offset from current position to end of file, | 369 | contains the offset from current position to end of file, | |
341 | and may be negative. | 370 | and 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" | |
343 | Returns when there is data to read; | 380 | Returns when there is data to read; | |
344 | .Va data | 381 | .Va data | |
345 | contains the number of bytes available. | 382 | contains the number of bytes available. | |
346 | .Pp | 383 | .Pp | |
347 | When the last writer disconnects, the filter will set EV_EOF in | 384 | When the last writer disconnects, the filter will set EV_EOF in | |
348 | .Va flags . | 385 | .Va flags . | |
349 | This may be cleared by passing in EV_CLEAR, at which point the | 386 | This may be cleared by passing in EV_CLEAR, at which point the | |
350 | filter will resume waiting for data to become available before | 387 | filter will resume waiting for data to become available before | |
351 | returning. | 388 | returning. | |
389 | .It "BPF devices" | |||
390 | Returns when the BPF buffer is full, the BPF timeout has expired, or | |||
391 | when the BPF has | |||
392 | .Dq immediate mode | |||
393 | enabled and there is any data to read; | |||
394 | .Va data | |||
352 | .El | 395 | .El | |
353 | .It Dv EVFILT_WRITE | 396 | .It Dv EVFILT_WRITE | |
354 | Takes a descriptor as the identifier, and returns whenever | 397 | Takes a descriptor as the identifier, and returns whenever | |
355 | it is possible to write to the descriptor. | 398 | it is possible to write to the descriptor. | |
356 | For sockets, pipes, fifos, and ttys, | 399 | For sockets, pipes, fifos, and ttys, | |
357 | .Va data | 400 | .Va data | |
358 | will contain the amount of space remaining in the write buffer. | 401 | will contain the amount of space remaining in the write buffer. | |
359 | The filter will set EV_EOF when the reader disconnects, and for | 402 | The filter will set EV_EOF when the reader disconnects, and for | |
360 | the fifo case, this may be cleared by use of EV_CLEAR. | 403 | the fifo case, this may be cleared by use of EV_CLEAR. | |
361 | Note that this filter is not supported for vnodes. | 404 | Note that this filter is not supported for vnodes. | |
362 | .Pp | 405 | .Pp | |
363 | For sockets, the low water mark and socket error handling is | 406 | For sockets, the low water mark and socket error handling is | |
364 | identical to the EVFILT_READ case. | 407 | identical 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 . | |
478 | When adding a timer, | 521 | When adding a timer, | |
479 | .Va data | 522 | .Va data | |
480 | specifies the timeout period in milliseconds. | 523 | specifies the timeout period in milliseconds. | |
481 | The timer will be periodic unless EV_ONESHOT is specified. | 524 | The timer will be periodic unless EV_ONESHOT is specified. | |
482 | On return, | 525 | On return, | |
483 | .Va data | 526 | .Va data | |
484 | contains the number of times the timeout has expired since the last call to | 527 | contains the number of times the timeout has expired since the last call to | |
485 | .Fn kevent . | 528 | .Fn kevent . | |
486 | This filter automatically sets the EV_CLEAR flag internally. | 529 | This filter automatically sets the EV_CLEAR flag internally. | |
487 | .It Dv EVFILT_FS | 530 | .It Dv EVFILT_FS | |
488 | Establishes a file system monitor. | 531 | Establishes a file system monitor. | |
489 | Currently it only monitors file system mount and unmount actions. | 532 | Currently it only monitors file system mount and unmount actions. | |
533 | .It Dv EVFILT_USER | |||
534 | Establishes a user event identified by | |||
535 | .Va ident | |||
536 | which is not associated with any kernel mechanism but is triggered by | |||
537 | user level code. | |||
538 | The lower 24 bits of the | |||
539 | .Va fflags | |||
540 | may be used for user defined flags and manipulated using the following: | |||
541 | .Bl -tag -width "Dv NOTE_FFLAGSMASK" | |||
542 | .It Dv NOTE_FFNOP | |||
543 | Ignore the input | |||
544 | .Va fflags . | |||
545 | .It Dv NOTE_FFAND | |||
546 | Bitwise AND | |||
547 | .Va fflags . | |||
548 | .It Dv NOTE_FFOR | |||
549 | Bitwise OR | |||
550 | .Va fflags . | |||
551 | .It Dv NOTE_FFCOPY | |||
552 | Copy | |||
553 | .Va fflags . | |||
554 | .It Dv NOTE_FFCTRLMASK | |||
555 | Control mask for | |||
556 | .Va fflags . | |||
557 | .It Dv NOTE_FFLAGSMASK | |||
558 | User defined flag mask for | |||
559 | .Va fflags . | |||
560 | .El | |||
561 | .Pp | |||
562 | A user event is triggered for output with the following: | |||
563 | .Bl -tag -width "Dv NOTE_FFLAGSMASK" | |||
564 | .It Dv NOTE_TRIGGER | |||
565 | Cause the event to be triggered. | |||
566 | .El | |||
567 | .Pp | |||
568 | On return, | |||
569 | .Va fflags | |||
570 | contains the users defined flags in the lower 24 bits. | |||
490 | .El | 571 | .El | |
572 | .Sh CANCELLATION BEHAVIOUR | |||
573 | If | |||
574 | .Fa nevents | |||
575 | is non-zero, i.e., the function is potentially blocking, the call | |||
576 | is a cancellation point. | |||
577 | Otherwise, i.e., if | |||
578 | .Fa nevents | |||
579 | is zero, the call is not cancellable. | |||
580 | Cancellation can only occur before any changes are made to the kqueue, | |||
581 | or when the call was blocked and no changes to the queue were requested. | |||
491 | .Sh RETURN VALUES | 582 | .Sh RETURN VALUES | |
583 | The | |||
492 | .Fn kqueue | 584 | .Fn kqueue | |
585 | system call | |||
493 | creates a new kernel event queue and returns a file descriptor. | 586 | creates a new kernel event queue and returns a file descriptor. | |
494 | If there was an error creating the kernel event queue, a value of \-1 is | 587 | If there was an error creating the kernel event queue, a value of \-1 is | |
495 | returned and | 588 | returned and | |
496 | .Dv errno | 589 | .Dv errno | |
497 | is set. | 590 | is set. | |
498 | .Pp | 591 | .Pp | |
592 | The | |||
499 | .Fn kevent | 593 | .Fn kevent | |
594 | system call | |||
500 | returns the number of events placed in the | 595 | returns the number of events placed in the | |
501 | .Fa eventlist , | 596 | .Fa eventlist , | |
502 | up to the value given by | 597 | up to the value given by | |
503 | .Fa nevents . | 598 | .Fa nevents . | |
504 | If an error occurs while processing an element of the | 599 | If an error occurs while processing an element of the | |
505 | .Fa changelist | 600 | .Fa changelist | |
506 | and there is enough room in the | 601 | and there is enough room in the | |
507 | .Fa eventlist , | 602 | .Fa eventlist , | |
508 | then the event will be placed in the | 603 | then the event will be placed in the | |
509 | .Fa eventlist | 604 | .Fa eventlist | |
510 | with | 605 | with | |
511 | .Dv EV_ERROR | 606 | .Dv EV_ERROR | |
512 | set in | 607 | set in |
--- 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 | |||
99 | static void filt_kqdetach(struct knote *); | 100 | static void filt_kqdetach(struct knote *); | |
100 | static int filt_kqueue(struct knote *, long hint); | 101 | static int filt_kqueue(struct knote *, long hint); | |
101 | static int filt_procattach(struct knote *); | 102 | static int filt_procattach(struct knote *); | |
102 | static void filt_procdetach(struct knote *); | 103 | static void filt_procdetach(struct knote *); | |
103 | static int filt_proc(struct knote *, long hint); | 104 | static int filt_proc(struct knote *, long hint); | |
104 | static int filt_fileattach(struct knote *); | 105 | static int filt_fileattach(struct knote *); | |
105 | static void filt_timerexpire(void *x); | 106 | static void filt_timerexpire(void *x); | |
106 | static int filt_timerattach(struct knote *); | 107 | static int filt_timerattach(struct knote *); | |
107 | static void filt_timerdetach(struct knote *); | 108 | static void filt_timerdetach(struct knote *); | |
108 | static int filt_timer(struct knote *, long hint); | 109 | static int filt_timer(struct knote *, long hint); | |
109 | static int filt_fsattach(struct knote *kn); | 110 | static int filt_fsattach(struct knote *kn); | |
110 | static void filt_fsdetach(struct knote *kn); | 111 | static void filt_fsdetach(struct knote *kn); | |
111 | static int filt_fs(struct knote *kn, long hint); | 112 | static int filt_fs(struct knote *kn, long hint); | |
113 | static int filt_userattach(struct knote *); | |||
114 | static void filt_userdetach(struct knote *); | |||
115 | static int filt_user(struct knote *, long hint); | |||
116 | static void filt_usertouch(struct knote *, struct kevent *, long type); | |||
112 | 117 | |||
113 | static const struct fileops kqueueops = { | 118 | static 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 | |||
154 | static const struct filterops fs_filtops = { | 159 | static 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 | |||
166 | static 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 | ||||
161 | static u_int kq_ncallouts = 0; | 174 | static u_int kq_ncallouts = 0; | |
162 | static int kq_calloutmax = (4 * 1024); | 175 | static 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 | |||
167 | extern const struct filterops sig_filtops; | 180 | extern 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 */ | |
186 | static struct kfilter sys_kfilters[] = { | 199 | static 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 */ | |
199 | static struct kfilter *user_kfilters; /* array */ | 213 | static struct kfilter *user_kfilters; /* array */ | |
200 | static int user_kfilterc; /* current offset */ | 214 | static int user_kfilterc; /* current offset */ | |
201 | static int user_kfiltermaxc; /* max size so far */ | 215 | static int user_kfiltermaxc; /* max size so far */ | |
202 | static size_t user_kfiltersz; /* size of allocated memory */ | 216 | static 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) | |||
766 | static int | 780 | static int | |
767 | filt_fs(struct knote *kn, long hint) | 781 | filt_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 | |||
793 | static int | |||
794 | filt_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 | ||||
811 | static void | |||
812 | filt_userdetach(struct knote *kn) | |||
813 | { | |||
814 | ||||
815 | /* | |||
816 | * EVFILT_USER knotes are not attached to anything in the kernel. | |||
817 | */ | |||
818 | } | |||
819 | ||||
820 | static int | |||
821 | filt_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 | ||||
833 | static void | |||
834 | filt_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 | */ | |
784 | int | 898 | int | |
785 | filt_seltrue(struct knote *kn, long hint) | 899 | filt_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 | */ | |
801 | static void | 915 | static void | |
802 | filt_seltruedetach(struct knote *kn) | 916 | filt_seltruedetach(struct knote *kn) | |
803 | { | 917 | { | |
804 | /* Nothing to do */ | 918 | /* Nothing to do */ | |
805 | } | 919 | } | |
806 | 920 | |||
807 | const struct filterops seltrue_filtops = { | 921 | const 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 | |||
814 | int | 929 | int | |
815 | seltrue_kqfilter(dev_t dev, struct knote *kn) | 930 | seltrue_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 | */ | |||
1291 | done_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 | } | |
1187 | doneunlock: | 1312 | doneunlock: | |
@@ -1261,27 +1386,27 @@ bad: | @@ -1261,27 +1386,27 @@ bad: | |||
1261 | * as appropriate. | 1386 | * as appropriate. | |
1262 | */ | 1387 | */ | |
1263 | static int | 1388 | static int | |
1264 | kqueue_scan(file_t *fp, size_t maxevents, struct kevent *ulistp, | 1389 | kqueue_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 | } |
--- 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 | |||
49 | struct kevent { | 50 | struct 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 | |||
58 | static __inline void | 59 | static __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 | */ | |
167 | struct filterops { | 197 | struct 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 | */ | |
184 | struct kfilter; | 215 | struct kfilter; | |
185 | 216 | |||
186 | struct knote { | 217 | struct 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" \ |
--- 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 | |||
178 | ATF_TC(kqueue_EVFILT_USER); | |||
179 | ATF_TC_HEAD(kqueue_EVFILT_USER, tc) | |||
180 | { | |||
181 | atf_tc_set_md_var(tc, "descr", "Checks usability of EVFILT_USER"); | |||
182 | } | |||
183 | ||||
184 | ATF_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 | |||
178 | ATF_TP_ADD_TCS(tp) | 210 | ATF_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 | } |