1*043036a2SApple OSS Distributions /*
2*043036a2SApple OSS Distributions * Copyright (c) 2018 Apple Inc. All rights reserved.
3*043036a2SApple OSS Distributions *
4*043036a2SApple OSS Distributions * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5*043036a2SApple OSS Distributions *
6*043036a2SApple OSS Distributions * This file contains Original Code and/or Modifications of Original Code
7*043036a2SApple OSS Distributions * as defined in and that are subject to the Apple Public Source License
8*043036a2SApple OSS Distributions * Version 2.0 (the 'License'). You may not use this file except in
9*043036a2SApple OSS Distributions * compliance with the License. The rights granted to you under the License
10*043036a2SApple OSS Distributions * may not be used to create, or enable the creation or redistribution of,
11*043036a2SApple OSS Distributions * unlawful or unlicensed copies of an Apple operating system, or to
12*043036a2SApple OSS Distributions * circumvent, violate, or enable the circumvention or violation of, any
13*043036a2SApple OSS Distributions * terms of an Apple operating system software license agreement.
14*043036a2SApple OSS Distributions *
15*043036a2SApple OSS Distributions * Please obtain a copy of the License at
16*043036a2SApple OSS Distributions * http://www.opensource.apple.com/apsl/ and read it before using this file.
17*043036a2SApple OSS Distributions *
18*043036a2SApple OSS Distributions * The Original Code and all software distributed under the License are
19*043036a2SApple OSS Distributions * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20*043036a2SApple OSS Distributions * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21*043036a2SApple OSS Distributions * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22*043036a2SApple OSS Distributions * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23*043036a2SApple OSS Distributions * Please see the License for the specific language governing rights and
24*043036a2SApple OSS Distributions * limitations under the License.
25*043036a2SApple OSS Distributions *
26*043036a2SApple OSS Distributions * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27*043036a2SApple OSS Distributions */
28*043036a2SApple OSS Distributions
29*043036a2SApple OSS Distributions #ifndef _KERN_MPSC_QUEUE_H_
30*043036a2SApple OSS Distributions #define _KERN_MPSC_QUEUE_H_
31*043036a2SApple OSS Distributions
32*043036a2SApple OSS Distributions #ifdef XNU_KERNEL_PRIVATE
33*043036a2SApple OSS Distributions
34*043036a2SApple OSS Distributions #include <machine/atomic.h>
35*043036a2SApple OSS Distributions #include <kern/macro_help.h>
36*043036a2SApple OSS Distributions #include <kern/thread_call.h>
37*043036a2SApple OSS Distributions
38*043036a2SApple OSS Distributions #endif // XNU_KERNEL_PRIVATE
39*043036a2SApple OSS Distributions
40*043036a2SApple OSS Distributions #include <sys/cdefs.h>
41*043036a2SApple OSS Distributions
42*043036a2SApple OSS Distributions __BEGIN_DECLS __ASSUME_PTR_ABI_SINGLE_BEGIN
43*043036a2SApple OSS Distributions
44*043036a2SApple OSS Distributions /*!
45*043036a2SApple OSS Distributions * @typedef struct mpsc_queue_chain
46*043036a2SApple OSS Distributions *
47*043036a2SApple OSS Distributions * @brief
48*043036a2SApple OSS Distributions * Type for the intrusive linkage used by MPSC queues.
49*043036a2SApple OSS Distributions */
50*043036a2SApple OSS Distributions typedef struct mpsc_queue_chain {
51*043036a2SApple OSS Distributions #if __has_ptrcheck // work around 78354145
52*043036a2SApple OSS Distributions struct mpsc_queue_chain *volatile mpqc_next;
53*043036a2SApple OSS Distributions #else
54*043036a2SApple OSS Distributions struct mpsc_queue_chain *_Atomic mpqc_next;
55*043036a2SApple OSS Distributions #endif
56*043036a2SApple OSS Distributions } *mpsc_queue_chain_t;
57*043036a2SApple OSS Distributions
58*043036a2SApple OSS Distributions /*!
59*043036a2SApple OSS Distributions * @typedef struct mpsc_queue_head
60*043036a2SApple OSS Distributions *
61*043036a2SApple OSS Distributions * @brief
62*043036a2SApple OSS Distributions * The type for a multi-producer single-consumer queue.
63*043036a2SApple OSS Distributions *
64*043036a2SApple OSS Distributions * @discussion
65*043036a2SApple OSS Distributions * MPSC queues allow for producers to not be affected by other producers or the
66*043036a2SApple OSS Distributions * consumer. Which means in turn that having producers in interrupt context
67*043036a2SApple OSS Distributions * does not require that other producers disable interrupts like a traditional
68*043036a2SApple OSS Distributions * spinlock based approach would require.
69*043036a2SApple OSS Distributions *
70*043036a2SApple OSS Distributions * These queues shine when data is produced from the entire system and is
71*043036a2SApple OSS Distributions * consumed from a single serial context (logging, tracing, ...).
72*043036a2SApple OSS Distributions * mpsc_daemon_queue_t is provided as a fully ready/easy-to-use pre-packaged
73*043036a2SApple OSS Distributions * solution for these common use cases.
74*043036a2SApple OSS Distributions *
75*043036a2SApple OSS Distributions * - mpsc_queue_append() can be used to append a single item
76*043036a2SApple OSS Distributions * - mpsc_queue_append_list() can be used to append a batch of items at once.
77*043036a2SApple OSS Distributions *
78*043036a2SApple OSS Distributions * Functions for the consumer side assume proper serialization that is not
79*043036a2SApple OSS Distributions * provided by the MPSC queue itself. Dequeuing doesn't require preemption
80*043036a2SApple OSS Distributions * to be disabled.
81*043036a2SApple OSS Distributions *
82*043036a2SApple OSS Distributions * <h2>Algorithm</h2>
83*043036a2SApple OSS Distributions *
84*043036a2SApple OSS Distributions * The base of the enqueue algorithm is a single atomic exchange (first half,
85*043036a2SApple OSS Distributions * called __mpsc_queue_append_update_tail) and a list fixup (2nd half, called
86*043036a2SApple OSS Distributions * __mpsc_queue_append_update_prev).
87*043036a2SApple OSS Distributions *
88*043036a2SApple OSS Distributions * Graphically, enqueuing `X` looks like this, with each step being done
89*043036a2SApple OSS Distributions * atomically (for the empty queue case, `tail` points to `head`):
90*043036a2SApple OSS Distributions *
91*043036a2SApple OSS Distributions * | orig state | update_tail | update_prev |
92*043036a2SApple OSS Distributions * +---------------------+---------------------+---------------------+
93*043036a2SApple OSS Distributions * | | | |
94*043036a2SApple OSS Distributions * | head -> e1 -> e2 -. | head -> e1 -> e2 -. | head -> e1 -> e2 -. |
95*043036a2SApple OSS Distributions * | | | | | | |
96*043036a2SApple OSS Distributions * | ,- ... <--' | ,- ... <--' | ,- ... <--' |
97*043036a2SApple OSS Distributions * | | | | | | |
98*043036a2SApple OSS Distributions * | v | v | v |
99*043036a2SApple OSS Distributions * | tail -> eN -> NULL | tail eN -> NULL | tail eN |
100*043036a2SApple OSS Distributions * | | | | | | |
101*043036a2SApple OSS Distributions * | | | | | v |
102*043036a2SApple OSS Distributions * | X -> NULL | `---> X -> NULL | '---> X -> NULL |
103*043036a2SApple OSS Distributions * | | | |
104*043036a2SApple OSS Distributions * +---------------------+---------------------+---------------------+
105*043036a2SApple OSS Distributions *
106*043036a2SApple OSS Distributions *
107*043036a2SApple OSS Distributions * There is a small 1-instruction gap of inconsistency which makes the chosen
108*043036a2SApple OSS Distributions * algorithm non linearizable, and requires enqueuers to disable preemption
109*043036a2SApple OSS Distributions * during the enqueue so as not to starve the consumer forever.
110*043036a2SApple OSS Distributions *
111*043036a2SApple OSS Distributions * As far as memory visibility is concerned, enqueuing uses a release fence in
112*043036a2SApple OSS Distributions * update_tail which pairs with memory fences in mpsc_queue_dequeue_batch().
113*043036a2SApple OSS Distributions *
114*043036a2SApple OSS Distributions * Note: as far as the data structure in memory, its layout is equivalent to
115*043036a2SApple OSS Distributions * a BSD <sys/queue.h> STAILQ. However because of this inconsistency
116*043036a2SApple OSS Distributions * window and memory ordering concerns, it is incorrect to use STAILQ
117*043036a2SApple OSS Distributions * macros on an MPSC queue.
118*043036a2SApple OSS Distributions */
119*043036a2SApple OSS Distributions typedef struct mpsc_queue_head {
120*043036a2SApple OSS Distributions struct mpsc_queue_chain mpqh_head;
121*043036a2SApple OSS Distributions #if __has_ptrcheck // work around 78354145
122*043036a2SApple OSS Distributions struct mpsc_queue_chain *volatile mpqh_tail;
123*043036a2SApple OSS Distributions #else
124*043036a2SApple OSS Distributions struct mpsc_queue_chain *_Atomic mpqh_tail;
125*043036a2SApple OSS Distributions #endif
126*043036a2SApple OSS Distributions } *mpsc_queue_head_t;
127*043036a2SApple OSS Distributions
128*043036a2SApple OSS Distributions /*!
129*043036a2SApple OSS Distributions * @macro MPSC_QUEUE_INITIALIZER
130*043036a2SApple OSS Distributions *
131*043036a2SApple OSS Distributions * @brief
132*043036a2SApple OSS Distributions * Macro to use in static initializers for mpsc queues.
133*043036a2SApple OSS Distributions *
134*043036a2SApple OSS Distributions * @param head
135*043036a2SApple OSS Distributions * The name of the variable to initialize.
136*043036a2SApple OSS Distributions */
137*043036a2SApple OSS Distributions #define MPSC_QUEUE_INITIALIZER(head) { .mpqh_tail = &(head).mpqh_head }
138*043036a2SApple OSS Distributions
139*043036a2SApple OSS Distributions #ifdef XNU_KERNEL_PRIVATE
140*043036a2SApple OSS Distributions
141*043036a2SApple OSS Distributions /*!
142*043036a2SApple OSS Distributions * @function mpsc_queue_init
143*043036a2SApple OSS Distributions *
144*043036a2SApple OSS Distributions * @brief
145*043036a2SApple OSS Distributions * Dynamically initialize an mpsc queue.
146*043036a2SApple OSS Distributions *
147*043036a2SApple OSS Distributions * @discussion
148*043036a2SApple OSS Distributions * This initialization assumes that the object holding the queue head
149*043036a2SApple OSS Distributions * is initialized before it can be made visible to other threads/cores.
150*043036a2SApple OSS Distributions *
151*043036a2SApple OSS Distributions * @param q
152*043036a2SApple OSS Distributions * The queue to initialize.
153*043036a2SApple OSS Distributions */
154*043036a2SApple OSS Distributions static inline void
mpsc_queue_init(mpsc_queue_head_t q)155*043036a2SApple OSS Distributions mpsc_queue_init(mpsc_queue_head_t q)
156*043036a2SApple OSS Distributions {
157*043036a2SApple OSS Distributions os_atomic_init(&q->mpqh_head.mpqc_next, NULL);
158*043036a2SApple OSS Distributions os_atomic_init(&q->mpqh_tail, &q->mpqh_head);
159*043036a2SApple OSS Distributions }
160*043036a2SApple OSS Distributions
161*043036a2SApple OSS Distributions /*!
162*043036a2SApple OSS Distributions * @typedef enum mpsc_queue_options
163*043036a2SApple OSS Distributions */
164*043036a2SApple OSS Distributions typedef enum mpsc_queue_options {
165*043036a2SApple OSS Distributions MPSC_QUEUE_NONE = 0,
166*043036a2SApple OSS Distributions MPSC_QUEUE_DISABLE_PREEMPTION = 1 << 0,
167*043036a2SApple OSS Distributions } mpsc_queue_options_t;
168*043036a2SApple OSS Distributions
169*043036a2SApple OSS Distributions /*!
170*043036a2SApple OSS Distributions * @const MPSC_QUEUE_NOTQUEUED_MARKER
171*043036a2SApple OSS Distributions *
172*043036a2SApple OSS Distributions * @brief
173*043036a2SApple OSS Distributions * Magical marker that implementations can use to poison the chain pointer of
174*043036a2SApple OSS Distributions * elements not on any MPSC queue.
175*043036a2SApple OSS Distributions */
176*043036a2SApple OSS Distributions #define MPSC_QUEUE_NOTQUEUED_MARKER ((mpsc_queue_chain_t)~0ul)
177*043036a2SApple OSS Distributions
178*043036a2SApple OSS Distributions /*!
179*043036a2SApple OSS Distributions * @macro mpsc_queue_element
180*043036a2SApple OSS Distributions *
181*043036a2SApple OSS Distributions * @brief
182*043036a2SApple OSS Distributions * Macro to find the pointer of an element back from its MPSC chain linkage.
183*043036a2SApple OSS Distributions */
184*043036a2SApple OSS Distributions #define mpsc_queue_element(ptr, type, field) __container_of(ptr, type, field)
185*043036a2SApple OSS Distributions
186*043036a2SApple OSS Distributions
187*043036a2SApple OSS Distributions #pragma mark Advanced Multi Producer calls
188*043036a2SApple OSS Distributions
189*043036a2SApple OSS Distributions /**
190*043036a2SApple OSS Distributions * @function __mpsc_queue_append_update_tail
191*043036a2SApple OSS Distributions *
192*043036a2SApple OSS Distributions * @brief
193*043036a2SApple OSS Distributions * First half of the enqueue operation onto a multi-producer single-consumer
194*043036a2SApple OSS Distributions * queue.
195*043036a2SApple OSS Distributions *
196*043036a2SApple OSS Distributions * @discussion
197*043036a2SApple OSS Distributions * This function is available for algorithms that need to do things (such as
198*043036a2SApple OSS Distributions * taking a refcount) before calling __mpsc_queue_append_update_prev().
199*043036a2SApple OSS Distributions *
200*043036a2SApple OSS Distributions * Preemption should be disabled before calling
201*043036a2SApple OSS Distributions * __mpsc_queue_append_update_tail(), and until
202*043036a2SApple OSS Distributions * __mpsc_queue_append_update_prev() has returned.
203*043036a2SApple OSS Distributions *
204*043036a2SApple OSS Distributions * @param q
205*043036a2SApple OSS Distributions * The queue to update.
206*043036a2SApple OSS Distributions *
207*043036a2SApple OSS Distributions * @param elm
208*043036a2SApple OSS Distributions * The element to append to `q`.
209*043036a2SApple OSS Distributions *
210*043036a2SApple OSS Distributions * @returns
211*043036a2SApple OSS Distributions * A token to later pass to __mpsc_queue_append_update_prev()
212*043036a2SApple OSS Distributions * to complete the enqueue.
213*043036a2SApple OSS Distributions */
214*043036a2SApple OSS Distributions static inline mpsc_queue_chain_t
__mpsc_queue_append_update_tail(mpsc_queue_head_t q,mpsc_queue_chain_t elm)215*043036a2SApple OSS Distributions __mpsc_queue_append_update_tail(mpsc_queue_head_t q, mpsc_queue_chain_t elm)
216*043036a2SApple OSS Distributions {
217*043036a2SApple OSS Distributions os_atomic_store(&elm->mpqc_next, (struct mpsc_queue_chain *__single)NULL, relaxed);
218*043036a2SApple OSS Distributions return os_atomic_xchg(&q->mpqh_tail, elm, release);
219*043036a2SApple OSS Distributions }
220*043036a2SApple OSS Distributions
221*043036a2SApple OSS Distributions /**
222*043036a2SApple OSS Distributions * @function __mpsc_queue_append_was_empty
223*043036a2SApple OSS Distributions *
224*043036a2SApple OSS Distributions * @brief
225*043036a2SApple OSS Distributions * Tests whether the queue was empty at the time
226*043036a2SApple OSS Distributions * __mpsc_queue_append_update_tail() was called.
227*043036a2SApple OSS Distributions *
228*043036a2SApple OSS Distributions * @param q
229*043036a2SApple OSS Distributions * The queue to test emptiness for.
230*043036a2SApple OSS Distributions *
231*043036a2SApple OSS Distributions * @param prev
232*043036a2SApple OSS Distributions * The token returned by __mpsc_queue_append_update_tail().
233*043036a2SApple OSS Distributions *
234*043036a2SApple OSS Distributions * @returns
235*043036a2SApple OSS Distributions * Whether the queue was empty (true) or not (false).
236*043036a2SApple OSS Distributions */
237*043036a2SApple OSS Distributions static inline bool
__mpsc_queue_append_was_empty(mpsc_queue_head_t q,mpsc_queue_chain_t prev)238*043036a2SApple OSS Distributions __mpsc_queue_append_was_empty(mpsc_queue_head_t q, mpsc_queue_chain_t prev)
239*043036a2SApple OSS Distributions {
240*043036a2SApple OSS Distributions return &q->mpqh_head == prev;
241*043036a2SApple OSS Distributions }
242*043036a2SApple OSS Distributions
243*043036a2SApple OSS Distributions /**
244*043036a2SApple OSS Distributions * @function __mpsc_queue_append_update_prev
245*043036a2SApple OSS Distributions *
246*043036a2SApple OSS Distributions * @brief
247*043036a2SApple OSS Distributions * Second half of the enqueue operation onto a multi-producer single-consumer
248*043036a2SApple OSS Distributions * queue.
249*043036a2SApple OSS Distributions *
250*043036a2SApple OSS Distributions * @discussion
251*043036a2SApple OSS Distributions * This function is available for algorithms that need to do things (such as
252*043036a2SApple OSS Distributions * taking a refcount) before calling __mpsc_queue_append_update_prev().
253*043036a2SApple OSS Distributions *
254*043036a2SApple OSS Distributions * Preemption should be disabled before calling
255*043036a2SApple OSS Distributions * __mpsc_queue_append_update_tail(), and until
256*043036a2SApple OSS Distributions * __mpsc_queue_append_update_prev() has returned.
257*043036a2SApple OSS Distributions *
258*043036a2SApple OSS Distributions * @param prev
259*043036a2SApple OSS Distributions * The token returned by __mpsc_queue_append_update_tail().
260*043036a2SApple OSS Distributions *
261*043036a2SApple OSS Distributions * @param elm
262*043036a2SApple OSS Distributions * The element to append to the queue.
263*043036a2SApple OSS Distributions */
264*043036a2SApple OSS Distributions static inline void
__mpsc_queue_append_update_prev(mpsc_queue_chain_t prev,mpsc_queue_chain_t elm)265*043036a2SApple OSS Distributions __mpsc_queue_append_update_prev(mpsc_queue_chain_t prev, mpsc_queue_chain_t elm)
266*043036a2SApple OSS Distributions {
267*043036a2SApple OSS Distributions os_atomic_store(&prev->mpqc_next, elm, relaxed);
268*043036a2SApple OSS Distributions }
269*043036a2SApple OSS Distributions
270*043036a2SApple OSS Distributions
271*043036a2SApple OSS Distributions #pragma mark Multi Producer calls
272*043036a2SApple OSS Distributions
273*043036a2SApple OSS Distributions /**
274*043036a2SApple OSS Distributions * @function mpsc_queue_append_list
275*043036a2SApple OSS Distributions *
276*043036a2SApple OSS Distributions * @brief
277*043036a2SApple OSS Distributions * Enqueues a list of elements onto a queue.
278*043036a2SApple OSS Distributions *
279*043036a2SApple OSS Distributions * @discussion
280*043036a2SApple OSS Distributions * This enqueues a list that has to be fully formed from `first` to `last`
281*043036a2SApple OSS Distributions * at the end of `q`.
282*043036a2SApple OSS Distributions *
283*043036a2SApple OSS Distributions * Preemption should be disabled when calling mpsc_queue_append_list().
284*043036a2SApple OSS Distributions *
285*043036a2SApple OSS Distributions * @param q
286*043036a2SApple OSS Distributions * The queue to update.
287*043036a2SApple OSS Distributions *
288*043036a2SApple OSS Distributions * @param first
289*043036a2SApple OSS Distributions * The first of the list elements being appended.
290*043036a2SApple OSS Distributions *
291*043036a2SApple OSS Distributions * @param last
292*043036a2SApple OSS Distributions * The last of the list elements being appended.
293*043036a2SApple OSS Distributions */
294*043036a2SApple OSS Distributions static inline bool
mpsc_queue_append_list(mpsc_queue_head_t q,mpsc_queue_chain_t first,mpsc_queue_chain_t last)295*043036a2SApple OSS Distributions mpsc_queue_append_list(mpsc_queue_head_t q, mpsc_queue_chain_t first,
296*043036a2SApple OSS Distributions mpsc_queue_chain_t last)
297*043036a2SApple OSS Distributions {
298*043036a2SApple OSS Distributions mpsc_queue_chain_t prev = __mpsc_queue_append_update_tail(q, last);
299*043036a2SApple OSS Distributions __mpsc_queue_append_update_prev(prev, first);
300*043036a2SApple OSS Distributions return __mpsc_queue_append_was_empty(q, prev);
301*043036a2SApple OSS Distributions }
302*043036a2SApple OSS Distributions
303*043036a2SApple OSS Distributions /**
304*043036a2SApple OSS Distributions * @function mpsc_queue_append
305*043036a2SApple OSS Distributions *
306*043036a2SApple OSS Distributions * @brief
307*043036a2SApple OSS Distributions * Enqueues an element onto a queue.
308*043036a2SApple OSS Distributions *
309*043036a2SApple OSS Distributions * @discussion
310*043036a2SApple OSS Distributions * Preemption should be disabled when calling mpsc_queue_append().
311*043036a2SApple OSS Distributions *
312*043036a2SApple OSS Distributions * @param q the queue to update
313*043036a2SApple OSS Distributions * @param elm the element to append
314*043036a2SApple OSS Distributions */
315*043036a2SApple OSS Distributions static inline bool
mpsc_queue_append(mpsc_queue_head_t q,mpsc_queue_chain_t elm)316*043036a2SApple OSS Distributions mpsc_queue_append(mpsc_queue_head_t q, mpsc_queue_chain_t elm)
317*043036a2SApple OSS Distributions {
318*043036a2SApple OSS Distributions return mpsc_queue_append_list(q, elm, elm);
319*043036a2SApple OSS Distributions }
320*043036a2SApple OSS Distributions
321*043036a2SApple OSS Distributions
322*043036a2SApple OSS Distributions #pragma mark Single Consumer calls
323*043036a2SApple OSS Distributions
324*043036a2SApple OSS Distributions /**
325*043036a2SApple OSS Distributions * @function mpsc_queue_dequeue_batch()
326*043036a2SApple OSS Distributions *
327*043036a2SApple OSS Distributions * @brief
328*043036a2SApple OSS Distributions * Atomically empty a queue at once and return the batch head and tail.
329*043036a2SApple OSS Distributions *
330*043036a2SApple OSS Distributions * @discussion
331*043036a2SApple OSS Distributions * Consumer function, must be called in a serialized way with respect to any
332*043036a2SApple OSS Distributions * other consumer function.
333*043036a2SApple OSS Distributions *
334*043036a2SApple OSS Distributions * @param q
335*043036a2SApple OSS Distributions * The queue
336*043036a2SApple OSS Distributions *
337*043036a2SApple OSS Distributions * @param tail
338*043036a2SApple OSS Distributions * An out pointer filled with the last element captured.
339*043036a2SApple OSS Distributions *
340*043036a2SApple OSS Distributions * @param dependency
341*043036a2SApple OSS Distributions * A dependency token (to rely on consume / hardware dependencies)
342*043036a2SApple OSS Distributions * When not trying to take advantage of hardware dependencies, just pass NULL.
343*043036a2SApple OSS Distributions *
344*043036a2SApple OSS Distributions * @returns
345*043036a2SApple OSS Distributions * The first element of the batch if any, or NULL the queue was empty.
346*043036a2SApple OSS Distributions */
347*043036a2SApple OSS Distributions mpsc_queue_chain_t
348*043036a2SApple OSS Distributions mpsc_queue_dequeue_batch(mpsc_queue_head_t q, mpsc_queue_chain_t *tail,
349*043036a2SApple OSS Distributions os_atomic_dependency_t dependency);
350*043036a2SApple OSS Distributions
351*043036a2SApple OSS Distributions /**
352*043036a2SApple OSS Distributions * @function mpsc_queue_batch_next()
353*043036a2SApple OSS Distributions *
354*043036a2SApple OSS Distributions * @brief
355*043036a2SApple OSS Distributions * Function used to consume an element from a batch dequeued with
356*043036a2SApple OSS Distributions * mpsc_queue_dequeue_batch().
357*043036a2SApple OSS Distributions *
358*043036a2SApple OSS Distributions * @discussion
359*043036a2SApple OSS Distributions * Once a batch has been dequeued, there is no need to hold the consumer lock
360*043036a2SApple OSS Distributions * anymore to consume it.
361*043036a2SApple OSS Distributions *
362*043036a2SApple OSS Distributions * mpsc_queue_batch_foreach_safe() is the preferred interface to consume
363*043036a2SApple OSS Distributions * the whole batch.
364*043036a2SApple OSS Distributions *
365*043036a2SApple OSS Distributions * @param cur
366*043036a2SApple OSS Distributions * The current inspected element of the batch (must be the batch head or
367*043036a2SApple OSS Distributions * a value returned by mpsc_queue_batch_next()).
368*043036a2SApple OSS Distributions *
369*043036a2SApple OSS Distributions * @param tail
370*043036a2SApple OSS Distributions * The last element of the batch.
371*043036a2SApple OSS Distributions *
372*043036a2SApple OSS Distributions * @returns
373*043036a2SApple OSS Distributions * The next element if any.
374*043036a2SApple OSS Distributions */
375*043036a2SApple OSS Distributions mpsc_queue_chain_t
376*043036a2SApple OSS Distributions mpsc_queue_batch_next(mpsc_queue_chain_t cur, mpsc_queue_chain_t tail);
377*043036a2SApple OSS Distributions
378*043036a2SApple OSS Distributions /**
379*043036a2SApple OSS Distributions * @macro mpsc_queue_batch_foreach_safe
380*043036a2SApple OSS Distributions *
381*043036a2SApple OSS Distributions * @brief
382*043036a2SApple OSS Distributions * Macro used to enumerate a batch dequeued with mpsc_queue_dequeue_batch().
383*043036a2SApple OSS Distributions *
384*043036a2SApple OSS Distributions * @param item
385*043036a2SApple OSS Distributions * The item being currently visited.
386*043036a2SApple OSS Distributions *
387*043036a2SApple OSS Distributions * @param head
388*043036a2SApple OSS Distributions * The first element of the batch.
389*043036a2SApple OSS Distributions *
390*043036a2SApple OSS Distributions * @param tail
391*043036a2SApple OSS Distributions * The last element of the batch.
392*043036a2SApple OSS Distributions */
393*043036a2SApple OSS Distributions #define mpsc_queue_batch_foreach_safe(item, head, tail) \
394*043036a2SApple OSS Distributions for (mpsc_queue_chain_t __tmp, __item = (head), __tail = (tail); \
395*043036a2SApple OSS Distributions __tmp = mpsc_queue_batch_next(__item, __tail), (item) = __item; \
396*043036a2SApple OSS Distributions __item = __tmp)
397*043036a2SApple OSS Distributions
398*043036a2SApple OSS Distributions /**
399*043036a2SApple OSS Distributions * @function mpsc_queue_restore_batch()
400*043036a2SApple OSS Distributions *
401*043036a2SApple OSS Distributions * @brief
402*043036a2SApple OSS Distributions * "Restore"s a batch at the head of the queue.
403*043036a2SApple OSS Distributions *
404*043036a2SApple OSS Distributions * @discussion
405*043036a2SApple OSS Distributions * Consumer function, must be called in a serialized way with respect to any
406*043036a2SApple OSS Distributions * other consumer function.
407*043036a2SApple OSS Distributions *
408*043036a2SApple OSS Distributions * @param q
409*043036a2SApple OSS Distributions * The queue
410*043036a2SApple OSS Distributions *
411*043036a2SApple OSS Distributions * @param first
412*043036a2SApple OSS Distributions * The first element to put back.
413*043036a2SApple OSS Distributions *
414*043036a2SApple OSS Distributions * @param last
415*043036a2SApple OSS Distributions * The last element to put back.
416*043036a2SApple OSS Distributions * It is the responsibility of the caller to ensure the linkages from first to
417*043036a2SApple OSS Distributions * last are properly set up before calling this function.
418*043036a2SApple OSS Distributions */
419*043036a2SApple OSS Distributions void
420*043036a2SApple OSS Distributions mpsc_queue_restore_batch(mpsc_queue_head_t q, mpsc_queue_chain_t first,
421*043036a2SApple OSS Distributions mpsc_queue_chain_t last);
422*043036a2SApple OSS Distributions
423*043036a2SApple OSS Distributions
424*043036a2SApple OSS Distributions #pragma mark "GCD"-like facilities
425*043036a2SApple OSS Distributions
426*043036a2SApple OSS Distributions /*!
427*043036a2SApple OSS Distributions * @typedef enum mpsc_daemon_init_options
428*043036a2SApple OSS Distributions *
429*043036a2SApple OSS Distributions * @const MPSC_DAEMON_INIT_NONE
430*043036a2SApple OSS Distributions * Default options (no specific behavior)
431*043036a2SApple OSS Distributions *
432*043036a2SApple OSS Distributions * @const MPSC_DAEMON_INIT_INACTIVE
433*043036a2SApple OSS Distributions * Create the queue inactive, which requires an explicit call
434*043036a2SApple OSS Distributions * to @c mpsc_daemon_queue_activate() to start draining.
435*043036a2SApple OSS Distributions *
436*043036a2SApple OSS Distributions */
437*043036a2SApple OSS Distributions __options_decl(mpsc_daemon_init_options_t, uint32_t, {
438*043036a2SApple OSS Distributions MPSC_DAEMON_INIT_NONE = 0,
439*043036a2SApple OSS Distributions MPSC_DAEMON_INIT_INACTIVE = 1 << 0,
440*043036a2SApple OSS Distributions });
441*043036a2SApple OSS Distributions
442*043036a2SApple OSS Distributions /*!
443*043036a2SApple OSS Distributions * @typedef struct mpsc_daemon_queue
444*043036a2SApple OSS Distributions *
445*043036a2SApple OSS Distributions * @brief
446*043036a2SApple OSS Distributions * Daemon queues are a ready-to use packaging of the low level MPSC queue
447*043036a2SApple OSS Distributions * primitive.
448*043036a2SApple OSS Distributions *
449*043036a2SApple OSS Distributions * @discussion
450*043036a2SApple OSS Distributions * mpsc_queue_t requires handling of state transitions of the queue and
451*043036a2SApple OSS Distributions * dequeuing yourself, which is a non trivial task.
452*043036a2SApple OSS Distributions *
453*043036a2SApple OSS Distributions * Daemon queues are a simple packaged solution that allows for mpsc_queue_t to
454*043036a2SApple OSS Distributions * form hierarchies (mostly for layering purposes), and be serviced at the
455*043036a2SApple OSS Distributions * bottom of such a hierarchy by a thread or a thread call.
456*043036a2SApple OSS Distributions *
457*043036a2SApple OSS Distributions * Daemon queues assume homogenous items, and are setup with an `invoke`
458*043036a2SApple OSS Distributions * callback that is called in the dequeuer on every item as they are dequeued.
459*043036a2SApple OSS Distributions */
460*043036a2SApple OSS Distributions typedef struct mpsc_daemon_queue *mpsc_daemon_queue_t;
461*043036a2SApple OSS Distributions
462*043036a2SApple OSS Distributions #define MPSC_QUEUE_BATCH_END ((mpsc_queue_chain_t)~0ul)
463*043036a2SApple OSS Distributions
464*043036a2SApple OSS Distributions /*!
465*043036a2SApple OSS Distributions * @typedef struct mpsc_daemon_queue
466*043036a2SApple OSS Distributions *
467*043036a2SApple OSS Distributions * @brief
468*043036a2SApple OSS Distributions * The type for MPSC Daemon Queues invoke callbacks.
469*043036a2SApple OSS Distributions */
470*043036a2SApple OSS Distributions typedef void (*mpsc_daemon_invoke_fn_t)(mpsc_queue_chain_t elm,
471*043036a2SApple OSS Distributions mpsc_daemon_queue_t dq);
472*043036a2SApple OSS Distributions
473*043036a2SApple OSS Distributions /*!
474*043036a2SApple OSS Distributions * @enum mpsc_daemon_queue_kind
475*043036a2SApple OSS Distributions *
476*043036a2SApple OSS Distributions * @brief
477*043036a2SApple OSS Distributions * Internal type, not to be used by clients.
478*043036a2SApple OSS Distributions */
479*043036a2SApple OSS Distributions __enum_decl(mpsc_daemon_queue_kind_t, uint16_t, {
480*043036a2SApple OSS Distributions MPSC_QUEUE_KIND_UNKNOWN,
481*043036a2SApple OSS Distributions MPSC_QUEUE_KIND_NESTED,
482*043036a2SApple OSS Distributions MPSC_QUEUE_KIND_THREAD,
483*043036a2SApple OSS Distributions MPSC_QUEUE_KIND_THREAD_CRITICAL,
484*043036a2SApple OSS Distributions MPSC_QUEUE_KIND_THREAD_CALL,
485*043036a2SApple OSS Distributions });
486*043036a2SApple OSS Distributions
487*043036a2SApple OSS Distributions /*!
488*043036a2SApple OSS Distributions * @enum mpsc_daemon_queue_options
489*043036a2SApple OSS Distributions *
490*043036a2SApple OSS Distributions * @brief
491*043036a2SApple OSS Distributions * Options clients can set on their queue before first use.
492*043036a2SApple OSS Distributions *
493*043036a2SApple OSS Distributions * @const MPSC_QUEUE_OPTION_BATCH
494*043036a2SApple OSS Distributions * Call the `invoke` callback at the end of a batch
495*043036a2SApple OSS Distributions * with the magic @c MPSC_QUEUE_BATCH_END marker.
496*043036a2SApple OSS Distributions */
497*043036a2SApple OSS Distributions __options_decl(mpsc_daemon_queue_options_t, uint16_t, {
498*043036a2SApple OSS Distributions MPSC_QUEUE_OPTION_BATCH = 0x0001,
499*043036a2SApple OSS Distributions });
500*043036a2SApple OSS Distributions
501*043036a2SApple OSS Distributions /*!
502*043036a2SApple OSS Distributions * @enum mpsc_daemon_queue_state
503*043036a2SApple OSS Distributions *
504*043036a2SApple OSS Distributions * @brief
505*043036a2SApple OSS Distributions * Internal type, not to be used by clients.
506*043036a2SApple OSS Distributions */
507*043036a2SApple OSS Distributions __options_decl(mpsc_daemon_queue_state_t, uint32_t, {
508*043036a2SApple OSS Distributions MPSC_QUEUE_STATE_DRAINING = 0x0001,
509*043036a2SApple OSS Distributions MPSC_QUEUE_STATE_WAKEUP = 0x0002,
510*043036a2SApple OSS Distributions MPSC_QUEUE_STATE_CANCELED = 0x0004,
511*043036a2SApple OSS Distributions MPSC_QUEUE_STATE_INACTIVE = 0x0008,
512*043036a2SApple OSS Distributions });
513*043036a2SApple OSS Distributions
514*043036a2SApple OSS Distributions struct mpsc_daemon_queue {
515*043036a2SApple OSS Distributions mpsc_daemon_queue_kind_t mpd_kind;
516*043036a2SApple OSS Distributions mpsc_daemon_queue_options_t mpd_options;
517*043036a2SApple OSS Distributions mpsc_daemon_queue_state_t _Atomic mpd_state;
518*043036a2SApple OSS Distributions mpsc_daemon_invoke_fn_t mpd_invoke;
519*043036a2SApple OSS Distributions union {
520*043036a2SApple OSS Distributions mpsc_daemon_queue_t mpd_target;
521*043036a2SApple OSS Distributions struct thread *mpd_thread;
522*043036a2SApple OSS Distributions struct thread_call *mpd_call;
523*043036a2SApple OSS Distributions };
524*043036a2SApple OSS Distributions struct mpsc_queue_head mpd_queue;
525*043036a2SApple OSS Distributions struct mpsc_queue_chain mpd_chain;
526*043036a2SApple OSS Distributions };
527*043036a2SApple OSS Distributions
528*043036a2SApple OSS Distributions /*!
529*043036a2SApple OSS Distributions * @function mpsc_daemon_queue_init_with_thread
530*043036a2SApple OSS Distributions *
531*043036a2SApple OSS Distributions * @brief
532*043036a2SApple OSS Distributions * Sets up a daemon queue to be a base queue drained by a kernel thread.
533*043036a2SApple OSS Distributions *
534*043036a2SApple OSS Distributions * @discussion
535*043036a2SApple OSS Distributions * The function will allocate the thread and start it in assert_wait.
536*043036a2SApple OSS Distributions *
537*043036a2SApple OSS Distributions * @param dq
538*043036a2SApple OSS Distributions * The queue to initialize
539*043036a2SApple OSS Distributions *
540*043036a2SApple OSS Distributions * @param invoke
541*043036a2SApple OSS Distributions * The invoke function called on individual items on the queue during drain.
542*043036a2SApple OSS Distributions *
543*043036a2SApple OSS Distributions * @param pri
544*043036a2SApple OSS Distributions * The scheduler priority for the created thread.
545*043036a2SApple OSS Distributions *
546*043036a2SApple OSS Distributions * @param name
547*043036a2SApple OSS Distributions * The name to give to the created thread.
548*043036a2SApple OSS Distributions *
549*043036a2SApple OSS Distributions * @param flags
550*043036a2SApple OSS Distributions * See mpsc_daemon_init_options_t.
551*043036a2SApple OSS Distributions *
552*043036a2SApple OSS Distributions * @returns
553*043036a2SApple OSS Distributions * Whether creating the thread was successful.
554*043036a2SApple OSS Distributions */
555*043036a2SApple OSS Distributions kern_return_t
556*043036a2SApple OSS Distributions mpsc_daemon_queue_init_with_thread(mpsc_daemon_queue_t dq,
557*043036a2SApple OSS Distributions mpsc_daemon_invoke_fn_t invoke, int pri, const char *name,
558*043036a2SApple OSS Distributions mpsc_daemon_init_options_t flags);
559*043036a2SApple OSS Distributions
560*043036a2SApple OSS Distributions
561*043036a2SApple OSS Distributions /*!
562*043036a2SApple OSS Distributions * @function mpsc_daemon_queue_init_with_thread_call
563*043036a2SApple OSS Distributions *
564*043036a2SApple OSS Distributions * @brief
565*043036a2SApple OSS Distributions * Sets up a daemon queue to be a base queue drained by a thread call.
566*043036a2SApple OSS Distributions *
567*043036a2SApple OSS Distributions * @param dq
568*043036a2SApple OSS Distributions * The queue to initialize
569*043036a2SApple OSS Distributions *
570*043036a2SApple OSS Distributions * @param invoke
571*043036a2SApple OSS Distributions * The invoke function called on individual items on the queue during drain.
572*043036a2SApple OSS Distributions *
573*043036a2SApple OSS Distributions * @param pri
574*043036a2SApple OSS Distributions * The priority the thread call will run at.
575*043036a2SApple OSS Distributions *
576*043036a2SApple OSS Distributions * @param flags
577*043036a2SApple OSS Distributions * See mpsc_daemon_init_options_t.
578*043036a2SApple OSS Distributions */
579*043036a2SApple OSS Distributions void
580*043036a2SApple OSS Distributions mpsc_daemon_queue_init_with_thread_call(mpsc_daemon_queue_t dq,
581*043036a2SApple OSS Distributions mpsc_daemon_invoke_fn_t invoke, thread_call_priority_t pri,
582*043036a2SApple OSS Distributions mpsc_daemon_init_options_t flags);
583*043036a2SApple OSS Distributions
584*043036a2SApple OSS Distributions /*!
585*043036a2SApple OSS Distributions * @function mpsc_daemon_queue_init_with_target
586*043036a2SApple OSS Distributions *
587*043036a2SApple OSS Distributions * @brief
588*043036a2SApple OSS Distributions * Sets up a daemon queue to target another daemon queue.
589*043036a2SApple OSS Distributions *
590*043036a2SApple OSS Distributions * @discussion
591*043036a2SApple OSS Distributions * The targetting relationship is useful for subsystem layering purposes only.
592*043036a2SApple OSS Distributions * Because draining a given queue is atomic with respect to its target, target
593*043036a2SApple OSS Distributions * queue hierarchies are prone to starvation.
594*043036a2SApple OSS Distributions *
595*043036a2SApple OSS Distributions * @param dq
596*043036a2SApple OSS Distributions * The queue to initialize
597*043036a2SApple OSS Distributions *
598*043036a2SApple OSS Distributions * @param invoke
599*043036a2SApple OSS Distributions * The invoke function called on individual items on the queue during drain.
600*043036a2SApple OSS Distributions *
601*043036a2SApple OSS Distributions * @param target
602*043036a2SApple OSS Distributions * The target queue of the initialized queue, which has to be initialized with
603*043036a2SApple OSS Distributions * the mpsc_daemon_queue_nested_invoke invoke handler.
604*043036a2SApple OSS Distributions *
605*043036a2SApple OSS Distributions * @param flags
606*043036a2SApple OSS Distributions * See mpsc_daemon_init_options_t.
607*043036a2SApple OSS Distributions */
608*043036a2SApple OSS Distributions void
609*043036a2SApple OSS Distributions mpsc_daemon_queue_init_with_target(mpsc_daemon_queue_t dq,
610*043036a2SApple OSS Distributions mpsc_daemon_invoke_fn_t invoke, mpsc_daemon_queue_t target,
611*043036a2SApple OSS Distributions mpsc_daemon_init_options_t flags);
612*043036a2SApple OSS Distributions
613*043036a2SApple OSS Distributions /*!
614*043036a2SApple OSS Distributions * @function mpsc_daemon_queue_nested_invoke
615*043036a2SApple OSS Distributions *
616*043036a2SApple OSS Distributions * @brief
617*043036a2SApple OSS Distributions * The invoke function to pass to mpsc_daemon_queue_init_* when a queue is meant
618*043036a2SApple OSS Distributions * to be targeted by other queues.
619*043036a2SApple OSS Distributions */
620*043036a2SApple OSS Distributions void
621*043036a2SApple OSS Distributions mpsc_daemon_queue_nested_invoke(mpsc_queue_chain_t elm,
622*043036a2SApple OSS Distributions mpsc_daemon_queue_t dq);
623*043036a2SApple OSS Distributions
624*043036a2SApple OSS Distributions /*!
625*043036a2SApple OSS Distributions * @function mpsc_daemon_queue_activate
626*043036a2SApple OSS Distributions *
627*043036a2SApple OSS Distributions * @brief
628*043036a2SApple OSS Distributions * Activate a queue that was created with the @c MPSC_DAEMON_INIT_INACTIVE flag.
629*043036a2SApple OSS Distributions *
630*043036a2SApple OSS Distributions * @param dq
631*043036a2SApple OSS Distributions * The queue to activate.
632*043036a2SApple OSS Distributions */
633*043036a2SApple OSS Distributions void
634*043036a2SApple OSS Distributions mpsc_daemon_queue_activate(mpsc_daemon_queue_t dq);
635*043036a2SApple OSS Distributions
636*043036a2SApple OSS Distributions /*!
637*043036a2SApple OSS Distributions * @function mpsc_daemon_queue_cancel_and_wait
638*043036a2SApple OSS Distributions *
639*043036a2SApple OSS Distributions * @brief
640*043036a2SApple OSS Distributions * Cancels the queue so that the object owning it can be destroyed.
641*043036a2SApple OSS Distributions *
642*043036a2SApple OSS Distributions * @discussion
643*043036a2SApple OSS Distributions * This interface will cancel the queue and wait synchronously for the
644*043036a2SApple OSS Distributions * cancelation to have taken effect, possibly waiting on elements currently
645*043036a2SApple OSS Distributions * draining.
646*043036a2SApple OSS Distributions *
647*043036a2SApple OSS Distributions * Sending objects to the daemon queue after cancelation is undefined.
648*043036a2SApple OSS Distributions *
649*043036a2SApple OSS Distributions * Calling this function multiple times is undefined.
650*043036a2SApple OSS Distributions *
651*043036a2SApple OSS Distributions * Tearing down daemon queue hierarchies is the responsibility of the adopter.
652*043036a2SApple OSS Distributions */
653*043036a2SApple OSS Distributions void
654*043036a2SApple OSS Distributions mpsc_daemon_queue_cancel_and_wait(mpsc_daemon_queue_t dq);
655*043036a2SApple OSS Distributions
656*043036a2SApple OSS Distributions /*!
657*043036a2SApple OSS Distributions * @function mpsc_daemon_enqueue
658*043036a2SApple OSS Distributions *
659*043036a2SApple OSS Distributions * @brief
660*043036a2SApple OSS Distributions * Send ("async") an item to a given daemon on a given queue.
661*043036a2SApple OSS Distributions *
662*043036a2SApple OSS Distributions * @discussion
663*043036a2SApple OSS Distributions * It is the responsibility of the caller to ensure preemption is disabled when
664*043036a2SApple OSS Distributions * this call is made.
665*043036a2SApple OSS Distributions *
666*043036a2SApple OSS Distributions * @param dq
667*043036a2SApple OSS Distributions * The daemon queue to enqueue the element onto.
668*043036a2SApple OSS Distributions *
669*043036a2SApple OSS Distributions * @param elm
670*043036a2SApple OSS Distributions * The item to enqueue.
671*043036a2SApple OSS Distributions *
672*043036a2SApple OSS Distributions * @param options
673*043036a2SApple OSS Distributions * Options applicable to the enqueue. In particupar passing
674*043036a2SApple OSS Distributions * MPSC_QUEUE_DISABLE_PREEMPTION makes sure preemption is properly disabled
675*043036a2SApple OSS Distributions * during the enqueue.
676*043036a2SApple OSS Distributions */
677*043036a2SApple OSS Distributions void
678*043036a2SApple OSS Distributions mpsc_daemon_enqueue(mpsc_daemon_queue_t dq, mpsc_queue_chain_t elm,
679*043036a2SApple OSS Distributions mpsc_queue_options_t options);
680*043036a2SApple OSS Distributions
681*043036a2SApple OSS Distributions
682*043036a2SApple OSS Distributions #pragma mark Deferred deallocation daemon
683*043036a2SApple OSS Distributions
684*043036a2SApple OSS Distributions /*!
685*043036a2SApple OSS Distributions * @function thread_deallocate_daemon_init
686*043036a2SApple OSS Distributions *
687*043036a2SApple OSS Distributions * @brief
688*043036a2SApple OSS Distributions * Initializes the deferred deallocation daemon, called by thread_daemon_init().
689*043036a2SApple OSS Distributions *
690*043036a2SApple OSS Distributions * @discussion
691*043036a2SApple OSS Distributions * The deferred deallocation daemon is a kernel thread based daemon queue that
692*043036a2SApple OSS Distributions * is targeted by nested daemon queues.
693*043036a2SApple OSS Distributions *
694*043036a2SApple OSS Distributions * It is used to perform deferred deallocation for objects that can't safely be
695*043036a2SApple OSS Distributions * deallocated from the context where the deallocation should normally occur.
696*043036a2SApple OSS Distributions *
697*043036a2SApple OSS Distributions * Subsystems using it are for example: turnstiles, workqueues, threads.
698*043036a2SApple OSS Distributions *
699*043036a2SApple OSS Distributions * @warning
700*043036a2SApple OSS Distributions * New queues should be added to this daemon with great care,
701*043036a2SApple OSS Distributions * as abusing it can lead to unbounded amount of kernel work.
702*043036a2SApple OSS Distributions */
703*043036a2SApple OSS Distributions void
704*043036a2SApple OSS Distributions thread_deallocate_daemon_init(void);
705*043036a2SApple OSS Distributions
706*043036a2SApple OSS Distributions /*!
707*043036a2SApple OSS Distributions * @function thread_deallocate_daemon_register_queue
708*043036a2SApple OSS Distributions *
709*043036a2SApple OSS Distributions * @brief
710*043036a2SApple OSS Distributions * Dynamically register a queue for deferred deletion with the deferred
711*043036a2SApple OSS Distributions * deallocation daemon.
712*043036a2SApple OSS Distributions *
713*043036a2SApple OSS Distributions * @param dq
714*043036a2SApple OSS Distributions * The daemon queue to register with the deferred deallocation daemon.
715*043036a2SApple OSS Distributions *
716*043036a2SApple OSS Distributions * @param invoke
717*043036a2SApple OSS Distributions * The callback called on every element of this queue by the deallocation
718*043036a2SApple OSS Distributions * daemon.
719*043036a2SApple OSS Distributions */
720*043036a2SApple OSS Distributions void
721*043036a2SApple OSS Distributions thread_deallocate_daemon_register_queue(mpsc_daemon_queue_t dq,
722*043036a2SApple OSS Distributions mpsc_daemon_invoke_fn_t invoke);
723*043036a2SApple OSS Distributions
724*043036a2SApple OSS Distributions
725*043036a2SApple OSS Distributions #pragma mark tests
726*043036a2SApple OSS Distributions #if DEBUG || DEVELOPMENT
727*043036a2SApple OSS Distributions
728*043036a2SApple OSS Distributions int
729*043036a2SApple OSS Distributions mpsc_test_pingpong(uint64_t count, uint64_t *out);
730*043036a2SApple OSS Distributions
731*043036a2SApple OSS Distributions #endif /* DEBUG || DEVELOPMENT */
732*043036a2SApple OSS Distributions
733*043036a2SApple OSS Distributions #endif /* XNU_KERNEL_PRIVATE */
734*043036a2SApple OSS Distributions
735*043036a2SApple OSS Distributions __ASSUME_PTR_ABI_SINGLE_END __END_DECLS
736*043036a2SApple OSS Distributions
737*043036a2SApple OSS Distributions #endif /* _KERN_MPSC_QUEUE_H_ */
738