2 * Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 * Copyright (c) 1999,2000 Jonathan Lemon <jlemon@FreeBSD.org>
30 * All rights reserved.
32 * Redistribution and use in source and binary forms, with or without
33 * modification, are permitted provided that the following conditions
35 * 1. Redistributions of source code must retain the above copyright
36 * notice, this list of conditions and the following disclaimer.
37 * 2. Redistributions in binary form must reproduce the above copyright
38 * notice, this list of conditions and the following disclaimer in the
39 * documentation and/or other materials provided with the distribution.
41 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
42 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
53 * $FreeBSD: src/sys/sys/eventvar.h,v 1.1.2.2 2000/07/18 21:49:12 jlemon Exp $
56 #ifndef _SYS_EVENTVAR_H_
57 #define _SYS_EVENTVAR_H_
59 #include <sys/event.h>
60 #include <sys/select.h>
61 #include <kern/kern_types.h>
62 #include <kern/waitq.h>
64 #if defined(XNU_KERNEL_PRIVATE)
66 typedef int (*kevent_callback_t
)(struct kqueue
*, struct kevent_internal_s
*, void *);
67 typedef void (*kqueue_continue_t
)(struct kqueue
*, void *, int);
70 #include <kern/locks.h>
71 #include <sys/pthread_shims.h>
72 #include <mach/thread_policy.h>
77 * The kqueue locking order can follow a few different patterns:
79 * Standard file-based kqueues (from above):
80 * proc fd lock -> kq lock -> kq-waitq-set lock -> thread lock
82 * WorkQ/WorkLoop kqueues (from above):
83 * proc fd lock -> kq lock -> kq-request lock -> pthread kext locks -> thread lock
85 * Whenever kqueues interact with source locks, it drops all of its own
86 * locks in exchange for a use-reference on the knote used to synchronize
87 * with the source code. When those sources post events from below, they
88 * have the following lock hierarchy.
90 * Standard file-based kqueues (from below):
91 * XXX lock -> kq lock -> kq-waitq-set lock -> thread lock
92 * Standard file-based kqueues with non-kq-aware sources (from below):
93 * XXX lock -> kq-waitq-set lock -> thread lock
95 * WorkQ/WorkLoop kqueues (from below):
96 * XXX lock -> kq lock -> kq-request lock -> pthread kext locks -> thread lock
97 * WorkQ/WorkLoop kqueues with non-kq-aware sources (from below):
98 * XXX -> kq-waitq-set lock -> kq-request lock -> pthread kext locks -> thread lock
101 #define KQEXTENT 256 /* linear growth by this amount */
104 * kqueue - common core definition of a kqueue
106 * No real structures are allocated of this type. They are
107 * either kqfile objects or kqworkq objects - each of which is
108 * derived from this definition.
111 struct waitq_set kq_wqs
; /* private waitq set */
112 lck_spin_t kq_lock
; /* kqueue lock */
113 uint16_t kq_state
; /* state of the kq */
114 uint16_t kq_level
; /* nesting level of the kq */
115 uint32_t kq_count
; /* number of queued events */
116 struct proc
*kq_p
; /* process containing kqueue */
117 struct kqtailq kq_queue
[1]; /* variable array of kqtailq structs */
120 #define KQ_SEL 0x001 /* select was recorded for kq */
121 #define KQ_SLEEP 0x002 /* thread is waiting for events */
122 #define KQ_PROCWAIT 0x004 /* thread waiting for processing */
123 #define KQ_KEV32 0x008 /* kq is used with 32-bit events */
124 #define KQ_KEV64 0x010 /* kq is used with 64-bit events */
125 #define KQ_KEV_QOS 0x020 /* kq events carry QoS info */
126 #define KQ_WORKQ 0x040 /* KQ is bound to process workq */
127 #define KQ_WORKLOOP 0x080 /* KQ is part of a workloop */
128 #define KQ_PROCESSING 0x100 /* KQ is being processed */
129 #define KQ_DRAIN 0x200 /* kq is draining */
130 #define KQ_WAKEUP 0x400 /* kq awakened while processing */
131 #define KQ_DYNAMIC 0x800 /* kqueue is dynamically managed */
132 #define KQ_NO_WQ_THREAD 0x1000 /* kq will not have workqueue threads dynamically created */
134 * kqfile - definition of a typical kqueue opened as a file descriptor
135 * via the kqueue() system call.
137 * Adds selinfo support to the base kqueue definition, as these
138 * fds can be fed into select().
141 struct kqueue kqf_kqueue
; /* common kqueue core */
142 struct kqtailq kqf_suppressed
; /* suppression queue */
143 struct selinfo kqf_sel
; /* parent select/kqueue info */
146 #define kqf_wqs kqf_kqueue.kq_wqs
147 #define kqf_lock kqf_kqueue.kq_lock
148 #define kqf_state kqf_kqueue.kq_state
149 #define kqf_level kqf_kqueue.kq_level
150 #define kqf_count kqf_kqueue.kq_count
151 #define kqf_p kqf_kqueue.kq_p
152 #define kqf_queue kqf_kqueue.kq_queue
154 #define QOS_INDEX_KQFILE 0 /* number of qos levels in a file kq */
157 struct kqtailq kqrb_suppressed
; /* Per-QoS suppression queues */
158 thread_t kqrb_thread
; /* thread to satisfy request */
162 * kqrequest - per-QoS thread request status
167 struct kqr_bound kqru_bound
; /* used when thread is bound */
168 struct workq_threadreq_s kqru_req
; /* used when request oustanding */
170 #define kqr_suppressed kqr_u.kqru_bound.kqrb_suppressed
171 #define kqr_thread kqr_u.kqru_bound.kqrb_thread
172 #define kqr_req kqr_u.kqru_req
174 struct kqr_bound kqr_bound
; /* used when thread is bound */
175 struct workq_threadreq_s kqr_req
; /* used when request oustanding */
176 #define kqr_suppressed kqr_bound.kqrb_suppressed
177 #define kqr_thread kqr_bound.kqrb_thread
179 uint8_t kqr_state
; /* KQ/workq interaction state */
180 uint8_t kqr_wakeup_indexes
; /* QoS/override levels that woke */
181 uint16_t kqr_dsync_waiters
:13, /* number of dispatch sync waiters */
182 kqr_dsync_owner_qos
:3; /* Qos override on dispatch sync owner */
183 uint16_t kqr_sync_suppress_count
; /* number of suppressed sync ipc knotes */
184 kq_index_t kqr_stayactive_qos
:3, /* max QoS of statyactive knotes */
185 kqr_owner_override_is_sync
:1, /* sync owner has sync ipc override */
186 kqr_override_index
:3, /* highest wakeup override index */
187 kqr_has_sync_override
:1; /* Qos/override at UI is sync ipc override */
189 /* set under both the kqlock and the filt_wllock */
190 kq_index_t
:0; /* prevent bitfields coalescing <rdar://problem/31854115> */
191 kq_index_t kqr_qos_index
:4, /* QoS for the thread request */
192 kqr_dsync_waiters_qos
:4; /* override from dispatch sync waiters */
196 #define KQR_PROCESSING 0x01 /* requested thread is running the q */
197 #define KQR_THREQUESTED 0x02 /* thread has been requested from workq */
198 #define KQR_WAKEUP 0x04 /* wakeup called during processing */
199 #define KQR_BOUND 0x08 /* servicing thread is bound */
200 #define KQR_THOVERCOMMIT 0x20 /* overcommit needed for thread requests */
201 #define KQR_DRAIN 0x40 /* cancel initiated - drain fulfill */
202 #define KQR_R2K_NOTIF_ARMED 0x80 /* ast notifications armed */
204 * WorkQ kqueues need to request threads to service the triggered
205 * knotes in the queue. These threads are brought up on a
206 * effective-requested-QoS basis. Knotes are segregated based on
207 * that value - calculated by computing max(event-QoS, kevent-QoS).
208 * Only one servicing thread is requested at a time for all the
209 * knotes at a given effective-requested-QoS.
212 #if !defined(KQWQ_QOS_MANAGER)
213 #define KQWQ_QOS_MANAGER (THREAD_QOS_LAST)
216 #if !defined(KQWQ_NQOS)
217 #define KQWQ_NQOS (KQWQ_QOS_MANAGER + 1)
221 * Workq thread start out a particular effective-requested-QoS, but
222 * additional events processed by the filters may represent
223 * backlogged events that may themselves have a higher requested-QoS.
224 * To represent this, the filter may apply an override to a knote's
227 * We further segregate these overridden knotes into different buckets
228 * by <requested, override> grouping. This allows easy matching of
229 * knotes to process vs. the highest workq thread override applied.
231 * Only certain override patterns need to be supported. A knote
232 * cannot have an effective-requested-QoS of UNSPECIFIED - because
233 * the kevent->qos (when canonicalized) will always be above that
234 * or indicate manager. And we don't allow an override to specify
235 * manager. This results in the following buckets being needed:
237 * Effective-Requested QoS
238 * MAINT BG UTIL DEFAULT UINIT UINTER MANAGER
245 * UINTER 5 10 14 17 19 20
248 #if !defined(KQWQ_NBUCKETS)
249 #define KQWQ_NBUCKETS 22
253 * kqworkq - definition of a private kqueue used to coordinate event
254 * handling for pthread work queues.
256 * These have per-qos processing queues and state to coordinate with
257 * the pthread kext to ask for threads at corresponding pthread priority
261 struct kqueue kqwq_kqueue
;
262 struct kqtailq kqwq_queuecont
[KQWQ_NBUCKETS
-1]; /* continue array of queues */
263 struct kqrequest kqwq_request
[KQWQ_NQOS
]; /* per-QoS request states */
264 lck_spin_t kqwq_reqlock
; /* kqueue request lock */
267 #define kqwq_wqs kqwq_kqueue.kq_wqs
268 #define kqwq_lock kqwq_kqueue.kq_lock
269 #define kqwq_state kqwq_kqueue.kq_state
270 #define kqwq_level kqwq_kqueue.kq_level
271 #define kqwq_count kqwq_kqueue.kq_count
272 #define kqwq_p kqwq_kqueue.kq_p
273 #define kqwq_queue kqwq_kqueue.kq_queue
275 #define kqwq_req_lock(kqwq) lck_spin_lock(&kqwq->kqwq_reqlock)
276 #define kqwq_req_unlock(kqwq) lck_spin_unlock(&kqwq->kqwq_reqlock)
277 #define kqwq_req_held(kqwq) LCK_SPIN_ASSERT(&kqwq->kqwq_reqlock, LCK_ASSERT_OWNED)
279 #define KQWQ_THMANAGER 0x10 /* expect manager thread to run the queue */
282 * WorkLoop kqueues need to request a thread to service the triggered
283 * knotes in the queue. The thread is brought up on a
284 * effective-requested-QoS basis. Knotes are segregated based on
285 * that value. Once a request is made, it cannot be undone. If
286 * events with higher QoS arrive after, they are stored in their
287 * own queues and an override applied to the original request based
288 * on the delta between the two QoS values.
292 * "Stay-active" knotes are held in a separate bucket that indicates
293 * special handling required. They are kept separate because the
294 * wakeups issued to them don't have context to tell us where to go
295 * to find and process them. All processing of them happens at the
296 * highest QoS. Unlike WorkQ kqueues, there is no special singular
297 * "manager thread" for a process. We simply request a servicing
298 * thread at the higest known QoS when these are woken (or override
299 * an existing request to that).
301 #define KQWL_BUCKET_STAYACTIVE (THREAD_QOS_LAST)
303 #if !defined(KQWL_NBUCKETS)
304 #define KQWL_NBUCKETS (KQWL_BUCKET_STAYACTIVE + 1)
308 * kqworkloop - definition of a private kqueue used to coordinate event
309 * handling for pthread workloops.
311 * Workloops vary from workqs in that only a single thread is ever
312 * requested to service a workloop at a time. But unlike workqs,
313 * workloops may be "owned" by user-space threads that are
314 * synchronously draining an event off the workloop. In those cases,
315 * any overrides have to be applied to the owner until it relinqueshes
318 * NOTE: "lane" support is TBD.
321 struct kqueue kqwl_kqueue
; /* queue of events */
322 struct kqtailq kqwl_queuecont
[KQWL_NBUCKETS
-1]; /* continue array of queues */
323 struct kqrequest kqwl_request
; /* thread request state */
324 lck_spin_t kqwl_reqlock
; /* kqueue request lock */
325 lck_mtx_t kqwl_statelock
; /* state/debounce lock */
326 thread_t kqwl_owner
; /* current [sync] owner thread */
327 uint32_t kqwl_retains
; /* retain references */
328 kqueue_id_t kqwl_dynamicid
; /* dynamic identity */
329 SLIST_ENTRY(kqworkloop
) kqwl_hashlink
; /* linkage for search list */
332 SLIST_HEAD(kqlist
, kqworkloop
);
334 #define kqwl_wqs kqwl_kqueue.kq_wqs
335 #define kqwl_lock kqwl_kqueue.kq_lock
336 #define kqwl_state kqwl_kqueue.kq_state
337 #define kqwl_level kqwl_kqueue.kq_level
338 #define kqwl_count kqwl_kqueue.kq_count
339 #define kqwl_p kqwl_kqueue.kq_p
340 #define kqwl_queue kqwl_kqueue.kq_queue
342 #define kqwl_req_lock(kqwl) lck_spin_lock(&kqwl->kqwl_reqlock)
343 #define kqwl_req_unlock(kqwl) lck_spin_unlock(&kqwl->kqwl_reqlock)
344 #define kqwl_req_held(kqwl) LCK_SPIN_ASSERT(&kqwl->kqwl_reqlock, LCK_ASSERT_OWNED)
346 #define KQ_WORKLOOP_RETAINS_MAX UINT32_MAX
348 extern int workloop_fulfill_threadreq(struct proc
*p
, workq_threadreq_t req
, thread_t thread
, int flags
);
350 extern struct kqueue
*kqueue_alloc(struct proc
*, unsigned int);
351 extern void kqueue_dealloc(struct kqueue
*);
353 extern void knotes_dealloc(struct proc
*);
355 extern void kevent_register(struct kqueue
*, struct kevent_internal_s
*, struct proc
*);
356 extern int kqueue_scan(struct kqueue
*, kevent_callback_t
, kqueue_continue_t
,
357 void *, struct filt_process_s
*, struct timeval
*, struct proc
*);
358 extern int kqueue_stat(struct kqueue
*, void *, int, proc_t
);
360 #endif /* XNU_KERNEL_PRIVATE */
362 #endif /* !_SYS_EVENTVAR_H_ */