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