xref: /xnu-12377.81.4/osfmk/kern/sched_common.h (revision 043036a2b3718f7f0be807e2870f8f47d3fa0796) !
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