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