1*e3723e1fSApple OSS Distributions // Copyright (c) 2024 Apple Inc. All rights reserved. 2*e3723e1fSApple OSS Distributions #ifndef XNU_SCHED_TEST_UTILS_H 3*e3723e1fSApple OSS Distributions #define XNU_SCHED_TEST_UTILS_H 4*e3723e1fSApple OSS Distributions 5*e3723e1fSApple OSS Distributions #include <stdbool.h> 6*e3723e1fSApple OSS Distributions 7*e3723e1fSApple OSS Distributions /* -- Meta-controls -- */ 8*e3723e1fSApple OSS Distributions 9*e3723e1fSApple OSS Distributions /* Verbose printing mode is enabled by default */ 10*e3723e1fSApple OSS Distributions void disable_verbose_sched_utils(void); 11*e3723e1fSApple OSS Distributions void reenable_verbose_sched_utils(void); 12*e3723e1fSApple OSS Distributions 13*e3723e1fSApple OSS Distributions /* -- Time conversions -- */ 14*e3723e1fSApple OSS Distributions uint64_t nanos_to_abs(uint64_t nanos); 15*e3723e1fSApple OSS Distributions uint64_t abs_to_nanos(uint64_t abs); 16*e3723e1fSApple OSS Distributions 17*e3723e1fSApple OSS Distributions /* -- Thread orchestration -- */ 18*e3723e1fSApple OSS Distributions void spin_for_duration(uint32_t seconds); 19*e3723e1fSApple OSS Distributions void stop_spinning_threads(void); 20*e3723e1fSApple OSS Distributions 21*e3723e1fSApple OSS Distributions /* 22*e3723e1fSApple OSS Distributions * Cluster-binding interfaces perform a soft bind on the current 23*e3723e1fSApple OSS Distributions * thread and require "enable_skstb=1" boot-arg to be set. 24*e3723e1fSApple OSS Distributions */ 25*e3723e1fSApple OSS Distributions 26*e3723e1fSApple OSS Distributions /* Returns the old bound type ('0' for unbound) */ 27*e3723e1fSApple OSS Distributions char bind_to_cluster_of_type(char type); 28*e3723e1fSApple OSS Distributions /* Returns the old bound id (-1 for unbound) */ 29*e3723e1fSApple OSS Distributions int bind_to_cluster_id(int cluster_id); 30*e3723e1fSApple OSS Distributions 31*e3723e1fSApple OSS Distributions /* 32*e3723e1fSApple OSS Distributions * Functions to create pthreads, optionally configured with 33*e3723e1fSApple OSS Distributions * a number of pthread attributes: 34*e3723e1fSApple OSS Distributions */ 35*e3723e1fSApple OSS Distributions void create_thread_pri(pthread_t *thread_handle, int priority, void *(*func)(void *), void *arg); 36*e3723e1fSApple OSS Distributions typedef enum { 37*e3723e1fSApple OSS Distributions eDetached, 38*e3723e1fSApple OSS Distributions eJoinable, // default 39*e3723e1fSApple OSS Distributions } detach_state_t; 40*e3723e1fSApple OSS Distributions typedef enum { 41*e3723e1fSApple OSS Distributions eSchedFIFO = 4, 42*e3723e1fSApple OSS Distributions eSchedRR = 2, 43*e3723e1fSApple OSS Distributions eSchedOther = 1, 44*e3723e1fSApple OSS Distributions eSchedDefault = 0, // default 45*e3723e1fSApple OSS Distributions } sched_policy_t; 46*e3723e1fSApple OSS Distributions #define DEFAULT_STACK_SIZE 0 47*e3723e1fSApple OSS Distributions // Default qos_class is QOS_CLASS_UNSPECIFIED 48*e3723e1fSApple OSS Distributions pthread_attr_t * 49*e3723e1fSApple OSS Distributions create_pthread_attr(int priority, 50*e3723e1fSApple OSS Distributions detach_state_t detach_state, qos_class_t qos_class, 51*e3723e1fSApple OSS Distributions sched_policy_t sched_policy, size_t stack_size); 52*e3723e1fSApple OSS Distributions void create_thread(pthread_t *thread_handle, pthread_attr_t *attr, void *(*func)(void *), void *arg); 53*e3723e1fSApple OSS Distributions pthread_t *create_threads(int num_threads, int priority, 54*e3723e1fSApple OSS Distributions detach_state_t detach_state, qos_class_t qos_class, 55*e3723e1fSApple OSS Distributions sched_policy_t sched_policy, size_t stack_size, 56*e3723e1fSApple OSS Distributions void *(*func)(void *), void *arg_array[]); 57*e3723e1fSApple OSS Distributions 58*e3723e1fSApple OSS Distributions /* -- ️ Platform checks -- */ 59*e3723e1fSApple OSS Distributions bool platform_is_amp(void); 60*e3723e1fSApple OSS Distributions bool platform_is_virtual_machine(void); 61*e3723e1fSApple OSS Distributions char *platform_sched_policy(void); 62*e3723e1fSApple OSS Distributions unsigned int platform_num_clusters(void); 63*e3723e1fSApple OSS Distributions const char *platform_perflevel_name(unsigned int perflevel); 64*e3723e1fSApple OSS Distributions unsigned int platform_nperflevels(void); 65*e3723e1fSApple OSS Distributions 66*e3723e1fSApple OSS Distributions /* -- Monitor system performance state -- */ 67*e3723e1fSApple OSS Distributions 68*e3723e1fSApple OSS Distributions /* 69*e3723e1fSApple OSS Distributions * Returns true if the system successfully quiesced below the specified threshold 70*e3723e1fSApple OSS Distributions * within the specified timeout, and false otherwise. 71*e3723e1fSApple OSS Distributions * idle_threshold is given as a ratio between [0.0, 1.0], defaulting to 0.9. 72*e3723e1fSApple OSS Distributions * Passing argument --no-quiesce disables waiting for quiescence. 73*e3723e1fSApple OSS Distributions */ 74*e3723e1fSApple OSS Distributions bool wait_for_quiescence(int argc, char *const argv[], double idle_threshold, int timeout_seconds); 75*e3723e1fSApple OSS Distributions bool wait_for_quiescence_default(int argc, char *const argv[]); 76*e3723e1fSApple OSS Distributions 77*e3723e1fSApple OSS Distributions /* Returns true if all cores on the device are recommended */ 78*e3723e1fSApple OSS Distributions bool check_recommended_core_mask(uint64_t *core_mask); 79*e3723e1fSApple OSS Distributions 80*e3723e1fSApple OSS Distributions /* -- ️ Query/control CPU topology -- */ 81*e3723e1fSApple OSS Distributions 82*e3723e1fSApple OSS Distributions /* 83*e3723e1fSApple OSS Distributions * Spawns and waits for clpcctrl with the given arguments. 84*e3723e1fSApple OSS Distributions * If read_value is true, returns the value assumed to be elicited from clpcctrl. 85*e3723e1fSApple OSS Distributions */ 86*e3723e1fSApple OSS Distributions uint64_t execute_clpcctrl(char *clpcctrl_args[], bool read_value); 87*e3723e1fSApple OSS Distributions 88*e3723e1fSApple OSS Distributions /* -- ️ Record traces -- */ 89*e3723e1fSApple OSS Distributions 90*e3723e1fSApple OSS Distributions /* 91*e3723e1fSApple OSS Distributions * Tracing requires root privilege. 92*e3723e1fSApple OSS Distributions * 93*e3723e1fSApple OSS Distributions * Standard usage of this interface would be to call begin_collect_trace() 94*e3723e1fSApple OSS Distributions * followed by end_collect_trace() and allow the library to automatically 95*e3723e1fSApple OSS Distributions * handle saving/discarding the collected trace upon test end. Traces will 96*e3723e1fSApple OSS Distributions * automatically be saved if a failure occurred during the test run and 97*e3723e1fSApple OSS Distributions * discarded otherwise. 98*e3723e1fSApple OSS Distributions */ 99*e3723e1fSApple OSS Distributions 100*e3723e1fSApple OSS Distributions typedef void *trace_handle_t; 101*e3723e1fSApple OSS Distributions 102*e3723e1fSApple OSS Distributions /* 103*e3723e1fSApple OSS Distributions * Begins trace collection, using the specified name as a prefix for all 104*e3723e1fSApple OSS Distributions * generated filenames. Arguments are parsed to check for --no-trace or 105*e3723e1fSApple OSS Distributions * --save-trace options, which disable tracing and enable unconditional 106*e3723e1fSApple OSS Distributions * saving of the trace file respectively. 107*e3723e1fSApple OSS Distributions * 108*e3723e1fSApple OSS Distributions * NOTE: Since scheduler tracing can generate large trace files when left to 109*e3723e1fSApple OSS Distributions * run for long durations, take care to begin tracing close to the start of 110*e3723e1fSApple OSS Distributions * the period of interest. 111*e3723e1fSApple OSS Distributions */ 112*e3723e1fSApple OSS Distributions trace_handle_t begin_collect_trace(int argc, char *const argv[], char *filename); 113*e3723e1fSApple OSS Distributions trace_handle_t begin_collect_trace_fmt(int argc, char *const argv[], char *filename_fmt, ...); 114*e3723e1fSApple OSS Distributions 115*e3723e1fSApple OSS Distributions /* 116*e3723e1fSApple OSS Distributions * NOTE: It's possible that tests may induce CPU starvation that can 117*e3723e1fSApple OSS Distributions * prevent the trace from ending or cause post-processing to take an extra 118*e3723e1fSApple OSS Distributions * long time. This can be avoided by terminating or blocking spawned test 119*e3723e1fSApple OSS Distributions * threads before calling end_collect_trace(). 120*e3723e1fSApple OSS Distributions */ 121*e3723e1fSApple OSS Distributions void end_collect_trace(trace_handle_t handle); 122*e3723e1fSApple OSS Distributions 123*e3723e1fSApple OSS Distributions /* 124*e3723e1fSApple OSS Distributions * Saves the recorded trace file to a tarball and marks the tarball for 125*e3723e1fSApple OSS Distributions * upload in BATS as a debugging artifact. 126*e3723e1fSApple OSS Distributions */ 127*e3723e1fSApple OSS Distributions void save_collected_trace(trace_handle_t handle); 128*e3723e1fSApple OSS Distributions 129*e3723e1fSApple OSS Distributions /* Deletes the recorded trace */ 130*e3723e1fSApple OSS Distributions void discard_collected_trace(trace_handle_t handle); 131*e3723e1fSApple OSS Distributions 132*e3723e1fSApple OSS Distributions #endif /* XNU_SCHED_TEST_UTILS_H */ 133