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