1 /* 2 * Copyright (c) 2024 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_SCHED_COMMON_H_ 30 #define _KERN_SCHED_COMMON_H_ 31 32 #include <stdint.h> 33 34 #include <kern/assert.h> 35 #include <kern/qsort.h> 36 #include <kern/smp.h> 37 38 typedef uint8_t pset_id_t; 39 static_assert(MAX_PSETS < UINT8_MAX, "Can store pset ids within 8 bits"); 40 #define PSET_ID_INVALID UINT8_MAX 41 42 #if __AMP__ 43 44 /* How many psets the system is configured to use. Only values less than 45 * sched_num_psets are considered valid pset IDs. */ 46 extern uint8_t sched_num_psets; 47 48 /* 49 * sched_pset_search_order_t 50 * 51 * Used for storing a computed search order of pset ids, relative to a 52 * scanning pset not included in the list. 53 * 54 * Storing/accessing the search order atomically avoids issues caused 55 * by editing the search order while processors are in the middle of 56 * traversing it, for example causing them to miss a pset or visit a 57 * particular pset more than once. Instead, the search order should be 58 * read atomically before traversing, so that new edits are ignored by 59 * that processor until its traversal is complete. 60 */ 61 typedef union { 62 pset_id_t spso_search_order[MAX_PSETS - 1]; 63 unsigned __int128 spso_packed; 64 } sched_pset_search_order_t; 65 66 static_assert(sizeof(sched_pset_search_order_t) <= sizeof(unsigned __int128), 67 "(MAX_PSETS - 1) * 8 bits fits in 128 bits, allowing sched_pset_search_order_t fields " 68 "to be accessed atomically"); 69 70 typedef struct processor_set *processor_set_t; 71 72 /* 73 * sched_pset_search_order_sort_data_t 74 * 75 * Pset data used when generating search orders, expected to be 76 * populated for each pset before calling sched_pset_search_order_compute() 77 */ 78 typedef struct { 79 processor_set_t spsosd_src_pset; 80 uint64_t spsosd_migration_weight; 81 pset_id_t spsosd_dst_pset_id; 82 } sched_pset_search_order_sort_data_t; 83 84 /* 85 * sched_pset_search_order_sort_cmpfunc_t 86 * 87 * Expected to compare two sched_pset_search_order_sort_data_t pointers, 88 * for the purpose of generating a pset search order. 89 */ 90 typedef cmpfunc_t sched_pset_search_order_sort_cmpfunc_t; 91 92 /* 93 * sched_pset_search_order_compute() 94 * 95 * Generates a pset search order by sorting the per-pset search order datas 96 * using the given comparator. 97 */ 98 void 99 sched_pset_search_order_compute(sched_pset_search_order_t *search_order_out, 100 sched_pset_search_order_sort_data_t *datas, size_t num_datas, 101 sched_pset_search_order_sort_cmpfunc_t cmp); 102 103 /* 104 * sched_pset_search_order_init() 105 * 106 * Generates a search order of all psets sorted by increasing pset id, still 107 * excluding the source pset. 108 */ 109 void 110 sched_pset_search_order_init(processor_set_t src_pset, sched_pset_search_order_t *search_order_out); 111 112 /* Options specifying how to iterate the search order */ 113 __options_decl(sched_pset_iterate_state_options_t, uint32_t, { 114 SCHED_PSET_ITERATE_STATE_OPTIONS_NONE = 0x0, 115 SCHED_PSET_ITERATE_STATE_OPTIONS_REVERSE = 0x1, 116 }); 117 118 /* 119 * sched_pset_iterate_state_t 120 * 121 * Used for tracking state across calls to sched_iterate_psets_ordered() 122 * for the same search order traversal, and for returning the current pset_id. 123 */ 124 typedef struct { 125 int spis_search_index; 126 sched_pset_search_order_t spis_cached_search_order; 127 pset_id_t spis_pset_id; // out 128 sched_pset_iterate_state_options_t spis_options; // in 129 int spis_valid_len; 130 } sched_pset_iterate_state_t; 131 132 #define SCHED_PSET_ITERATE_STATE_INIT ((sched_pset_iterate_state_t) \ 133 { .spis_search_index = -1, .spis_options = SCHED_PSET_ITERATE_STATE_OPTIONS_NONE }) 134 135 /* 136 * sched_iterate_psets_ordered() 137 * 138 * Routine to iterate through candidate psets based on a given search_order 139 * and starting from starting_pset. 140 * Returns true if iteration continues and another candidate pset was found, 141 * which will be stored at istate->spis_pset_id. Returns false and 142 * istate->spis_pset_id of -1 once iteration is complete. Iterate state should 143 * start out initialized to SCHED_PSET_ITERATE_STATE_INIT. 144 */ 145 bool 146 sched_iterate_psets_ordered(processor_set_t starting_pset, sched_pset_search_order_t *search_order, 147 uint64_t candidate_map, sched_pset_iterate_state_t *istate); 148 149 #endif /* __AMP__ */ 150 151 #endif /* _KERN_SCHED_COMMON_H_ */ 152