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