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