xref: /xnu-12377.41.6/osfmk/kern/priority_queue.h (revision bbb1b6f9e71b8cdde6e5cd6f4841f207dee3d828)
1*bbb1b6f9SApple OSS Distributions /*
2*bbb1b6f9SApple OSS Distributions  * Copyright (c) 2018 Apple Inc. All rights reserved.
3*bbb1b6f9SApple OSS Distributions  *
4*bbb1b6f9SApple OSS Distributions  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5*bbb1b6f9SApple OSS Distributions  *
6*bbb1b6f9SApple OSS Distributions  * This file contains Original Code and/or Modifications of Original Code
7*bbb1b6f9SApple OSS Distributions  * as defined in and that are subject to the Apple Public Source License
8*bbb1b6f9SApple OSS Distributions  * Version 2.0 (the 'License'). You may not use this file except in
9*bbb1b6f9SApple OSS Distributions  * compliance with the License. The rights granted to you under the License
10*bbb1b6f9SApple OSS Distributions  * may not be used to create, or enable the creation or redistribution of,
11*bbb1b6f9SApple OSS Distributions  * unlawful or unlicensed copies of an Apple operating system, or to
12*bbb1b6f9SApple OSS Distributions  * circumvent, violate, or enable the circumvention or violation of, any
13*bbb1b6f9SApple OSS Distributions  * terms of an Apple operating system software license agreement.
14*bbb1b6f9SApple OSS Distributions  *
15*bbb1b6f9SApple OSS Distributions  * Please obtain a copy of the License at
16*bbb1b6f9SApple OSS Distributions  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17*bbb1b6f9SApple OSS Distributions  *
18*bbb1b6f9SApple OSS Distributions  * The Original Code and all software distributed under the License are
19*bbb1b6f9SApple OSS Distributions  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20*bbb1b6f9SApple OSS Distributions  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21*bbb1b6f9SApple OSS Distributions  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22*bbb1b6f9SApple OSS Distributions  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23*bbb1b6f9SApple OSS Distributions  * Please see the License for the specific language governing rights and
24*bbb1b6f9SApple OSS Distributions  * limitations under the License.
25*bbb1b6f9SApple OSS Distributions  *
26*bbb1b6f9SApple OSS Distributions  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27*bbb1b6f9SApple OSS Distributions  */
28*bbb1b6f9SApple OSS Distributions 
29*bbb1b6f9SApple OSS Distributions #ifndef _KERN_PRIORITY_QUEUE_H_
30*bbb1b6f9SApple OSS Distributions #define _KERN_PRIORITY_QUEUE_H_
31*bbb1b6f9SApple OSS Distributions 
32*bbb1b6f9SApple OSS Distributions #if KERNEL
33*bbb1b6f9SApple OSS Distributions #include <kern/kern_types.h>
34*bbb1b6f9SApple OSS Distributions #include <kern/macro_help.h>
35*bbb1b6f9SApple OSS Distributions #include <kern/assert.h>
36*bbb1b6f9SApple OSS Distributions #endif
37*bbb1b6f9SApple OSS Distributions 
38*bbb1b6f9SApple OSS Distributions #include <stdbool.h>
39*bbb1b6f9SApple OSS Distributions #include <sys/cdefs.h>
40*bbb1b6f9SApple OSS Distributions 
41*bbb1b6f9SApple OSS Distributions #pragma GCC visibility push(hidden)
42*bbb1b6f9SApple OSS Distributions 
43*bbb1b6f9SApple OSS Distributions __BEGIN_DECLS
44*bbb1b6f9SApple OSS Distributions 
45*bbb1b6f9SApple OSS Distributions /*
46*bbb1b6f9SApple OSS Distributions  * A generic priorty ordered queue implementation based on pairing heaps.
47*bbb1b6f9SApple OSS Distributions  *
48*bbb1b6f9SApple OSS Distributions  * Reference Papers:
49*bbb1b6f9SApple OSS Distributions  * - A Back-to-Basics Empirical Study of Priority Queues (https://arxiv.org/abs/1403.0252)
50*bbb1b6f9SApple OSS Distributions  * - The Pairing Heap: A New Form of Self-Adjusting Heap
51*bbb1b6f9SApple OSS Distributions  *   (https://www.cs.cmu.edu/~sleator/papers/pairing-heaps.pdf)
52*bbb1b6f9SApple OSS Distributions  *
53*bbb1b6f9SApple OSS Distributions  * The XNU implementation is a basic version of the pairing heap.
54*bbb1b6f9SApple OSS Distributions  * It allows for O(1) insertion and amortized O(log n) deletion.
55*bbb1b6f9SApple OSS Distributions  *
56*bbb1b6f9SApple OSS Distributions  * It is not a stable data structure by default since adding stability would
57*bbb1b6f9SApple OSS Distributions  * need more pointers and hence more memory.
58*bbb1b6f9SApple OSS Distributions  *
59*bbb1b6f9SApple OSS Distributions  * Type of queues
60*bbb1b6f9SApple OSS Distributions  *
61*bbb1b6f9SApple OSS Distributions  *         There are several types of priority queues, with types named:
62*bbb1b6f9SApple OSS Distributions  *
63*bbb1b6f9SApple OSS Distributions  *         struct priority_queue_<subtype>_<min|max>
64*bbb1b6f9SApple OSS Distributions  *
65*bbb1b6f9SApple OSS Distributions  *         In the rest of this header, `struct priority_queue` is used as
66*bbb1b6f9SApple OSS Distributions  *         a generic type to mean any priority_queue type.
67*bbb1b6f9SApple OSS Distributions  *
68*bbb1b6f9SApple OSS Distributions  *         min/max refers to whether the priority queue is a min or a max heap.
69*bbb1b6f9SApple OSS Distributions  *
70*bbb1b6f9SApple OSS Distributions  *         the subtype can be:
71*bbb1b6f9SApple OSS Distributions  *
72*bbb1b6f9SApple OSS Distributions  *         - sched, in which case the key is built in the linkage and assumed to
73*bbb1b6f9SApple OSS Distributions  *           be a scheduler priority.
74*bbb1b6f9SApple OSS Distributions  *
75*bbb1b6f9SApple OSS Distributions  *         - sched_stable, in which case the key is a combination of:
76*bbb1b6f9SApple OSS Distributions  *             * a scheduler priority
77*bbb1b6f9SApple OSS Distributions  *             * whether the entry was preempted or not
78*bbb1b6f9SApple OSS Distributions  *             * a timestamp.
79*bbb1b6f9SApple OSS Distributions  *
80*bbb1b6f9SApple OSS Distributions  *         - generic, in which case a comparison function must be passed to
81*bbb1b6f9SApple OSS Distributions  *           the priority_queue_init.
82*bbb1b6f9SApple OSS Distributions  *
83*bbb1b6f9SApple OSS Distributions  * Element Linkage:
84*bbb1b6f9SApple OSS Distributions  *
85*bbb1b6f9SApple OSS Distributions  *         Both types use a common queue head and linkage pattern.
86*bbb1b6f9SApple OSS Distributions  *         The head of a priority queue is declared as:
87*bbb1b6f9SApple OSS Distributions  *
88*bbb1b6f9SApple OSS Distributions  *              struct priority_queue_<subtype>_<min|max> pq_head;
89*bbb1b6f9SApple OSS Distributions  *
90*bbb1b6f9SApple OSS Distributions  *         Elements in this queue are linked together using one of the struct
91*bbb1b6f9SApple OSS Distributions  *         priority_queue_entry_<subtype> objects embedded within a structure:
92*bbb1b6f9SApple OSS Distributions  *
93*bbb1b6f9SApple OSS Distributions  *              struct some_data {
94*bbb1b6f9SApple OSS Distributions  *                      int field1;
95*bbb1b6f9SApple OSS Distributions  *                      int field2;
96*bbb1b6f9SApple OSS Distributions  *                      ...
97*bbb1b6f9SApple OSS Distributions  *                      struct priority_queue_entry link;
98*bbb1b6f9SApple OSS Distributions  *                      ...
99*bbb1b6f9SApple OSS Distributions  *                      int last_field;
100*bbb1b6f9SApple OSS Distributions  *              };
101*bbb1b6f9SApple OSS Distributions  *         struct some_data is referred to as the queue "element"
102*bbb1b6f9SApple OSS Distributions  *
103*bbb1b6f9SApple OSS Distributions  *         This method uses the next, prev and child pointers of the struct
104*bbb1b6f9SApple OSS Distributions  *         priority_queue_entry linkage object embedded in a queue element to
105*bbb1b6f9SApple OSS Distributions  *         point to other elements in the queue. The head of the priority queue
106*bbb1b6f9SApple OSS Distributions  *         (the priority_queue object) will point to the root of the pairing
107*bbb1b6f9SApple OSS Distributions  *         heap (NULL if heap is empty). This method allows multiple chains
108*bbb1b6f9SApple OSS Distributions  *         through a given object, by embedding multiple priority_queue_entry
109*bbb1b6f9SApple OSS Distributions  *         objects in the structure, while simultaneously providing fast removal
110*bbb1b6f9SApple OSS Distributions  *         and insertion into the heap using only priority_queue_entry object
111*bbb1b6f9SApple OSS Distributions  *         pointers.
112*bbb1b6f9SApple OSS Distributions  */
113*bbb1b6f9SApple OSS Distributions 
114*bbb1b6f9SApple OSS Distributions 
115*bbb1b6f9SApple OSS Distributions /*
116*bbb1b6f9SApple OSS Distributions  * Priority keys maintained by the data structure.
117*bbb1b6f9SApple OSS Distributions  * Since the priority is packed in the node itself, it restricts keys to be 16-bits only.
118*bbb1b6f9SApple OSS Distributions  */
119*bbb1b6f9SApple OSS Distributions #define PRIORITY_QUEUE_KEY_NONE             0
120*bbb1b6f9SApple OSS Distributions typedef uint16_t priority_queue_key_t;
121*bbb1b6f9SApple OSS Distributions 
122*bbb1b6f9SApple OSS Distributions #ifdef __LP64__
123*bbb1b6f9SApple OSS Distributions 
124*bbb1b6f9SApple OSS Distributions /*
125*bbb1b6f9SApple OSS Distributions  * For 64-bit platforms, pack the priority key into the child pointer
126*bbb1b6f9SApple OSS Distributions  * The packing/unpacking is done using a compiler trick to sign extend long.
127*bbb1b6f9SApple OSS Distributions  * This avoids additional NULL checks which are needed in typical packing
128*bbb1b6f9SApple OSS Distributions  * implementation. The idea is to define the packed location as a long and
129*bbb1b6f9SApple OSS Distributions  * for unpacking simply cast it to a full pointer which sign extends it.
130*bbb1b6f9SApple OSS Distributions  */
131*bbb1b6f9SApple OSS Distributions #if CONFIG_KERNEL_TAGGING
132*bbb1b6f9SApple OSS Distributions #define PRIORITY_QUEUE_ENTRY_CHILD_BITS     44
133*bbb1b6f9SApple OSS Distributions #define PRIORITY_QUEUE_ENTRY_TAG_BITS       4
134*bbb1b6f9SApple OSS Distributions #define PRIORITY_QUEUE_ENTRY_KEY_BITS       16
135*bbb1b6f9SApple OSS Distributions #else /* CONFIG_KERNEL_TAGGING */
136*bbb1b6f9SApple OSS Distributions #define PRIORITY_QUEUE_ENTRY_CHILD_BITS     48
137*bbb1b6f9SApple OSS Distributions #define PRIORITY_QUEUE_ENTRY_KEY_BITS       16
138*bbb1b6f9SApple OSS Distributions #endif /* CONFIG_KERNEL_TAGGING */
139*bbb1b6f9SApple OSS Distributions 
140*bbb1b6f9SApple OSS Distributions typedef struct priority_queue_entry {
141*bbb1b6f9SApple OSS Distributions 	struct priority_queue_entry        *next;
142*bbb1b6f9SApple OSS Distributions 	struct priority_queue_entry        *prev;
143*bbb1b6f9SApple OSS Distributions 	long                                __key: PRIORITY_QUEUE_ENTRY_KEY_BITS;
144*bbb1b6f9SApple OSS Distributions #if CONFIG_KERNEL_TAGGING
145*bbb1b6f9SApple OSS Distributions 	unsigned long                       tag: PRIORITY_QUEUE_ENTRY_TAG_BITS;
146*bbb1b6f9SApple OSS Distributions #endif /* CONFIG_KERNEL_TAGGING */
147*bbb1b6f9SApple OSS Distributions 	long                                child: PRIORITY_QUEUE_ENTRY_CHILD_BITS;
148*bbb1b6f9SApple OSS Distributions } *priority_queue_entry_t;
149*bbb1b6f9SApple OSS Distributions 
150*bbb1b6f9SApple OSS Distributions typedef struct priority_queue_entry_deadline {
151*bbb1b6f9SApple OSS Distributions 	struct priority_queue_entry_deadline *next;
152*bbb1b6f9SApple OSS Distributions 	struct priority_queue_entry_deadline *prev;
153*bbb1b6f9SApple OSS Distributions 	long                                  __key: PRIORITY_QUEUE_ENTRY_KEY_BITS;
154*bbb1b6f9SApple OSS Distributions #if CONFIG_KERNEL_TAGGING
155*bbb1b6f9SApple OSS Distributions 	unsigned long                         tag: PRIORITY_QUEUE_ENTRY_TAG_BITS;
156*bbb1b6f9SApple OSS Distributions #endif /* CONFIG_KERNEL_TAGGING */
157*bbb1b6f9SApple OSS Distributions 	long                                  child: PRIORITY_QUEUE_ENTRY_CHILD_BITS;
158*bbb1b6f9SApple OSS Distributions 	uint64_t                              deadline;
159*bbb1b6f9SApple OSS Distributions } *priority_queue_entry_deadline_t;
160*bbb1b6f9SApple OSS Distributions 
161*bbb1b6f9SApple OSS Distributions typedef struct priority_queue_entry_sched {
162*bbb1b6f9SApple OSS Distributions 	struct priority_queue_entry_sched  *next;
163*bbb1b6f9SApple OSS Distributions 	struct priority_queue_entry_sched  *prev;
164*bbb1b6f9SApple OSS Distributions 	long                                key: PRIORITY_QUEUE_ENTRY_KEY_BITS;
165*bbb1b6f9SApple OSS Distributions #if CONFIG_KERNEL_TAGGING
166*bbb1b6f9SApple OSS Distributions 	unsigned long                       tag: PRIORITY_QUEUE_ENTRY_TAG_BITS;
167*bbb1b6f9SApple OSS Distributions #endif /* CONFIG_KERNEL_TAGGING */
168*bbb1b6f9SApple OSS Distributions 	long                                child: PRIORITY_QUEUE_ENTRY_CHILD_BITS;
169*bbb1b6f9SApple OSS Distributions } *priority_queue_entry_sched_t;
170*bbb1b6f9SApple OSS Distributions 
171*bbb1b6f9SApple OSS Distributions typedef struct priority_queue_entry_stable {
172*bbb1b6f9SApple OSS Distributions 	struct priority_queue_entry_stable *next;
173*bbb1b6f9SApple OSS Distributions 	struct priority_queue_entry_stable *prev;
174*bbb1b6f9SApple OSS Distributions 	long                                key: PRIORITY_QUEUE_ENTRY_KEY_BITS;
175*bbb1b6f9SApple OSS Distributions #if CONFIG_KERNEL_TAGGING
176*bbb1b6f9SApple OSS Distributions 	unsigned long                       tag: PRIORITY_QUEUE_ENTRY_TAG_BITS;
177*bbb1b6f9SApple OSS Distributions #endif /* CONFIG_KERNEL_TAGGING */
178*bbb1b6f9SApple OSS Distributions 	long                                child: PRIORITY_QUEUE_ENTRY_CHILD_BITS;
179*bbb1b6f9SApple OSS Distributions 	uint64_t                            stamp;
180*bbb1b6f9SApple OSS Distributions } *priority_queue_entry_stable_t;
181*bbb1b6f9SApple OSS Distributions 
182*bbb1b6f9SApple OSS Distributions #else /* __LP64__ */
183*bbb1b6f9SApple OSS Distributions 
184*bbb1b6f9SApple OSS Distributions typedef struct priority_queue_entry {
185*bbb1b6f9SApple OSS Distributions 	struct priority_queue_entry        *next;
186*bbb1b6f9SApple OSS Distributions 	struct priority_queue_entry        *prev;
187*bbb1b6f9SApple OSS Distributions 	long                                child;
188*bbb1b6f9SApple OSS Distributions } *priority_queue_entry_t;
189*bbb1b6f9SApple OSS Distributions 
190*bbb1b6f9SApple OSS Distributions typedef struct priority_queue_entry_deadline {
191*bbb1b6f9SApple OSS Distributions 	struct priority_queue_entry_deadline *next;
192*bbb1b6f9SApple OSS Distributions 	struct priority_queue_entry_deadline *prev;
193*bbb1b6f9SApple OSS Distributions 	long                                  child;
194*bbb1b6f9SApple OSS Distributions 	uint64_t                              deadline;
195*bbb1b6f9SApple OSS Distributions } *priority_queue_entry_deadline_t;
196*bbb1b6f9SApple OSS Distributions 
197*bbb1b6f9SApple OSS Distributions /*
198*bbb1b6f9SApple OSS Distributions  * For 32-bit platforms, use an extra field to store the key since child pointer packing
199*bbb1b6f9SApple OSS Distributions  * is not an option. The child is maintained as a long to use the same packing/unpacking
200*bbb1b6f9SApple OSS Distributions  * routines that work for 64-bit platforms.
201*bbb1b6f9SApple OSS Distributions  */
202*bbb1b6f9SApple OSS Distributions typedef struct priority_queue_entry_sched {
203*bbb1b6f9SApple OSS Distributions 	struct priority_queue_entry_sched  *next;
204*bbb1b6f9SApple OSS Distributions 	struct priority_queue_entry_sched  *prev;
205*bbb1b6f9SApple OSS Distributions 	long                                child;
206*bbb1b6f9SApple OSS Distributions 	priority_queue_key_t                key;
207*bbb1b6f9SApple OSS Distributions } *priority_queue_entry_sched_t;
208*bbb1b6f9SApple OSS Distributions 
209*bbb1b6f9SApple OSS Distributions typedef struct priority_queue_entry_stable {
210*bbb1b6f9SApple OSS Distributions 	struct priority_queue_entry_stable *next;
211*bbb1b6f9SApple OSS Distributions 	struct priority_queue_entry_stable *prev;
212*bbb1b6f9SApple OSS Distributions 	long                                child;
213*bbb1b6f9SApple OSS Distributions 	priority_queue_key_t                key;
214*bbb1b6f9SApple OSS Distributions 	uint64_t                            stamp;
215*bbb1b6f9SApple OSS Distributions } *priority_queue_entry_stable_t;
216*bbb1b6f9SApple OSS Distributions 
217*bbb1b6f9SApple OSS Distributions #endif /* __LP64__ */
218*bbb1b6f9SApple OSS Distributions 
219*bbb1b6f9SApple OSS Distributions /*
220*bbb1b6f9SApple OSS Distributions  * Comparator block prototype
221*bbb1b6f9SApple OSS Distributions  * Args:
222*bbb1b6f9SApple OSS Distributions  *      - elements to compare
223*bbb1b6f9SApple OSS Distributions  * Return:
224*bbb1b6f9SApple OSS Distributions  * comparision result to indicate relative ordering of elements according to the heap type
225*bbb1b6f9SApple OSS Distributions  */
226*bbb1b6f9SApple OSS Distributions typedef int (^priority_queue_compare_fn_t)(struct priority_queue_entry *e1,
227*bbb1b6f9SApple OSS Distributions     struct priority_queue_entry *e2);
228*bbb1b6f9SApple OSS Distributions 
229*bbb1b6f9SApple OSS Distributions #define priority_heap_compare_ints(a, b) ((a) < (b) ? 1 : -1)
230*bbb1b6f9SApple OSS Distributions 
231*bbb1b6f9SApple OSS Distributions #define priority_heap_make_comparator(name1, name2, type, field, ...) \
232*bbb1b6f9SApple OSS Distributions 	(^int(priority_queue_entry_t __e1, priority_queue_entry_t __e2){        \
233*bbb1b6f9SApple OSS Distributions 	    type *name1 = pqe_element_fast(__e1, type, field);                  \
234*bbb1b6f9SApple OSS Distributions 	    type *name2 = pqe_element_fast(__e2, type, field);                  \
235*bbb1b6f9SApple OSS Distributions 	    __VA_ARGS__;                                                        \
236*bbb1b6f9SApple OSS Distributions 	})
237*bbb1b6f9SApple OSS Distributions 
238*bbb1b6f9SApple OSS Distributions /*
239*bbb1b6f9SApple OSS Distributions  * Type for any priority queue, only used for documentation purposes.
240*bbb1b6f9SApple OSS Distributions  */
241*bbb1b6f9SApple OSS Distributions struct priority_queue;
242*bbb1b6f9SApple OSS Distributions 
243*bbb1b6f9SApple OSS Distributions /*
244*bbb1b6f9SApple OSS Distributions  * Type of generic heaps
245*bbb1b6f9SApple OSS Distributions  */
246*bbb1b6f9SApple OSS Distributions struct priority_queue_min {
247*bbb1b6f9SApple OSS Distributions 	struct priority_queue_entry *pq_root;
248*bbb1b6f9SApple OSS Distributions 	priority_queue_compare_fn_t  pq_cmp_fn;
249*bbb1b6f9SApple OSS Distributions };
250*bbb1b6f9SApple OSS Distributions struct priority_queue_max {
251*bbb1b6f9SApple OSS Distributions 	struct priority_queue_entry *pq_root;
252*bbb1b6f9SApple OSS Distributions 	priority_queue_compare_fn_t  pq_cmp_fn;
253*bbb1b6f9SApple OSS Distributions };
254*bbb1b6f9SApple OSS Distributions 
255*bbb1b6f9SApple OSS Distributions /*
256*bbb1b6f9SApple OSS Distributions  * Type of deadline heaps
257*bbb1b6f9SApple OSS Distributions  */
258*bbb1b6f9SApple OSS Distributions struct priority_queue_deadline_min {
259*bbb1b6f9SApple OSS Distributions 	struct priority_queue_entry_deadline *pq_root;
260*bbb1b6f9SApple OSS Distributions };
261*bbb1b6f9SApple OSS Distributions struct priority_queue_deadline_max {
262*bbb1b6f9SApple OSS Distributions 	struct priority_queue_entry_deadline *pq_root;
263*bbb1b6f9SApple OSS Distributions };
264*bbb1b6f9SApple OSS Distributions 
265*bbb1b6f9SApple OSS Distributions /*
266*bbb1b6f9SApple OSS Distributions  * Type of scheduler priority based heaps
267*bbb1b6f9SApple OSS Distributions  */
268*bbb1b6f9SApple OSS Distributions struct priority_queue_sched_min {
269*bbb1b6f9SApple OSS Distributions 	struct priority_queue_entry_sched *pq_root;
270*bbb1b6f9SApple OSS Distributions };
271*bbb1b6f9SApple OSS Distributions struct priority_queue_sched_max {
272*bbb1b6f9SApple OSS Distributions 	struct priority_queue_entry_sched *pq_root;
273*bbb1b6f9SApple OSS Distributions };
274*bbb1b6f9SApple OSS Distributions 
275*bbb1b6f9SApple OSS Distributions /*
276*bbb1b6f9SApple OSS Distributions  * Type of scheduler priority based stable heaps
277*bbb1b6f9SApple OSS Distributions  */
278*bbb1b6f9SApple OSS Distributions struct priority_queue_sched_stable_min {
279*bbb1b6f9SApple OSS Distributions 	struct priority_queue_entry_stable *pq_root;
280*bbb1b6f9SApple OSS Distributions };
281*bbb1b6f9SApple OSS Distributions struct priority_queue_sched_stable_max {
282*bbb1b6f9SApple OSS Distributions 	struct priority_queue_entry_stable *pq_root;
283*bbb1b6f9SApple OSS Distributions };
284*bbb1b6f9SApple OSS Distributions 
285*bbb1b6f9SApple OSS Distributions #pragma mark generic interface
286*bbb1b6f9SApple OSS Distributions 
287*bbb1b6f9SApple OSS Distributions #define PRIORITY_QUEUE_INITIALIZER { .pq_root = NULL }
288*bbb1b6f9SApple OSS Distributions 
289*bbb1b6f9SApple OSS Distributions #define __pqueue_overloadable  __attribute__((overloadable))
290*bbb1b6f9SApple OSS Distributions 
291*bbb1b6f9SApple OSS Distributions #define priority_queue_is_min_heap(pq) _Generic(pq, \
292*bbb1b6f9SApple OSS Distributions 	struct priority_queue_min *: true, \
293*bbb1b6f9SApple OSS Distributions 	struct priority_queue_max *: false, \
294*bbb1b6f9SApple OSS Distributions 	struct priority_queue_deadline_min *: true, \
295*bbb1b6f9SApple OSS Distributions 	struct priority_queue_deadline_max *: false, \
296*bbb1b6f9SApple OSS Distributions 	struct priority_queue_sched_min *: true, \
297*bbb1b6f9SApple OSS Distributions 	struct priority_queue_sched_max *: false, \
298*bbb1b6f9SApple OSS Distributions 	struct priority_queue_sched_stable_min *: true, \
299*bbb1b6f9SApple OSS Distributions 	struct priority_queue_sched_stable_max *: false)
300*bbb1b6f9SApple OSS Distributions 
301*bbb1b6f9SApple OSS Distributions #define priority_queue_is_max_heap(pq) \
302*bbb1b6f9SApple OSS Distributions 	(!priority_queue_is_min_heap(pq))
303*bbb1b6f9SApple OSS Distributions 
304*bbb1b6f9SApple OSS Distributions /*
305*bbb1b6f9SApple OSS Distributions  *      Macro:          pqe_element_fast
306*bbb1b6f9SApple OSS Distributions  *      Function:
307*bbb1b6f9SApple OSS Distributions  *              Convert a priority_queue_entry_t to a queue element pointer.
308*bbb1b6f9SApple OSS Distributions  *              Get a pointer to the user-defined element containing
309*bbb1b6f9SApple OSS Distributions  *              a given priority_queue_entry_t
310*bbb1b6f9SApple OSS Distributions  *
311*bbb1b6f9SApple OSS Distributions  *              The fast variant assumes that `qe` is not NULL
312*bbb1b6f9SApple OSS Distributions  *      Header:
313*bbb1b6f9SApple OSS Distributions  *              pqe_element_fast(qe, type, field)
314*bbb1b6f9SApple OSS Distributions  *                      <priority_queue_entry_t> qe
315*bbb1b6f9SApple OSS Distributions  *                      <type> type of element in priority queue
316*bbb1b6f9SApple OSS Distributions  *                      <field> chain field in (*<type>)
317*bbb1b6f9SApple OSS Distributions  *      Returns:
318*bbb1b6f9SApple OSS Distributions  *              <type *> containing qe
319*bbb1b6f9SApple OSS Distributions  */
320*bbb1b6f9SApple OSS Distributions #define pqe_element_fast(qe, type, field)  __container_of(qe, type, field)
321*bbb1b6f9SApple OSS Distributions 
322*bbb1b6f9SApple OSS Distributions /*
323*bbb1b6f9SApple OSS Distributions  *      Macro:          pqe_element
324*bbb1b6f9SApple OSS Distributions  *      Function:
325*bbb1b6f9SApple OSS Distributions  *              Convert a priority_queue_entry_t to a queue element pointer.
326*bbb1b6f9SApple OSS Distributions  *              Get a pointer to the user-defined element containing
327*bbb1b6f9SApple OSS Distributions  *              a given priority_queue_entry_t
328*bbb1b6f9SApple OSS Distributions  *
329*bbb1b6f9SApple OSS Distributions  *              The non fast variant handles NULL `qe`
330*bbb1b6f9SApple OSS Distributions  *      Header:
331*bbb1b6f9SApple OSS Distributions  *              pqe_element(qe, type, field)
332*bbb1b6f9SApple OSS Distributions  *                      <priority_queue_entry_t> qe
333*bbb1b6f9SApple OSS Distributions  *                      <type> type of element in priority queue
334*bbb1b6f9SApple OSS Distributions  *                      <field> chain field in (*<type>)
335*bbb1b6f9SApple OSS Distributions  *      Returns:
336*bbb1b6f9SApple OSS Distributions  *              <type *> containing qe
337*bbb1b6f9SApple OSS Distributions  */
338*bbb1b6f9SApple OSS Distributions #define pqe_element(qe, type, field)  ({                                        \
339*bbb1b6f9SApple OSS Distributions 	__auto_type _tmp_entry = (qe);                                          \
340*bbb1b6f9SApple OSS Distributions 	_tmp_entry ? pqe_element_fast(_tmp_entry, type, field) : ((type *)NULL);\
341*bbb1b6f9SApple OSS Distributions })
342*bbb1b6f9SApple OSS Distributions 
343*bbb1b6f9SApple OSS Distributions /*
344*bbb1b6f9SApple OSS Distributions  * Priority Queue functionality routines
345*bbb1b6f9SApple OSS Distributions  */
346*bbb1b6f9SApple OSS Distributions 
347*bbb1b6f9SApple OSS Distributions /*
348*bbb1b6f9SApple OSS Distributions  *      Macro:          priority_queue_empty
349*bbb1b6f9SApple OSS Distributions  *      Function:
350*bbb1b6f9SApple OSS Distributions  *              Tests whether a priority queue is empty.
351*bbb1b6f9SApple OSS Distributions  *      Header:
352*bbb1b6f9SApple OSS Distributions  *              boolean_t priority_queue_empty(pq)
353*bbb1b6f9SApple OSS Distributions  *                      <struct priority_queue *> pq
354*bbb1b6f9SApple OSS Distributions  */
355*bbb1b6f9SApple OSS Distributions #define priority_queue_empty(pq)         ((pq)->pq_root == NULL)
356*bbb1b6f9SApple OSS Distributions 
357*bbb1b6f9SApple OSS Distributions /*
358*bbb1b6f9SApple OSS Distributions  *      Macro:          priority_queue_init
359*bbb1b6f9SApple OSS Distributions  *      Function:
360*bbb1b6f9SApple OSS Distributions  *              Initialize a <struct priority_queue *>.
361*bbb1b6f9SApple OSS Distributions  *      Header:
362*bbb1b6f9SApple OSS Distributions  *              priority_queue_init(pq)
363*bbb1b6f9SApple OSS Distributions  *                      <struct priority_queue *> pq
364*bbb1b6f9SApple OSS Distributions  *                      (optional) <cmp_fn> comparator function
365*bbb1b6f9SApple OSS Distributions  *      Returns:
366*bbb1b6f9SApple OSS Distributions  *              None
367*bbb1b6f9SApple OSS Distributions  */
368*bbb1b6f9SApple OSS Distributions __pqueue_overloadable
369*bbb1b6f9SApple OSS Distributions extern void
370*bbb1b6f9SApple OSS Distributions priority_queue_init(struct priority_queue *pq, ...);
371*bbb1b6f9SApple OSS Distributions 
372*bbb1b6f9SApple OSS Distributions /*
373*bbb1b6f9SApple OSS Distributions  *      Macro:          priority_queue_entry_init
374*bbb1b6f9SApple OSS Distributions  *      Function:
375*bbb1b6f9SApple OSS Distributions  *              Initialize a priority_queue_entry_t
376*bbb1b6f9SApple OSS Distributions  *      Header:
377*bbb1b6f9SApple OSS Distributions  *              priority_queue_entry_init(qe)
378*bbb1b6f9SApple OSS Distributions  *                      <priority_queue_entry_t> qe
379*bbb1b6f9SApple OSS Distributions  *      Returns:
380*bbb1b6f9SApple OSS Distributions  *              None
381*bbb1b6f9SApple OSS Distributions  */
382*bbb1b6f9SApple OSS Distributions #define priority_queue_entry_init(qe) \
383*bbb1b6f9SApple OSS Distributions 	__builtin_bzero(qe, sizeof(*(qe)))
384*bbb1b6f9SApple OSS Distributions 
385*bbb1b6f9SApple OSS Distributions /*
386*bbb1b6f9SApple OSS Distributions  *      Macro:          priority_queue_destroy
387*bbb1b6f9SApple OSS Distributions  *      Function:
388*bbb1b6f9SApple OSS Distributions  *              Destroy a priority queue safely. This routine accepts a callback
389*bbb1b6f9SApple OSS Distributions  *              to handle any cleanup for elements in the priority queue. The queue does
390*bbb1b6f9SApple OSS Distributions  *              not maintain its invariants while getting destroyed. The priority queue and
391*bbb1b6f9SApple OSS Distributions  *              the linkage nodes need to be re-initialized before re-using them.
392*bbb1b6f9SApple OSS Distributions  *      Header:
393*bbb1b6f9SApple OSS Distributions  *              priority_queue_destroy(pq, type, field, callback)
394*bbb1b6f9SApple OSS Distributions  *                      <struct priority_queue *> pq
395*bbb1b6f9SApple OSS Distributions  *                      <callback> callback for each element
396*bbb1b6f9SApple OSS Distributions  *
397*bbb1b6f9SApple OSS Distributions  *      Returns:
398*bbb1b6f9SApple OSS Distributions  *              None
399*bbb1b6f9SApple OSS Distributions  */
400*bbb1b6f9SApple OSS Distributions #define priority_queue_destroy(pq, type, field, callback)                       \
401*bbb1b6f9SApple OSS Distributions MACRO_BEGIN                                                                     \
402*bbb1b6f9SApple OSS Distributions 	void (^__callback)(type *) = (callback); /* type check */               \
403*bbb1b6f9SApple OSS Distributions 	_priority_queue_destroy(pq, offsetof(type, field),                      \
404*bbb1b6f9SApple OSS Distributions 	    (void (^)(void *))(__callback));                                    \
405*bbb1b6f9SApple OSS Distributions MACRO_END
406*bbb1b6f9SApple OSS Distributions 
407*bbb1b6f9SApple OSS Distributions /*
408*bbb1b6f9SApple OSS Distributions  *      Macro:          priority_queue_min
409*bbb1b6f9SApple OSS Distributions  *      Function:
410*bbb1b6f9SApple OSS Distributions  *              Lookup the minimum in a min-priority queue.
411*bbb1b6f9SApple OSS Distributions  *
412*bbb1b6f9SApple OSS Distributions  *      Header:
413*bbb1b6f9SApple OSS Distributions  *              priority_queue_min(pq, type, field)
414*bbb1b6f9SApple OSS Distributions  *                      <struct priority_queue *> pq
415*bbb1b6f9SApple OSS Distributions  *                      <type> type of element in priority queue
416*bbb1b6f9SApple OSS Distributions  *                      <field> chain field in (*<type>)
417*bbb1b6f9SApple OSS Distributions  *      Returns:
418*bbb1b6f9SApple OSS Distributions  *              <type *> root element
419*bbb1b6f9SApple OSS Distributions  */
420*bbb1b6f9SApple OSS Distributions #define priority_queue_min(pq, type, field) ({                                  \
421*bbb1b6f9SApple OSS Distributions 	static_assert(priority_queue_is_min_heap(pq), "queue is min heap");     \
422*bbb1b6f9SApple OSS Distributions 	pqe_element((pq)->pq_root, type, field);                                \
423*bbb1b6f9SApple OSS Distributions })
424*bbb1b6f9SApple OSS Distributions 
425*bbb1b6f9SApple OSS Distributions /*
426*bbb1b6f9SApple OSS Distributions  *      Macro:          priority_queue_max
427*bbb1b6f9SApple OSS Distributions  *      Function:
428*bbb1b6f9SApple OSS Distributions  *              Lookup the maximum element in a max-priority queue.
429*bbb1b6f9SApple OSS Distributions  *
430*bbb1b6f9SApple OSS Distributions  *      Header:
431*bbb1b6f9SApple OSS Distributions  *              priority_queue_max(pq, type, field)
432*bbb1b6f9SApple OSS Distributions  *                      <struct priority_queue *> pq
433*bbb1b6f9SApple OSS Distributions  *                      <type> type of element in priority queue
434*bbb1b6f9SApple OSS Distributions  *                      <field> chain field in (*<type>)
435*bbb1b6f9SApple OSS Distributions  *      Returns:
436*bbb1b6f9SApple OSS Distributions  *              <type *> root element
437*bbb1b6f9SApple OSS Distributions  */
438*bbb1b6f9SApple OSS Distributions #define priority_queue_max(pq, type, field) ({                                  \
439*bbb1b6f9SApple OSS Distributions 	static_assert(priority_queue_is_max_heap(pq), "queue is max heap");     \
440*bbb1b6f9SApple OSS Distributions 	pqe_element((pq)->pq_root, type, field);                                \
441*bbb1b6f9SApple OSS Distributions })
442*bbb1b6f9SApple OSS Distributions 
443*bbb1b6f9SApple OSS Distributions /*
444*bbb1b6f9SApple OSS Distributions  *      Macro:          priority_queue_insert
445*bbb1b6f9SApple OSS Distributions  *      Function:
446*bbb1b6f9SApple OSS Distributions  *              Insert an element into the priority queue
447*bbb1b6f9SApple OSS Distributions  *
448*bbb1b6f9SApple OSS Distributions  *              The caller must have set the key prio to insertion
449*bbb1b6f9SApple OSS Distributions  *
450*bbb1b6f9SApple OSS Distributions  *      Header:
451*bbb1b6f9SApple OSS Distributions  *              priority_queue_insert(pq, elt, new_key)
452*bbb1b6f9SApple OSS Distributions  *                      <struct priority_queue *> pq
453*bbb1b6f9SApple OSS Distributions  *                      <priority_queue_entry_t> elt
454*bbb1b6f9SApple OSS Distributions  *      Returns:
455*bbb1b6f9SApple OSS Distributions  *              Whether the inserted element became the new root
456*bbb1b6f9SApple OSS Distributions  */
457*bbb1b6f9SApple OSS Distributions extern bool
458*bbb1b6f9SApple OSS Distributions priority_queue_insert(struct priority_queue *pq,
459*bbb1b6f9SApple OSS Distributions     struct priority_queue_entry *elt) __pqueue_overloadable;
460*bbb1b6f9SApple OSS Distributions 
461*bbb1b6f9SApple OSS Distributions /*
462*bbb1b6f9SApple OSS Distributions  *      Macro:          priority_queue_remove_min
463*bbb1b6f9SApple OSS Distributions  *      Function:
464*bbb1b6f9SApple OSS Distributions  *              Remove the minimum element in a min-heap priority queue.
465*bbb1b6f9SApple OSS Distributions  *      Header:
466*bbb1b6f9SApple OSS Distributions  *              priority_queue_remove_min(pq, type, field)
467*bbb1b6f9SApple OSS Distributions  *                      <struct priority_queue *> pq
468*bbb1b6f9SApple OSS Distributions  *                      <type> type of element in priority queue
469*bbb1b6f9SApple OSS Distributions  *                      <field> chain field in (*<type>)
470*bbb1b6f9SApple OSS Distributions  *      Returns:
471*bbb1b6f9SApple OSS Distributions  *              <type *> max element
472*bbb1b6f9SApple OSS Distributions  */
473*bbb1b6f9SApple OSS Distributions #define priority_queue_remove_min(pq, type, field) ({                           \
474*bbb1b6f9SApple OSS Distributions 	static_assert(priority_queue_is_min_heap(pq), "queue is min heap");     \
475*bbb1b6f9SApple OSS Distributions 	pqe_element(_priority_queue_remove_root(pq), type, field);              \
476*bbb1b6f9SApple OSS Distributions })
477*bbb1b6f9SApple OSS Distributions 
478*bbb1b6f9SApple OSS Distributions /*
479*bbb1b6f9SApple OSS Distributions  *      Macro:          priority_queue_remove_max
480*bbb1b6f9SApple OSS Distributions  *      Function:
481*bbb1b6f9SApple OSS Distributions  *              Remove the maximum element in a max-heap priority queue.
482*bbb1b6f9SApple OSS Distributions  *      Header:
483*bbb1b6f9SApple OSS Distributions  *              priority_queue_remove_max(pq, type, field)
484*bbb1b6f9SApple OSS Distributions  *                      <struct priority_queue *> pq
485*bbb1b6f9SApple OSS Distributions  *                      <type> type of element in priority queue
486*bbb1b6f9SApple OSS Distributions  *                      <field> chain field in (*<type>)
487*bbb1b6f9SApple OSS Distributions  *      Returns:
488*bbb1b6f9SApple OSS Distributions  *              <type *> max element
489*bbb1b6f9SApple OSS Distributions  */
490*bbb1b6f9SApple OSS Distributions #define priority_queue_remove_max(pq, type, field) ({                           \
491*bbb1b6f9SApple OSS Distributions 	static_assert(priority_queue_is_max_heap(pq), "queue is max heap");     \
492*bbb1b6f9SApple OSS Distributions 	pqe_element(_priority_queue_remove_root(pq), type, field);              \
493*bbb1b6f9SApple OSS Distributions })
494*bbb1b6f9SApple OSS Distributions 
495*bbb1b6f9SApple OSS Distributions /*
496*bbb1b6f9SApple OSS Distributions  *      Macro:          priority_queue_remove
497*bbb1b6f9SApple OSS Distributions  *      Function:
498*bbb1b6f9SApple OSS Distributions  *              Removes an element from the priority queue
499*bbb1b6f9SApple OSS Distributions  *      Header:
500*bbb1b6f9SApple OSS Distributions  *              priority_queue_remove(pq, elt)
501*bbb1b6f9SApple OSS Distributions  *                      <struct priority_queue *> pq
502*bbb1b6f9SApple OSS Distributions  *                      <priority_queue_entry_t> elt
503*bbb1b6f9SApple OSS Distributions  *      Returns:
504*bbb1b6f9SApple OSS Distributions  *              Whether the removed element was the root
505*bbb1b6f9SApple OSS Distributions  */
506*bbb1b6f9SApple OSS Distributions extern bool
507*bbb1b6f9SApple OSS Distributions priority_queue_remove(struct priority_queue *pq,
508*bbb1b6f9SApple OSS Distributions     struct priority_queue_entry *elt) __pqueue_overloadable;
509*bbb1b6f9SApple OSS Distributions 
510*bbb1b6f9SApple OSS Distributions 
511*bbb1b6f9SApple OSS Distributions /*
512*bbb1b6f9SApple OSS Distributions  *      Macro:          priority_queue_entry_decreased
513*bbb1b6f9SApple OSS Distributions  *
514*bbb1b6f9SApple OSS Distributions  *      Function:
515*bbb1b6f9SApple OSS Distributions  *              Signal the priority queue that the entry priority has decreased.
516*bbb1b6f9SApple OSS Distributions  *
517*bbb1b6f9SApple OSS Distributions  *              The new value for the element priority must have been set
518*bbb1b6f9SApple OSS Distributions  *              prior to calling this function.
519*bbb1b6f9SApple OSS Distributions  *
520*bbb1b6f9SApple OSS Distributions  *      Header:
521*bbb1b6f9SApple OSS Distributions  *              priority_queue_entry_decreased(pq, elt)
522*bbb1b6f9SApple OSS Distributions  *                      <struct priority_queue *> pq
523*bbb1b6f9SApple OSS Distributions  *                      <priority_queue_entry_t> elt
524*bbb1b6f9SApple OSS Distributions  *      Returns:
525*bbb1b6f9SApple OSS Distributions  *              Whether the update caused the root or its key to change.
526*bbb1b6f9SApple OSS Distributions  */
527*bbb1b6f9SApple OSS Distributions extern bool
528*bbb1b6f9SApple OSS Distributions priority_queue_entry_decreased(struct priority_queue *pq,
529*bbb1b6f9SApple OSS Distributions     struct priority_queue_entry *elt) __pqueue_overloadable;
530*bbb1b6f9SApple OSS Distributions 
531*bbb1b6f9SApple OSS Distributions /*
532*bbb1b6f9SApple OSS Distributions  *      Macro:          priority_queue_entry_increased
533*bbb1b6f9SApple OSS Distributions  *
534*bbb1b6f9SApple OSS Distributions  *      Function:
535*bbb1b6f9SApple OSS Distributions  *              Signal the priority queue that the entry priority has increased.
536*bbb1b6f9SApple OSS Distributions  *
537*bbb1b6f9SApple OSS Distributions  *              The new value for the element priority must have been set
538*bbb1b6f9SApple OSS Distributions  *              prior to calling this function.
539*bbb1b6f9SApple OSS Distributions  *
540*bbb1b6f9SApple OSS Distributions  *      Header:
541*bbb1b6f9SApple OSS Distributions  *              priority_queue_entry_increased(pq, elt, new_key)
542*bbb1b6f9SApple OSS Distributions  *                      <struct priority_queue *> pq
543*bbb1b6f9SApple OSS Distributions  *                      <priority_queue_entry_t> elt
544*bbb1b6f9SApple OSS Distributions  *      Returns:
545*bbb1b6f9SApple OSS Distributions  *              Whether the update caused the root or its key to change.
546*bbb1b6f9SApple OSS Distributions  */
547*bbb1b6f9SApple OSS Distributions extern bool
548*bbb1b6f9SApple OSS Distributions priority_queue_entry_increased(struct priority_queue *pq,
549*bbb1b6f9SApple OSS Distributions     struct priority_queue_entry *elt) __pqueue_overloadable;
550*bbb1b6f9SApple OSS Distributions 
551*bbb1b6f9SApple OSS Distributions 
552*bbb1b6f9SApple OSS Distributions #pragma mark priority_queue_sched_*
553*bbb1b6f9SApple OSS Distributions 
554*bbb1b6f9SApple OSS Distributions __enum_decl(priority_queue_entry_sched_modifier_t, uint8_t, {
555*bbb1b6f9SApple OSS Distributions 	PRIORITY_QUEUE_ENTRY_NONE      = 0,
556*bbb1b6f9SApple OSS Distributions 	PRIORITY_QUEUE_ENTRY_PREEMPTED = 1,
557*bbb1b6f9SApple OSS Distributions });
558*bbb1b6f9SApple OSS Distributions 
559*bbb1b6f9SApple OSS Distributions #define priority_queue_is_sched_heap(pq) _Generic(pq, \
560*bbb1b6f9SApple OSS Distributions 	struct priority_queue_sched_min *: true, \
561*bbb1b6f9SApple OSS Distributions 	struct priority_queue_sched_max *: true, \
562*bbb1b6f9SApple OSS Distributions 	struct priority_queue_sched_stable_min *: true, \
563*bbb1b6f9SApple OSS Distributions 	struct priority_queue_sched_stable_max *: true, \
564*bbb1b6f9SApple OSS Distributions 	default: false)
565*bbb1b6f9SApple OSS Distributions 
566*bbb1b6f9SApple OSS Distributions /*
567*bbb1b6f9SApple OSS Distributions  *      Macro:          priority_queue_entry_set_sched_pri
568*bbb1b6f9SApple OSS Distributions  *
569*bbb1b6f9SApple OSS Distributions  *      Function:
570*bbb1b6f9SApple OSS Distributions  *              Sets the scheduler priority on an entry supporting this concept.
571*bbb1b6f9SApple OSS Distributions  *
572*bbb1b6f9SApple OSS Distributions  *              The priority is expected to fit on 8 bits.
573*bbb1b6f9SApple OSS Distributions  *              An optional sorting modifier.
574*bbb1b6f9SApple OSS Distributions  *
575*bbb1b6f9SApple OSS Distributions  *      Header:
576*bbb1b6f9SApple OSS Distributions  *              priority_queue_entry_set_sched_pri(pq, elt, pri, modifier)
577*bbb1b6f9SApple OSS Distributions  *                      <struct priority_queue *> pq
578*bbb1b6f9SApple OSS Distributions  *                      <priority_queue_entry_t> elt
579*bbb1b6f9SApple OSS Distributions  *                      <uint8_t> pri
580*bbb1b6f9SApple OSS Distributions  *                      <priority_queue_entry_sched_modifier_t> modifier
581*bbb1b6f9SApple OSS Distributions  */
582*bbb1b6f9SApple OSS Distributions #define priority_queue_entry_set_sched_pri(pq, elt, pri, modifier)              \
583*bbb1b6f9SApple OSS Distributions MACRO_BEGIN                                                                     \
584*bbb1b6f9SApple OSS Distributions 	static_assert(priority_queue_is_sched_heap(pq), "is a sched heap");     \
585*bbb1b6f9SApple OSS Distributions 	(elt)->key = (priority_queue_key_t)(((pri) << 8) + (modifier));         \
586*bbb1b6f9SApple OSS Distributions MACRO_END
587*bbb1b6f9SApple OSS Distributions 
588*bbb1b6f9SApple OSS Distributions /*
589*bbb1b6f9SApple OSS Distributions  *      Macro:          priority_queue_entry_sched_pri
590*bbb1b6f9SApple OSS Distributions  *
591*bbb1b6f9SApple OSS Distributions  *      Function:
592*bbb1b6f9SApple OSS Distributions  *              Return the scheduler priority on an entry supporting this
593*bbb1b6f9SApple OSS Distributions  *              concept.
594*bbb1b6f9SApple OSS Distributions  *
595*bbb1b6f9SApple OSS Distributions  *      Header:
596*bbb1b6f9SApple OSS Distributions  *              priority_queue_entry_sched_pri(pq, elt)
597*bbb1b6f9SApple OSS Distributions  *                      <struct priority_queue *> pq
598*bbb1b6f9SApple OSS Distributions  *                      <priority_queue_entry_t> elt
599*bbb1b6f9SApple OSS Distributions  *
600*bbb1b6f9SApple OSS Distributions  *      Returns:
601*bbb1b6f9SApple OSS Distributions  *              The scheduler priority of this entry
602*bbb1b6f9SApple OSS Distributions  */
603*bbb1b6f9SApple OSS Distributions #define priority_queue_entry_sched_pri(pq, elt) ({                              \
604*bbb1b6f9SApple OSS Distributions 	static_assert(priority_queue_is_sched_heap(pq), "is a sched heap");     \
605*bbb1b6f9SApple OSS Distributions 	(priority_queue_key_t)((elt)->key >> 8);                                \
606*bbb1b6f9SApple OSS Distributions })
607*bbb1b6f9SApple OSS Distributions 
608*bbb1b6f9SApple OSS Distributions /*
609*bbb1b6f9SApple OSS Distributions  *      Macro:          priority_queue_entry_sched_modifier
610*bbb1b6f9SApple OSS Distributions  *
611*bbb1b6f9SApple OSS Distributions  *      Function:
612*bbb1b6f9SApple OSS Distributions  *              Return the scheduler modifier on an entry supporting this
613*bbb1b6f9SApple OSS Distributions  *              concept.
614*bbb1b6f9SApple OSS Distributions  *
615*bbb1b6f9SApple OSS Distributions  *      Header:
616*bbb1b6f9SApple OSS Distributions  *              priority_queue_entry_sched_modifier(pq, elt)
617*bbb1b6f9SApple OSS Distributions  *                      <struct priority_queue *> pq
618*bbb1b6f9SApple OSS Distributions  *                      <priority_queue_entry_t> elt
619*bbb1b6f9SApple OSS Distributions  *
620*bbb1b6f9SApple OSS Distributions  *      Returns:
621*bbb1b6f9SApple OSS Distributions  *              The scheduler priority of this entry
622*bbb1b6f9SApple OSS Distributions  */
623*bbb1b6f9SApple OSS Distributions #define priority_queue_entry_sched_modifier(pq, elt) ({                         \
624*bbb1b6f9SApple OSS Distributions 	static_assert(priority_queue_is_sched_heap(pq), "is a sched heap");     \
625*bbb1b6f9SApple OSS Distributions 	(priority_queue_entry_sched_modifier_t)(elt)->key;                      \
626*bbb1b6f9SApple OSS Distributions })
627*bbb1b6f9SApple OSS Distributions 
628*bbb1b6f9SApple OSS Distributions /*
629*bbb1b6f9SApple OSS Distributions  *      Macro:          priority_queue_min_sched_pri
630*bbb1b6f9SApple OSS Distributions  *
631*bbb1b6f9SApple OSS Distributions  *      Function:
632*bbb1b6f9SApple OSS Distributions  *              Return the scheduler priority of the minimum element
633*bbb1b6f9SApple OSS Distributions  *              of a scheduler priority queue.
634*bbb1b6f9SApple OSS Distributions  *
635*bbb1b6f9SApple OSS Distributions  *      Header:
636*bbb1b6f9SApple OSS Distributions  *              priority_queue_min_sched_pri(pq)
637*bbb1b6f9SApple OSS Distributions  *                      <struct priority_queue *> pq
638*bbb1b6f9SApple OSS Distributions  *
639*bbb1b6f9SApple OSS Distributions  *      Returns:
640*bbb1b6f9SApple OSS Distributions  *              The scheduler priority of this entry
641*bbb1b6f9SApple OSS Distributions  */
642*bbb1b6f9SApple OSS Distributions #define priority_queue_min_sched_pri(pq) ({                                     \
643*bbb1b6f9SApple OSS Distributions 	static_assert(priority_queue_is_min_heap(pq), "queue is min heap");     \
644*bbb1b6f9SApple OSS Distributions 	priority_queue_entry_sched_pri(pq, (pq)->pq_root);                      \
645*bbb1b6f9SApple OSS Distributions })
646*bbb1b6f9SApple OSS Distributions 
647*bbb1b6f9SApple OSS Distributions /*
648*bbb1b6f9SApple OSS Distributions  *      Macro:          priority_queue_max_sched_pri
649*bbb1b6f9SApple OSS Distributions  *
650*bbb1b6f9SApple OSS Distributions  *      Function:
651*bbb1b6f9SApple OSS Distributions  *              Return the scheduler priority of the maximum element
652*bbb1b6f9SApple OSS Distributions  *              of a scheduler priority queue.
653*bbb1b6f9SApple OSS Distributions  *
654*bbb1b6f9SApple OSS Distributions  *      Header:
655*bbb1b6f9SApple OSS Distributions  *              priority_queue_max_sched_pri(pq)
656*bbb1b6f9SApple OSS Distributions  *                      <struct priority_queue *> pq
657*bbb1b6f9SApple OSS Distributions  *
658*bbb1b6f9SApple OSS Distributions  *      Returns:
659*bbb1b6f9SApple OSS Distributions  *              The scheduler priority of this entry
660*bbb1b6f9SApple OSS Distributions  */
661*bbb1b6f9SApple OSS Distributions #define priority_queue_max_sched_pri(pq) ({                                     \
662*bbb1b6f9SApple OSS Distributions 	static_assert(priority_queue_is_max_heap(pq), "queue is max heap");     \
663*bbb1b6f9SApple OSS Distributions 	priority_queue_entry_sched_pri(pq, (pq)->pq_root);                      \
664*bbb1b6f9SApple OSS Distributions })
665*bbb1b6f9SApple OSS Distributions 
666*bbb1b6f9SApple OSS Distributions 
667*bbb1b6f9SApple OSS Distributions #pragma mark implementation details
668*bbb1b6f9SApple OSS Distributions 
669*bbb1b6f9SApple OSS Distributions #define PRIORITY_QUEUE_MAKE_BASE(pqueue_t, pqelem_t) \
670*bbb1b6f9SApple OSS Distributions                                                                                 \
671*bbb1b6f9SApple OSS Distributions __pqueue_overloadable extern void                                               \
672*bbb1b6f9SApple OSS Distributions _priority_queue_destroy(pqueue_t pq, uintptr_t offset, void (^cb)(void *));     \
673*bbb1b6f9SApple OSS Distributions                                                                                 \
674*bbb1b6f9SApple OSS Distributions __pqueue_overloadable extern bool                                               \
675*bbb1b6f9SApple OSS Distributions priority_queue_insert(pqueue_t que, pqelem_t elt);                              \
676*bbb1b6f9SApple OSS Distributions                                                                                 \
677*bbb1b6f9SApple OSS Distributions __pqueue_overloadable extern pqelem_t                                           \
678*bbb1b6f9SApple OSS Distributions _priority_queue_remove_root(pqueue_t que);                                      \
679*bbb1b6f9SApple OSS Distributions                                                                                 \
680*bbb1b6f9SApple OSS Distributions __pqueue_overloadable extern bool                                               \
681*bbb1b6f9SApple OSS Distributions priority_queue_remove(pqueue_t que, pqelem_t elt);                              \
682*bbb1b6f9SApple OSS Distributions                                                                                 \
683*bbb1b6f9SApple OSS Distributions __pqueue_overloadable extern bool                                               \
684*bbb1b6f9SApple OSS Distributions priority_queue_entry_decreased(pqueue_t que, pqelem_t elt);                     \
685*bbb1b6f9SApple OSS Distributions                                                                                 \
686*bbb1b6f9SApple OSS Distributions __pqueue_overloadable extern bool                                               \
687*bbb1b6f9SApple OSS Distributions priority_queue_entry_increased(pqueue_t que, pqelem_t elt)
688*bbb1b6f9SApple OSS Distributions 
689*bbb1b6f9SApple OSS Distributions #define PRIORITY_QUEUE_MAKE(pqueue_t, pqelem_t) \
690*bbb1b6f9SApple OSS Distributions __pqueue_overloadable                                                           \
691*bbb1b6f9SApple OSS Distributions static inline void                                                              \
692*bbb1b6f9SApple OSS Distributions priority_queue_init(pqueue_t que)                                               \
693*bbb1b6f9SApple OSS Distributions {                                                                               \
694*bbb1b6f9SApple OSS Distributions 	__builtin_bzero(que, sizeof(*que));                                     \
695*bbb1b6f9SApple OSS Distributions }                                                                               \
696*bbb1b6f9SApple OSS Distributions                                                                                 \
697*bbb1b6f9SApple OSS Distributions PRIORITY_QUEUE_MAKE_BASE(pqueue_t, pqelem_t)
698*bbb1b6f9SApple OSS Distributions 
699*bbb1b6f9SApple OSS Distributions #define PRIORITY_QUEUE_MAKE_CB(pqueue_t, pqelem_t) \
700*bbb1b6f9SApple OSS Distributions __pqueue_overloadable                                                           \
701*bbb1b6f9SApple OSS Distributions static inline void                                                              \
702*bbb1b6f9SApple OSS Distributions priority_queue_init(pqueue_t pq, priority_queue_compare_fn_t cmp_fn)            \
703*bbb1b6f9SApple OSS Distributions {                                                                               \
704*bbb1b6f9SApple OSS Distributions 	pq->pq_root = NULL;                                                     \
705*bbb1b6f9SApple OSS Distributions 	pq->pq_cmp_fn = cmp_fn;                                                 \
706*bbb1b6f9SApple OSS Distributions }                                                                               \
707*bbb1b6f9SApple OSS Distributions                                                                                 \
708*bbb1b6f9SApple OSS Distributions PRIORITY_QUEUE_MAKE_BASE(pqueue_t, pqelem_t)
709*bbb1b6f9SApple OSS Distributions 
710*bbb1b6f9SApple OSS Distributions PRIORITY_QUEUE_MAKE_CB(struct priority_queue_min *, priority_queue_entry_t);
711*bbb1b6f9SApple OSS Distributions PRIORITY_QUEUE_MAKE_CB(struct priority_queue_max *, priority_queue_entry_t);
712*bbb1b6f9SApple OSS Distributions 
713*bbb1b6f9SApple OSS Distributions PRIORITY_QUEUE_MAKE(struct priority_queue_deadline_min *, priority_queue_entry_deadline_t);
714*bbb1b6f9SApple OSS Distributions PRIORITY_QUEUE_MAKE(struct priority_queue_deadline_max *, priority_queue_entry_deadline_t);
715*bbb1b6f9SApple OSS Distributions 
716*bbb1b6f9SApple OSS Distributions PRIORITY_QUEUE_MAKE(struct priority_queue_sched_min *, priority_queue_entry_sched_t);
717*bbb1b6f9SApple OSS Distributions PRIORITY_QUEUE_MAKE(struct priority_queue_sched_max *, priority_queue_entry_sched_t);
718*bbb1b6f9SApple OSS Distributions 
719*bbb1b6f9SApple OSS Distributions PRIORITY_QUEUE_MAKE(struct priority_queue_sched_stable_min *, priority_queue_entry_stable_t);
720*bbb1b6f9SApple OSS Distributions PRIORITY_QUEUE_MAKE(struct priority_queue_sched_stable_max *, priority_queue_entry_stable_t);
721*bbb1b6f9SApple OSS Distributions 
722*bbb1b6f9SApple OSS Distributions __END_DECLS
723*bbb1b6f9SApple OSS Distributions 
724*bbb1b6f9SApple OSS Distributions #pragma GCC visibility pop
725*bbb1b6f9SApple OSS Distributions 
726*bbb1b6f9SApple OSS Distributions #endif /* _KERN_PRIORITY_QUEUE_H_ */
727