This is xnu-12377.1.9. See this file in:
/*
 * Copyright (c) 2024 Apple Inc. All rights reserved.
 *
 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
 *
 * This file contains Original Code and/or Modifications of Original Code
 * as defined in and that are subject to the Apple Public Source License
 * Version 2.0 (the 'License'). You may not use this file except in
 * compliance with the License. The rights granted to you under the License
 * may not be used to create, or enable the creation or redistribution of,
 * unlawful or unlicensed copies of an Apple operating system, or to
 * circumvent, violate, or enable the circumvention or violation of, any
 * terms of an Apple operating system software license agreement.
 *
 * Please obtain a copy of the License at
 * http://www.opensource.apple.com/apsl/ and read it before using this file.
 *
 * The Original Code and all software distributed under the License are
 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
 * Please see the License for the specific language governing rights and
 * limitations under the License.
 *
 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
 */

#ifndef _KERN_SCHED_COMMON_H_
#define _KERN_SCHED_COMMON_H_

#include <kern/assert.h>
#include <kern/qsort.h>
#include <kern/smp.h>

typedef uint8_t pset_id_t;
static_assert(MAX_PSETS < UINT8_MAX, "Can store pset ids within 8 bits");
#define PSET_ID_INVALID UINT8_MAX

#if __AMP__

/*
 * sched_pset_search_order_t
 *
 * Used for storing a computed search order of pset ids, relative to a
 * scanning pset not included in the list.
 *
 * Storing/accessing the search order atomically avoids issues caused
 * by editing the search order while processors are in the middle of
 * traversing it, for example causing them to miss a pset or visit a
 * particular pset more than once. Instead, the search order should be
 * read atomically before traversing, so that new edits are ignored by
 * that processor until its traversal is complete.
 */
typedef union {
	pset_id_t spso_search_order[MAX_PSETS - 1];
	unsigned __int128 spso_packed;
} sched_pset_search_order_t;

static_assert(sizeof(sched_pset_search_order_t) <= sizeof(unsigned __int128),
    "(MAX_PSETS - 1) * 8 bits fits in 128 bits, allowing sched_pset_search_order_t fields "
    "to be accessed atomically");

typedef struct processor_set *processor_set_t;

/*
 * sched_pset_search_order_sort_data_t
 *
 * Pset data used when generating search orders, expected to be
 * populated for each pset before calling sched_pset_search_order_compute()
 */
typedef struct {
	processor_set_t spsosd_src_pset;
	uint64_t spsosd_migration_weight;
	pset_id_t spsosd_dst_pset_id;
} sched_pset_search_order_sort_data_t;

/*
 * sched_pset_search_order_sort_cmpfunc_t
 *
 * Expected to compare two sched_pset_search_order_sort_data_t pointers,
 * for the purpose of generating a pset search order.
 */
typedef cmpfunc_t sched_pset_search_order_sort_cmpfunc_t;

/*
 * sched_pset_search_order_compute()
 *
 * Generates a pset search order by sorting the per-pset search order datas
 * using the given comparator.
 */
void
sched_pset_search_order_compute(sched_pset_search_order_t *search_order_out,
    sched_pset_search_order_sort_data_t *datas, size_t num_datas,
    sched_pset_search_order_sort_cmpfunc_t cmp);

/*
 * sched_pset_search_order_init()
 *
 * Generates a search order of all psets sorted by increasing pset id, still
 * excluding the source pset.
 */
void
sched_pset_search_order_init(processor_set_t src_pset, sched_pset_search_order_t *search_order_out);

/*
 * sched_pset_iterate_state_t
 *
 * Used for tracking state across calls to sched_iterate_psets_ordered()
 * for the same search order traversal, and for returning the current pset_id.
 */
typedef struct {
	int spis_search_index;
	sched_pset_search_order_t spis_cached_search_order;
	int spis_pset_id; // out
} sched_pset_iterate_state_t;

#define SCHED_PSET_ITERATE_STATE_INIT ((sched_pset_iterate_state_t) { .spis_search_index = -1 })

/*
 * sched_iterate_psets_ordered()
 *
 * Routine to iterate through candidate psets based on a given search_order
 * and starting from starting_pset.
 * Returns true if iteration continues and another candidate pset was found,
 * which will be stored at istate->spis_pset_id. Returns false and
 * istate->spis_pset_id of -1 once iteration is complete. Iterate state should
 * start out initialized to SCHED_PSET_ITERATE_STATE_INIT.
 */
bool
sched_iterate_psets_ordered(processor_set_t starting_pset, sched_pset_search_order_t *search_order,
    uint64_t candidate_map, sched_pset_iterate_state_t *istate);

#endif /* __AMP__ */

#endif /* _KERN_SCHED_COMMON_H_ */