1*043036a2SApple OSS Distributions // Copyright (c) 2023 Apple Inc. All rights reserved. 2*043036a2SApple OSS Distributions 3*043036a2SApple OSS Distributions #include <string.h> 4*043036a2SApple OSS Distributions 5*043036a2SApple OSS Distributions #include "sched_test_harness/sched_policy_darwintest.h" 6*043036a2SApple OSS Distributions #include "sched_test_harness/sched_clutch_harness.h" 7*043036a2SApple OSS Distributions 8*043036a2SApple OSS Distributions T_GLOBAL_META(T_META_NAMESPACE("xnu.scheduler"), 9*043036a2SApple OSS Distributions T_META_RADAR_COMPONENT_NAME("xnu"), 10*043036a2SApple OSS Distributions T_META_RADAR_COMPONENT_VERSION("scheduler"), 11*043036a2SApple OSS Distributions T_META_RUN_CONCURRENTLY(true), 12*043036a2SApple OSS Distributions T_META_OWNER("emily_peterson")); 13*043036a2SApple OSS Distributions 14*043036a2SApple OSS Distributions #define NUM_RAND_SEEDS 5 15*043036a2SApple OSS Distributions static unsigned int rand_seeds[NUM_RAND_SEEDS] = {377111, 2738572, 1717171, 4990221, 777777}; 16*043036a2SApple OSS Distributions 17*043036a2SApple OSS Distributions SCHED_POLICY_T_DECL(runq_processor_bound, 18*043036a2SApple OSS Distributions "Processor-bound threads vs. Regular threads") 19*043036a2SApple OSS Distributions { 20*043036a2SApple OSS Distributions int ret; 21*043036a2SApple OSS Distributions init_runqueue_harness(); 22*043036a2SApple OSS Distributions 23*043036a2SApple OSS Distributions struct thread_group *high_tg = create_tg(clutch_interactivity_score_max); 24*043036a2SApple OSS Distributions struct thread_group *low_tg = create_tg(0); 25*043036a2SApple OSS Distributions 26*043036a2SApple OSS Distributions test_thread_t lowest_bound = create_thread(TH_BUCKET_SHARE_BG, low_tg, root_bucket_to_highest_pri[TH_BUCKET_SHARE_BG]); 27*043036a2SApple OSS Distributions set_thread_processor_bound(lowest_bound, get_default_cpu()); 28*043036a2SApple OSS Distributions test_thread_t highest_bound = create_thread(TH_BUCKET_SHARE_IN, high_tg, root_bucket_to_highest_pri[TH_BUCKET_SHARE_IN]); 29*043036a2SApple OSS Distributions set_thread_processor_bound(highest_bound, get_default_cpu()); 30*043036a2SApple OSS Distributions test_thread_t lowest_unbound = create_thread(TH_BUCKET_SHARE_BG, low_tg, root_bucket_to_highest_pri[TH_BUCKET_SHARE_BG]); 31*043036a2SApple OSS Distributions test_thread_t highest_unbound = create_thread(TH_BUCKET_SHARE_IN, high_tg, root_bucket_to_highest_pri[TH_BUCKET_SHARE_IN]); 32*043036a2SApple OSS Distributions 33*043036a2SApple OSS Distributions for (int i = 0; i < NUM_RAND_SEEDS; i++) { 34*043036a2SApple OSS Distributions enqueue_threads_rand_order(default_target, rand_seeds[i], 4, lowest_bound, highest_bound, lowest_unbound, highest_unbound); 35*043036a2SApple OSS Distributions ret = dequeue_threads_expect_ordered(default_target, 4, highest_bound, highest_unbound, lowest_bound, lowest_unbound); 36*043036a2SApple OSS Distributions T_QUIET; T_EXPECT_EQ(ret, -1, "Processor-bound failed to win tie-break"); 37*043036a2SApple OSS Distributions T_QUIET; T_ASSERT_TRUE(runqueue_empty(default_target), "runqueue_empty"); 38*043036a2SApple OSS Distributions } 39*043036a2SApple OSS Distributions SCHED_POLICY_PASS("Processor-bound threads win priority tie-breaker"); 40*043036a2SApple OSS Distributions 41*043036a2SApple OSS Distributions test_thread_t bound = create_thread(TH_BUCKET_SHARE_DF, low_tg, root_bucket_to_highest_pri[TH_BUCKET_SHARE_DF] - 1); 42*043036a2SApple OSS Distributions set_thread_processor_bound(bound, get_default_cpu()); 43*043036a2SApple OSS Distributions test_thread_t higherpri_unbound = create_thread(TH_BUCKET_SHARE_DF, low_tg, root_bucket_to_highest_pri[TH_BUCKET_SHARE_DF]); 44*043036a2SApple OSS Distributions test_thread_t interactive_higherpri_unbound = create_thread(TH_BUCKET_SHARE_DF, high_tg, root_bucket_to_highest_pri[TH_BUCKET_SHARE_DF]); 45*043036a2SApple OSS Distributions test_thread_t interactive_lowerpri_unbound = create_thread(TH_BUCKET_SHARE_DF, high_tg, root_bucket_to_highest_pri[TH_BUCKET_SHARE_DF] - 2); 46*043036a2SApple OSS Distributions for (int i = 0; i < NUM_RAND_SEEDS; i++) { 47*043036a2SApple OSS Distributions enqueue_threads_rand_order(default_target, rand_seeds[i], 4, bound, higherpri_unbound, interactive_higherpri_unbound, interactive_lowerpri_unbound); 48*043036a2SApple OSS Distributions ret = dequeue_threads_expect_ordered(default_target, 4, interactive_higherpri_unbound, bound, interactive_lowerpri_unbound, higherpri_unbound); 49*043036a2SApple OSS Distributions T_QUIET; T_EXPECT_EQ(ret, -1, "Priority and Clutch interactivity score not factored correctly against processor-bound thread"); 50*043036a2SApple OSS Distributions T_QUIET; T_ASSERT_TRUE(runqueue_empty(default_target), "runqueue_empty"); 51*043036a2SApple OSS Distributions } 52*043036a2SApple OSS Distributions SCHED_POLICY_PASS("Clutch root represented against processor-bound threads by highest pri thread in the highest pri Clutch bucket"); 53*043036a2SApple OSS Distributions } 54*043036a2SApple OSS Distributions 55*043036a2SApple OSS Distributions SCHED_POLICY_T_DECL(runq_aboveui, 56*043036a2SApple OSS Distributions "Above UI vs. timeshare FG root buckets") 57*043036a2SApple OSS Distributions { 58*043036a2SApple OSS Distributions int ret; 59*043036a2SApple OSS Distributions init_runqueue_harness(); 60*043036a2SApple OSS Distributions 61*043036a2SApple OSS Distributions struct thread_group *same_tg = create_tg(clutch_interactivity_score_max); 62*043036a2SApple OSS Distributions test_thread_t aboveui = create_thread(TH_BUCKET_FIXPRI, same_tg, root_bucket_to_highest_pri[TH_BUCKET_FIXPRI]); 63*043036a2SApple OSS Distributions set_thread_sched_mode(aboveui, TH_MODE_FIXED); 64*043036a2SApple OSS Distributions test_thread_t low_fg = create_thread(TH_BUCKET_SHARE_FG, same_tg, root_bucket_to_highest_pri[TH_BUCKET_SHARE_FG]); 65*043036a2SApple OSS Distributions test_thread_t high_fg = create_thread(TH_BUCKET_SHARE_FG, same_tg, root_bucket_to_highest_pri[TH_BUCKET_FIXPRI] + 1); 66*043036a2SApple OSS Distributions 67*043036a2SApple OSS Distributions for (int i = 0; i < NUM_RAND_SEEDS; i++) { 68*043036a2SApple OSS Distributions enqueue_threads_rand_order(default_target, rand_seeds[i], 3, aboveui, low_fg, high_fg); 69*043036a2SApple OSS Distributions ret = dequeue_threads_expect_ordered(default_target, 3, high_fg, aboveui, low_fg); 70*043036a2SApple OSS Distributions T_QUIET; T_EXPECT_EQ(ret, -1, "Aboveui vs. foreground threads dequeued out of order"); 71*043036a2SApple OSS Distributions T_QUIET; T_ASSERT_TRUE(runqueue_empty(default_target), "runqueue_empty"); 72*043036a2SApple OSS Distributions } 73*043036a2SApple OSS Distributions SCHED_POLICY_PASS("Aboveui vs. foreground ordered according to priority"); 74*043036a2SApple OSS Distributions } 75*043036a2SApple OSS Distributions 76*043036a2SApple OSS Distributions SCHED_POLICY_T_DECL(runq_diff_root_bucket, 77*043036a2SApple OSS Distributions "Different root buckets (EDF, Starvation Avoidance Mode, and Warp)") 78*043036a2SApple OSS Distributions { 79*043036a2SApple OSS Distributions int ret; 80*043036a2SApple OSS Distributions init_runqueue_harness(); 81*043036a2SApple OSS Distributions 82*043036a2SApple OSS Distributions struct thread_group *same_tg = create_tg(0); 83*043036a2SApple OSS Distributions int num_threads = TH_BUCKET_SCHED_MAX - 1; 84*043036a2SApple OSS Distributions test_thread_t threads[num_threads]; 85*043036a2SApple OSS Distributions test_thread_t rev_threads[num_threads]; 86*043036a2SApple OSS Distributions test_thread_t warper_threads[num_threads]; 87*043036a2SApple OSS Distributions for (int bucket = TH_BUCKET_SHARE_FG; bucket < TH_BUCKET_SCHED_MAX; bucket++) { 88*043036a2SApple OSS Distributions threads[bucket - 1] = create_thread(bucket, same_tg, root_bucket_to_highest_pri[bucket]); 89*043036a2SApple OSS Distributions rev_threads[num_threads - bucket] = threads[bucket - 1]; 90*043036a2SApple OSS Distributions warper_threads[bucket - 1] = create_thread(bucket, same_tg, root_bucket_to_highest_pri[bucket]); 91*043036a2SApple OSS Distributions } 92*043036a2SApple OSS Distributions 93*043036a2SApple OSS Distributions /* Validate natural EDF between root buckets */ 94*043036a2SApple OSS Distributions for (int i = 0; i < NUM_RAND_SEEDS; i++) { 95*043036a2SApple OSS Distributions enqueue_threads_arr_rand_order(default_target, rand_seeds[i], num_threads, threads); 96*043036a2SApple OSS Distributions ret = dequeue_threads_expect_ordered_arr(default_target, num_threads, threads); 97*043036a2SApple OSS Distributions T_QUIET; T_EXPECT_EQ(ret, -1, "Root buckets dequeued out of EDF order, after the first %d threads dequeued were correct", ret); 98*043036a2SApple OSS Distributions T_QUIET; T_ASSERT_TRUE(runqueue_empty(default_target), "runqueue_empty"); 99*043036a2SApple OSS Distributions } 100*043036a2SApple OSS Distributions SCHED_POLICY_PASS("Basic EDF root bucket order respected"); 101*043036a2SApple OSS Distributions 102*043036a2SApple OSS Distributions /* Warp lets high root buckets win despite reverse ordering of root bucket deadlines */ 103*043036a2SApple OSS Distributions for (int bucket = TH_BUCKET_SHARE_BG; bucket >= TH_BUCKET_SHARE_FG; bucket--) { 104*043036a2SApple OSS Distributions if (bucket < TH_BUCKET_SHARE_BG) { 105*043036a2SApple OSS Distributions increment_mock_time_us(clutch_root_bucket_wcel_us[bucket + 1] - clutch_root_bucket_wcel_us[bucket] + 1); 106*043036a2SApple OSS Distributions } 107*043036a2SApple OSS Distributions enqueue_thread(default_target, warper_threads[bucket - 1]); 108*043036a2SApple OSS Distributions enqueue_thread(default_target, threads[bucket - 1]); 109*043036a2SApple OSS Distributions } 110*043036a2SApple OSS Distributions for (int bucket = TH_BUCKET_SHARE_FG; bucket < TH_BUCKET_SCHED_MAX; bucket++) { 111*043036a2SApple OSS Distributions ret = dequeue_thread_expect(default_target, warper_threads[bucket - 1]); 112*043036a2SApple OSS Distributions T_QUIET; T_EXPECT_TRUE(ret, "Root bucket %d failed to warp ahead", bucket); 113*043036a2SApple OSS Distributions increment_mock_time_us(clutch_root_bucket_warp_us[bucket] / 2); 114*043036a2SApple OSS Distributions ret = dequeue_thread_expect(default_target, threads[bucket - 1]); 115*043036a2SApple OSS Distributions T_QUIET; T_EXPECT_TRUE(ret, "Root bucket %d's warp window failed to stay open", bucket); 116*043036a2SApple OSS Distributions increment_mock_time_us(clutch_root_bucket_warp_us[bucket] / 2 + 1); 117*043036a2SApple OSS Distributions } 118*043036a2SApple OSS Distributions T_QUIET; T_ASSERT_TRUE(runqueue_empty(default_target), "runqueue_empty"); 119*043036a2SApple OSS Distributions SCHED_POLICY_PASS("Warping and Warp Windows respected"); 120*043036a2SApple OSS Distributions 121*043036a2SApple OSS Distributions /* After Warp is exhausted, Starvation Avoidance Mode kicks in to choose the buckets in EDF order */ 122*043036a2SApple OSS Distributions for (int bucket = TH_BUCKET_SHARE_BG; bucket >= TH_BUCKET_SHARE_FG; bucket--) { 123*043036a2SApple OSS Distributions if (bucket < TH_BUCKET_SHARE_BG) { 124*043036a2SApple OSS Distributions increment_mock_time_us(clutch_root_bucket_wcel_us[bucket + 1] - clutch_root_bucket_wcel_us[bucket] + 1); 125*043036a2SApple OSS Distributions } 126*043036a2SApple OSS Distributions enqueue_thread(default_target, threads[bucket - 1]); 127*043036a2SApple OSS Distributions } 128*043036a2SApple OSS Distributions ret = dequeue_threads_expect_ordered_arr(default_target, num_threads, rev_threads); 129*043036a2SApple OSS Distributions T_QUIET; T_EXPECT_EQ(ret, -1, "Starvation avoidance failed to kick in, after the first %d threads dequeued were correct", ret); 130*043036a2SApple OSS Distributions T_QUIET; T_ASSERT_TRUE(runqueue_empty(default_target), "runqueue_empty"); 131*043036a2SApple OSS Distributions SCHED_POLICY_PASS("Starvation Avoidance Mode respected"); 132*043036a2SApple OSS Distributions } 133*043036a2SApple OSS Distributions 134*043036a2SApple OSS Distributions SCHED_POLICY_T_DECL(runq_diff_clutch_bucket, 135*043036a2SApple OSS Distributions "Same root bucket, different TGs") 136*043036a2SApple OSS Distributions { 137*043036a2SApple OSS Distributions int ret; 138*043036a2SApple OSS Distributions init_runqueue_harness(); 139*043036a2SApple OSS Distributions 140*043036a2SApple OSS Distributions int num_tgs = clutch_interactivity_score_max + 1; 141*043036a2SApple OSS Distributions struct thread_group *tgs[num_tgs]; 142*043036a2SApple OSS Distributions for (int i = 0; i < num_tgs; i++) { 143*043036a2SApple OSS Distributions tgs[i] = create_tg(i); 144*043036a2SApple OSS Distributions } 145*043036a2SApple OSS Distributions 146*043036a2SApple OSS Distributions for (int bucket = TH_BUCKET_SHARE_FG; bucket < TH_BUCKET_SCHED_MAX; bucket++) { 147*043036a2SApple OSS Distributions test_thread_t threads[num_tgs]; 148*043036a2SApple OSS Distributions for (int i = 0; i < num_tgs; i++) { 149*043036a2SApple OSS Distributions threads[i] = create_thread(bucket, tgs[clutch_interactivity_score_max - i], root_bucket_to_highest_pri[bucket]); 150*043036a2SApple OSS Distributions } 151*043036a2SApple OSS Distributions 152*043036a2SApple OSS Distributions for (int i = 0; i < NUM_RAND_SEEDS; i++) { 153*043036a2SApple OSS Distributions enqueue_threads_arr_rand_order(default_target, rand_seeds[i], num_tgs, threads); 154*043036a2SApple OSS Distributions ret = dequeue_threads_expect_ordered_arr(default_target, num_tgs, threads); 155*043036a2SApple OSS Distributions T_QUIET; T_EXPECT_EQ(ret, -1, "Unique interactivity scores dequeued out-of-order, after the first %d threads dequeued were correct", ret); 156*043036a2SApple OSS Distributions T_QUIET; T_ASSERT_TRUE(runqueue_empty(default_target), "runqueue_empty"); 157*043036a2SApple OSS Distributions } 158*043036a2SApple OSS Distributions } 159*043036a2SApple OSS Distributions SCHED_POLICY_PASS("Interactivity scores between Clutch buckets respected"); 160*043036a2SApple OSS Distributions 161*043036a2SApple OSS Distributions struct thread_group *low_tg = create_tg(clutch_interactivity_score_max / 2); 162*043036a2SApple OSS Distributions struct thread_group *high_tg = create_tg((clutch_interactivity_score_max / 2) + 2); 163*043036a2SApple OSS Distributions for (int bucket = TH_BUCKET_SHARE_FG; bucket < TH_BUCKET_SCHED_MAX; bucket++) { 164*043036a2SApple OSS Distributions test_thread_t lowpri_but_interactive = create_thread(bucket, high_tg, root_bucket_to_highest_pri[bucket] - 1); 165*043036a2SApple OSS Distributions test_thread_t highpri = create_thread(bucket, low_tg, root_bucket_to_highest_pri[bucket]); 166*043036a2SApple OSS Distributions 167*043036a2SApple OSS Distributions for (int order = 0; order < 2; order++) { 168*043036a2SApple OSS Distributions enqueue_threads(default_target, 2, (order == 0 ? lowpri_but_interactive : highpri), (order == 0 ? highpri : lowpri_but_interactive)); 169*043036a2SApple OSS Distributions ret = dequeue_threads_expect_ordered(default_target, 2, lowpri_but_interactive, highpri); 170*043036a2SApple OSS Distributions T_QUIET; T_EXPECT_EQ(ret, -1, "Pri %d and i-score %d dequeued before pri %d and i-score %d, enqueue-order %d", root_bucket_to_highest_pri[bucket] - 1, (clutch_interactivity_score_max / 2) + 2, root_bucket_to_highest_pri[bucket], clutch_interactivity_score_max / 2, order); 171*043036a2SApple OSS Distributions } 172*043036a2SApple OSS Distributions 173*043036a2SApple OSS Distributions T_QUIET; T_ASSERT_TRUE(runqueue_empty(default_target), "runqueue_empty"); 174*043036a2SApple OSS Distributions } 175*043036a2SApple OSS Distributions SCHED_POLICY_PASS("Priority correctly combined with interactivity scores to order Clutch buckets"); 176*043036a2SApple OSS Distributions 177*043036a2SApple OSS Distributions struct thread_group *first_tg = create_tg(clutch_interactivity_score_max / 2); 178*043036a2SApple OSS Distributions struct thread_group *second_tg = create_tg(clutch_interactivity_score_max / 2); 179*043036a2SApple OSS Distributions for (int bucket = TH_BUCKET_SHARE_FG; bucket < TH_BUCKET_SCHED_MAX; bucket++) { 180*043036a2SApple OSS Distributions test_thread_t first = create_thread(bucket, first_tg, root_bucket_to_highest_pri[bucket]); 181*043036a2SApple OSS Distributions test_thread_t second = create_thread(bucket, second_tg, root_bucket_to_highest_pri[bucket]); 182*043036a2SApple OSS Distributions enqueue_threads(default_target, 2, first, second); 183*043036a2SApple OSS Distributions 184*043036a2SApple OSS Distributions ret = dequeue_threads_expect_ordered(default_target, 2, first, second); 185*043036a2SApple OSS Distributions T_QUIET; T_EXPECT_EQ(ret, -1, "FIFO order disrespected for threads in two Clutch buckets of equal priority"); 186*043036a2SApple OSS Distributions 187*043036a2SApple OSS Distributions T_QUIET; T_ASSERT_TRUE(runqueue_empty(default_target), "runqueue_empty"); 188*043036a2SApple OSS Distributions } 189*043036a2SApple OSS Distributions SCHED_POLICY_PASS("Clutch bucket FIFO order respected, for Clutch buckets with the same priority"); 190*043036a2SApple OSS Distributions } 191*043036a2SApple OSS Distributions 192*043036a2SApple OSS Distributions SCHED_POLICY_T_DECL(runq_diff_priority, 193*043036a2SApple OSS Distributions "Same root bucket, same TG, different priorities") 194*043036a2SApple OSS Distributions { 195*043036a2SApple OSS Distributions int ret; 196*043036a2SApple OSS Distributions init_runqueue_harness(); 197*043036a2SApple OSS Distributions 198*043036a2SApple OSS Distributions struct thread_group *same_tg = create_tg(0); 199*043036a2SApple OSS Distributions 200*043036a2SApple OSS Distributions for (int bucket = TH_BUCKET_SHARE_FG; bucket < TH_BUCKET_SCHED_MAX; bucket++) { 201*043036a2SApple OSS Distributions test_thread_t lowpri = create_thread(bucket, same_tg, root_bucket_to_highest_pri[bucket] - 1); 202*043036a2SApple OSS Distributions test_thread_t highpri = create_thread(bucket, same_tg, root_bucket_to_highest_pri[bucket]); 203*043036a2SApple OSS Distributions 204*043036a2SApple OSS Distributions for (int order = 0; order < 2; order++) { 205*043036a2SApple OSS Distributions enqueue_threads(default_target, 2, (order == 0 ? lowpri : highpri), (order == 0 ? highpri : lowpri)); 206*043036a2SApple OSS Distributions ret = dequeue_threads_expect_ordered(default_target, 2, highpri, lowpri); 207*043036a2SApple OSS Distributions T_QUIET; T_EXPECT_EQ(ret, -1, "Pri %d dequeued before pri %d, enqueue-order %d", root_bucket_to_highest_pri[bucket] - 1, root_bucket_to_highest_pri[bucket], order); 208*043036a2SApple OSS Distributions } 209*043036a2SApple OSS Distributions 210*043036a2SApple OSS Distributions T_QUIET; T_ASSERT_TRUE(runqueue_empty(default_target), "runqueue_empty"); 211*043036a2SApple OSS Distributions } 212*043036a2SApple OSS Distributions SCHED_POLICY_PASS("sched_pri order respected, for threads in the same Clutch bucket"); 213*043036a2SApple OSS Distributions 214*043036a2SApple OSS Distributions for (int bucket = TH_BUCKET_SHARE_FG; bucket < TH_BUCKET_SCHED_MAX; bucket++) { 215*043036a2SApple OSS Distributions int num_threads = 10; 216*043036a2SApple OSS Distributions test_thread_t threads[num_threads]; 217*043036a2SApple OSS Distributions for (int i = 0; i < num_threads; i++) { 218*043036a2SApple OSS Distributions threads[i] = create_thread(bucket, same_tg, root_bucket_to_highest_pri[bucket]); 219*043036a2SApple OSS Distributions increment_mock_time_us(5); 220*043036a2SApple OSS Distributions enqueue_thread(default_target, threads[i]); 221*043036a2SApple OSS Distributions } 222*043036a2SApple OSS Distributions ret = dequeue_threads_expect_ordered_arr(default_target, num_threads, threads); 223*043036a2SApple OSS Distributions T_QUIET; T_EXPECT_EQ(ret, -1, "FIFO order disrespected for %d threads at pri %d", num_threads, root_bucket_to_highest_pri[bucket]); 224*043036a2SApple OSS Distributions T_QUIET; T_ASSERT_TRUE(runqueue_empty(default_target), "runqueue_empty"); 225*043036a2SApple OSS Distributions } 226*043036a2SApple OSS Distributions SCHED_POLICY_PASS("Thread FIFO order respected, for threads in the same Clutch bucket with the same sched_pri"); 227*043036a2SApple OSS Distributions } 228*043036a2SApple OSS Distributions 229*043036a2SApple OSS Distributions /* 230*043036a2SApple OSS Distributions * 64 bits of fourth argument to CLUTCH_THREAD_SELECT expected to 231*043036a2SApple OSS Distributions * match the following layout, ordered from most to least significant bit: 232*043036a2SApple OSS Distributions * 233*043036a2SApple OSS Distributions * (reserved 23) (selection_opened_starvation_avoidance_window 1) 234*043036a2SApple OSS Distributions * | (starvation_avoidance_window_close 12) | (selection_was_edf 1) 235*043036a2SApple OSS Distributions * | | | | (traverse mode 3) 236*043036a2SApple OSS Distributions * v v v v v 237*043036a2SApple OSS Distributions * r----------------------wc----------sc----------wsbec-----t--v--- 238*043036a2SApple OSS Distributions * ^ ^ ^ ^ ^ 239*043036a2SApple OSS Distributions * | | | | (version 4) 240*043036a2SApple OSS Distributions * (warp_window_close 12) | | (cluster_id 6) 241*043036a2SApple OSS Distributions * | (selection_was_cluster_bound 1) 242*043036a2SApple OSS Distributions * (selection_opened_warp_window 1) 243*043036a2SApple OSS Distributions */ 244*043036a2SApple OSS Distributions #define CTS_VERSION 1ULL 245*043036a2SApple OSS Distributions #define TRAVERSE_MODE_REMOVE_CONSIDER_CURRENT (1ULL << 4) 246*043036a2SApple OSS Distributions #define TRAVERSE_MODE_CHECK_PREEMPT (2ULL << 4) 247*043036a2SApple OSS Distributions #define CLUSTER_ID(id) (id << 7) 248*043036a2SApple OSS Distributions #define SELECTION_WAS_EDF (1ULL << 13) 249*043036a2SApple OSS Distributions #define SELECTION_WAS_CLUSTER_BOUND (1ULL << 14) 250*043036a2SApple OSS Distributions #define SELECTION_OPENED_STARVATION_AVOIDANCE_WINDOW (1ULL << 15) | SELECTION_WAS_EDF 251*043036a2SApple OSS Distributions #define SELECTION_OPENED_WARP_WINDOW (1ULL << 16) 252*043036a2SApple OSS Distributions #define WINDOW_MASK(bucket, cluster_bound) ( 1ULL << (bucket + cluster_bound * TH_BUCKET_SCHED_MAX) ) 253*043036a2SApple OSS Distributions #define STARVATION_AVOIDANCE_WINDOW_CLOSE(bucket, cluster_bound) (WINDOW_MASK(bucket, cluster_bound) << 17) 254*043036a2SApple OSS Distributions #define WARP_WINDOW_CLOSE(bucket, cluster_bound) (WINDOW_MASK(bucket, cluster_bound) << 29) 255*043036a2SApple OSS Distributions 256*043036a2SApple OSS Distributions /* 257*043036a2SApple OSS Distributions * We test the selection_was_cluster_bound bit and cluster_id field gated 258*043036a2SApple OSS Distributions * on the Edge version of this test case. 259*043036a2SApple OSS Distributions */ 260*043036a2SApple OSS Distributions 261*043036a2SApple OSS Distributions SCHED_POLICY_T_DECL(runq_tracepoint_thread_select, 262*043036a2SApple OSS Distributions "Validate emitted MACH_SCHED_CLUTCH_THREAD_SELECT tracepoints") 263*043036a2SApple OSS Distributions { 264*043036a2SApple OSS Distributions int ret; 265*043036a2SApple OSS Distributions uint64_t root_bucket_arg; 266*043036a2SApple OSS Distributions uint64_t bucket_is_bound = false; 267*043036a2SApple OSS Distributions #if CONFIG_SCHED_EDGE 268*043036a2SApple OSS Distributions init_migration_harness(basic_amp); 269*043036a2SApple OSS Distributions bucket_is_bound = true; 270*043036a2SApple OSS Distributions #else /* !CONFIG_SCHED_EDGE */ 271*043036a2SApple OSS Distributions init_runqueue_harness(); 272*043036a2SApple OSS Distributions #endif /* CONFIG_SCHED_EDGE */ 273*043036a2SApple OSS Distributions disable_auto_current_thread(); 274*043036a2SApple OSS Distributions 275*043036a2SApple OSS Distributions struct thread_group *same_tg = create_tg(0); 276*043036a2SApple OSS Distributions int num_threads = TH_BUCKET_SCHED_MAX - 1; 277*043036a2SApple OSS Distributions test_thread_t threads[num_threads]; 278*043036a2SApple OSS Distributions test_thread_t rev_threads[num_threads]; 279*043036a2SApple OSS Distributions test_thread_t warper_threads[num_threads]; 280*043036a2SApple OSS Distributions for (int bucket = TH_BUCKET_SHARE_FG; bucket < TH_BUCKET_SCHED_MAX; bucket++) { 281*043036a2SApple OSS Distributions threads[bucket - 1] = create_thread(bucket, same_tg, root_bucket_to_highest_pri[bucket]); 282*043036a2SApple OSS Distributions rev_threads[num_threads - bucket] = threads[bucket - 1]; 283*043036a2SApple OSS Distributions warper_threads[bucket - 1] = create_thread(bucket, same_tg, root_bucket_to_highest_pri[bucket]); 284*043036a2SApple OSS Distributions #if CONFIG_SCHED_EDGE 285*043036a2SApple OSS Distributions set_thread_cluster_bound(threads[bucket - 1], 0); 286*043036a2SApple OSS Distributions set_thread_cluster_bound(warper_threads[bucket - 1], 0); 287*043036a2SApple OSS Distributions #endif /* CONFIG_SCHED_EDGE */ 288*043036a2SApple OSS Distributions } 289*043036a2SApple OSS Distributions 290*043036a2SApple OSS Distributions /* Natural EDF */ 291*043036a2SApple OSS Distributions enqueue_threads_arr(default_target, num_threads, threads); 292*043036a2SApple OSS Distributions for (int bucket = TH_BUCKET_SHARE_FG; bucket < TH_BUCKET_SCHED_MAX; bucket++) { 293*043036a2SApple OSS Distributions ret = dequeue_thread_expect(default_target, threads[bucket - 1]); 294*043036a2SApple OSS Distributions T_QUIET; T_EXPECT_TRUE(ret, "Root bucket %d failed to warp ahead", bucket); 295*043036a2SApple OSS Distributions root_bucket_arg = SELECTION_WAS_EDF | CTS_VERSION; 296*043036a2SApple OSS Distributions #if CONFIG_SCHED_EDGE 297*043036a2SApple OSS Distributions root_bucket_arg |= SELECTION_WAS_CLUSTER_BOUND; 298*043036a2SApple OSS Distributions #endif /* CONFIG_SCHED_EDGE */ 299*043036a2SApple OSS Distributions ret = tracepoint_expect(CLUTCH_THREAD_SELECT, (bucket - 1) * 2, 0, bucket, root_bucket_arg); 300*043036a2SApple OSS Distributions T_QUIET; T_EXPECT_TRUE(ret, "EDF CLUTCH_THREAD_SELECT tracepoint"); 301*043036a2SApple OSS Distributions } 302*043036a2SApple OSS Distributions T_QUIET; T_ASSERT_EQ(runqueue_empty(default_target), true, "runqueue_empty"); 303*043036a2SApple OSS Distributions SCHED_POLICY_PASS("Correct CLUTCH_THREAD_SELECT tracepoint info for EDF selections"); 304*043036a2SApple OSS Distributions 305*043036a2SApple OSS Distributions /* Warp windows */ 306*043036a2SApple OSS Distributions for (int bucket = TH_BUCKET_SHARE_BG; bucket >= TH_BUCKET_SHARE_FG; bucket--) { 307*043036a2SApple OSS Distributions if (bucket < TH_BUCKET_SHARE_BG) { 308*043036a2SApple OSS Distributions increment_mock_time_us(clutch_root_bucket_wcel_us[bucket + 1] - clutch_root_bucket_wcel_us[bucket] + 1); 309*043036a2SApple OSS Distributions } 310*043036a2SApple OSS Distributions enqueue_thread(default_target, warper_threads[bucket - 1]); 311*043036a2SApple OSS Distributions enqueue_thread(default_target, threads[bucket - 1]); 312*043036a2SApple OSS Distributions } 313*043036a2SApple OSS Distributions for (int bucket = TH_BUCKET_SHARE_FG; bucket < TH_BUCKET_SCHED_MAX; bucket++) { 314*043036a2SApple OSS Distributions /* Opens a new warp window */ 315*043036a2SApple OSS Distributions ret = dequeue_thread_expect(default_target, warper_threads[bucket - 1]); 316*043036a2SApple OSS Distributions T_QUIET; T_EXPECT_TRUE(ret, "Root bucket %d failed to warp ahead", bucket); 317*043036a2SApple OSS Distributions root_bucket_arg = (bucket < TH_BUCKET_SHARE_BG ? SELECTION_OPENED_WARP_WINDOW : SELECTION_WAS_EDF) | CTS_VERSION; 318*043036a2SApple OSS Distributions #if CONFIG_SCHED_EDGE 319*043036a2SApple OSS Distributions root_bucket_arg |= SELECTION_WAS_CLUSTER_BOUND; 320*043036a2SApple OSS Distributions #endif /* CONFIG_SCHED_EDGE */ 321*043036a2SApple OSS Distributions ret = tracepoint_expect(CLUTCH_THREAD_SELECT, bucket * 2 - 1, 0, bucket, root_bucket_arg); 322*043036a2SApple OSS Distributions T_QUIET; T_EXPECT_TRUE(ret, "Open warp window CLUTCH_THREAD_SELECT tracepoint"); 323*043036a2SApple OSS Distributions 324*043036a2SApple OSS Distributions /* Makes use of the opened warp window */ 325*043036a2SApple OSS Distributions increment_mock_time_us(clutch_root_bucket_warp_us[bucket] / 2); 326*043036a2SApple OSS Distributions ret = dequeue_thread_expect(default_target, threads[bucket - 1]); 327*043036a2SApple OSS Distributions T_QUIET; T_EXPECT_TRUE(ret, "Root bucket %d's warp window failed to stay open", bucket); 328*043036a2SApple OSS Distributions root_bucket_arg = (bucket < TH_BUCKET_SHARE_BG ? 0 : SELECTION_WAS_EDF) | CTS_VERSION; 329*043036a2SApple OSS Distributions #if CONFIG_SCHED_EDGE 330*043036a2SApple OSS Distributions root_bucket_arg |= SELECTION_WAS_CLUSTER_BOUND; 331*043036a2SApple OSS Distributions #endif /* CONFIG_SCHED_EDGE */ 332*043036a2SApple OSS Distributions ret = tracepoint_expect(CLUTCH_THREAD_SELECT, bucket * 2 - 2, 0, bucket, root_bucket_arg); 333*043036a2SApple OSS Distributions T_QUIET; T_EXPECT_TRUE(ret, "Active warp window CLUTCH_THREAD_SELECT tracepoint"); 334*043036a2SApple OSS Distributions 335*043036a2SApple OSS Distributions increment_mock_time_us(clutch_root_bucket_warp_us[bucket] / 2 + 1); 336*043036a2SApple OSS Distributions } 337*043036a2SApple OSS Distributions T_QUIET; T_ASSERT_TRUE(runqueue_empty(default_target), "runqueue_empty"); 338*043036a2SApple OSS Distributions SCHED_POLICY_PASS("Correct CLUTCH_THREAD_SELECT tracepoint info for warp windows"); 339*043036a2SApple OSS Distributions 340*043036a2SApple OSS Distributions /* Starvation avoidance windows */ 341*043036a2SApple OSS Distributions for (int bucket = TH_BUCKET_SHARE_BG; bucket >= TH_BUCKET_SHARE_FG; bucket--) { 342*043036a2SApple OSS Distributions if (bucket < TH_BUCKET_SHARE_BG) { 343*043036a2SApple OSS Distributions increment_mock_time_us(clutch_root_bucket_wcel_us[bucket + 1] - clutch_root_bucket_wcel_us[bucket] + 1); 344*043036a2SApple OSS Distributions } 345*043036a2SApple OSS Distributions enqueue_thread(default_target, threads[bucket - 1]); 346*043036a2SApple OSS Distributions } 347*043036a2SApple OSS Distributions for (int bucket = TH_BUCKET_SHARE_BG; bucket >= TH_BUCKET_SHARE_FG; bucket--) { 348*043036a2SApple OSS Distributions ret = dequeue_thread_expect(default_target, threads[bucket - 1]); 349*043036a2SApple OSS Distributions T_QUIET; T_EXPECT_TRUE(ret, "Starvation avoidance failed to kick in for bucket %d", bucket); 350*043036a2SApple OSS Distributions root_bucket_arg = SELECTION_WAS_EDF | CTS_VERSION; 351*043036a2SApple OSS Distributions #if CONFIG_SCHED_EDGE 352*043036a2SApple OSS Distributions root_bucket_arg |= SELECTION_WAS_CLUSTER_BOUND; 353*043036a2SApple OSS Distributions #endif /* CONFIG_SCHED_EDGE */ 354*043036a2SApple OSS Distributions if (bucket == TH_BUCKET_SHARE_BG) { 355*043036a2SApple OSS Distributions /* Enough time has passed for the warp windows opened in the last phase to be closed in one go */ 356*043036a2SApple OSS Distributions for (int warping_bucket = TH_BUCKET_SHARE_FG; warping_bucket < TH_BUCKET_SHARE_BG; warping_bucket++) { 357*043036a2SApple OSS Distributions root_bucket_arg |= WARP_WINDOW_CLOSE(warping_bucket, bucket_is_bound); 358*043036a2SApple OSS Distributions } 359*043036a2SApple OSS Distributions } 360*043036a2SApple OSS Distributions if (bucket > TH_BUCKET_SHARE_FG) { 361*043036a2SApple OSS Distributions root_bucket_arg |= SELECTION_OPENED_STARVATION_AVOIDANCE_WINDOW; 362*043036a2SApple OSS Distributions } 363*043036a2SApple OSS Distributions ret = tracepoint_expect(CLUTCH_THREAD_SELECT, (bucket - 1) * 2, 0, bucket, root_bucket_arg); 364*043036a2SApple OSS Distributions T_QUIET; T_EXPECT_TRUE(ret, "Open starvation avoidance window CLUTCH_THREAD_SELECT tracepoint"); 365*043036a2SApple OSS Distributions } 366*043036a2SApple OSS Distributions increment_mock_time_us(clutch_root_bucket_wcel_us[TH_BUCKET_SHARE_BG]); 367*043036a2SApple OSS Distributions for (int bucket = TH_BUCKET_SHARE_FG; bucket < TH_BUCKET_SCHED_MAX; bucket++) { 368*043036a2SApple OSS Distributions enqueue_thread(default_target, threads[bucket - 1]); 369*043036a2SApple OSS Distributions } 370*043036a2SApple OSS Distributions for (int bucket = TH_BUCKET_SHARE_FG; bucket < TH_BUCKET_SCHED_MAX; bucket++) { 371*043036a2SApple OSS Distributions ret = dequeue_thread_expect(default_target, threads[bucket - 1]); 372*043036a2SApple OSS Distributions T_QUIET; T_EXPECT_TRUE(ret, "EDF dequeue for bucket %d", bucket); 373*043036a2SApple OSS Distributions root_bucket_arg = SELECTION_WAS_EDF | CTS_VERSION; 374*043036a2SApple OSS Distributions #if CONFIG_SCHED_EDGE 375*043036a2SApple OSS Distributions root_bucket_arg |= SELECTION_WAS_CLUSTER_BOUND; 376*043036a2SApple OSS Distributions #endif /* CONFIG_SCHED_EDGE */ 377*043036a2SApple OSS Distributions if (bucket == TH_BUCKET_SHARE_FG) { 378*043036a2SApple OSS Distributions /* Enough time has passed for the starvation avoidance windows opened in the last phase to be closed in one go */ 379*043036a2SApple OSS Distributions for (int starved_bucket = TH_BUCKET_SHARE_BG; starved_bucket > TH_BUCKET_SHARE_FG; starved_bucket--) { 380*043036a2SApple OSS Distributions root_bucket_arg |= STARVATION_AVOIDANCE_WINDOW_CLOSE(starved_bucket, bucket_is_bound); 381*043036a2SApple OSS Distributions } 382*043036a2SApple OSS Distributions } 383*043036a2SApple OSS Distributions ret = tracepoint_expect(CLUTCH_THREAD_SELECT, (bucket - 1) * 2, 0, bucket, root_bucket_arg); 384*043036a2SApple OSS Distributions T_QUIET; T_EXPECT_TRUE(ret, "Closing starvation avoidance window or EDF CLUTCH_THREAD_SELECT tracepoint"); 385*043036a2SApple OSS Distributions } 386*043036a2SApple OSS Distributions T_QUIET; T_ASSERT_TRUE(runqueue_empty(default_target), "runqueue_empty"); 387*043036a2SApple OSS Distributions SCHED_POLICY_PASS("Correct CLUTCH_THREAD_SELECT tracepoint info for starvation avoidance windows"); 388*043036a2SApple OSS Distributions 389*043036a2SApple OSS Distributions /* Different runq traverse modes */ 390*043036a2SApple OSS Distributions cpu_set_thread_current(get_default_cpu(), threads[0]); 391*043036a2SApple OSS Distributions enqueue_thread(default_target, threads[1]); 392*043036a2SApple OSS Distributions ret = cpu_dequeue_thread_expect_compare_current(get_default_cpu(), threads[0]); 393*043036a2SApple OSS Distributions T_QUIET; T_EXPECT_TRUE(ret, "EDF dequeue current thread for bucket"); 394*043036a2SApple OSS Distributions root_bucket_arg = TRAVERSE_MODE_REMOVE_CONSIDER_CURRENT | SELECTION_WAS_EDF | CTS_VERSION; 395*043036a2SApple OSS Distributions #if CONFIG_SCHED_EDGE 396*043036a2SApple OSS Distributions root_bucket_arg |= SELECTION_WAS_CLUSTER_BOUND; 397*043036a2SApple OSS Distributions #endif /* CONFIG_SCHED_EDGE */ 398*043036a2SApple OSS Distributions ret = tracepoint_expect(CLUTCH_THREAD_SELECT, 0, 0, TH_BUCKET_SHARE_FG, root_bucket_arg); 399*043036a2SApple OSS Distributions T_QUIET; T_EXPECT_TRUE(ret, "Current thread EDF CLUTCH_THREAD_SELECT tracepoint"); 400*043036a2SApple OSS Distributions ret = cpu_check_preempt_current(get_default_cpu(), false); 401*043036a2SApple OSS Distributions T_QUIET; T_EXPECT_TRUE(ret, "Current thread check preempt"); 402*043036a2SApple OSS Distributions root_bucket_arg = TRAVERSE_MODE_CHECK_PREEMPT | SELECTION_WAS_EDF | CTS_VERSION; 403*043036a2SApple OSS Distributions #if CONFIG_SCHED_EDGE 404*043036a2SApple OSS Distributions root_bucket_arg |= SELECTION_WAS_CLUSTER_BOUND; 405*043036a2SApple OSS Distributions #endif /* CONFIG_SCHED_EDGE */ 406*043036a2SApple OSS Distributions ret = tracepoint_expect(CLUTCH_THREAD_SELECT, 0, 0, TH_BUCKET_SHARE_FG, root_bucket_arg); 407*043036a2SApple OSS Distributions T_QUIET; T_EXPECT_TRUE(ret, "Current thread check preempt CLUTCH_THREAD_SELECT tracepoint"); 408*043036a2SApple OSS Distributions SCHED_POLICY_PASS("Correct CLUTCH_THREAD_SELECT tracepoint info for current thread (traverse modes)"); 409*043036a2SApple OSS Distributions #if CONFIG_SCHED_EDGE 410*043036a2SApple OSS Distributions /* Test the cluster_id field */ 411*043036a2SApple OSS Distributions test_thread_t bound_thread = create_thread(TH_BUCKET_SHARE_DF, same_tg, root_bucket_to_highest_pri[TH_BUCKET_SHARE_DF]); 412*043036a2SApple OSS Distributions set_thread_cluster_bound(bound_thread, 1); 413*043036a2SApple OSS Distributions enqueue_thread(pset_target(1), bound_thread); 414*043036a2SApple OSS Distributions ret = dequeue_thread_expect(pset_target(1), bound_thread); 415*043036a2SApple OSS Distributions T_QUIET; T_ASSERT_TRUE(ret, "Dequeue single thread on cluster 1"); 416*043036a2SApple OSS Distributions root_bucket_arg = SELECTION_WAS_EDF | CTS_VERSION | SELECTION_WAS_CLUSTER_BOUND | CLUSTER_ID(1); 417*043036a2SApple OSS Distributions ret = tracepoint_expect(CLUTCH_THREAD_SELECT, 10, 0, TH_BUCKET_SHARE_DF, root_bucket_arg); 418*043036a2SApple OSS Distributions T_QUIET; T_EXPECT_TRUE(ret, "Cluster-bound CLUTCH_THREAD_SELECT tracepoint"); 419*043036a2SApple OSS Distributions SCHED_POLICY_PASS("CLUTCH_THREAD_SELECT tracepoint handles non-zero cluster id"); 420*043036a2SApple OSS Distributions #endif /* CONFIG_SCHED_EDGE */ 421*043036a2SApple OSS Distributions } 422*043036a2SApple OSS Distributions 423*043036a2SApple OSS Distributions SCHED_POLICY_T_DECL(runq_root_bucket_expired_windows, 424*043036a2SApple OSS Distributions "Root bucket warp and starvation avoidance windows should expire at the right time") 425*043036a2SApple OSS Distributions { 426*043036a2SApple OSS Distributions int ret; 427*043036a2SApple OSS Distributions uint64_t root_bucket_arg; 428*043036a2SApple OSS Distributions init_runqueue_harness(); 429*043036a2SApple OSS Distributions disable_auto_current_thread(); 430*043036a2SApple OSS Distributions 431*043036a2SApple OSS Distributions struct thread_group *same_tg = create_tg(0); 432*043036a2SApple OSS Distributions test_thread_t def_thread = create_thread(TH_BUCKET_SHARE_DF, same_tg, root_bucket_to_highest_pri[TH_BUCKET_SHARE_DF]); 433*043036a2SApple OSS Distributions test_thread_t in_thread = create_thread(TH_BUCKET_SHARE_IN, same_tg, root_bucket_to_highest_pri[TH_BUCKET_SHARE_IN]); 434*043036a2SApple OSS Distributions 435*043036a2SApple OSS Distributions /* Expect user_initiated bucket to warp ahread of starved default bucket */ 436*043036a2SApple OSS Distributions enqueue_thread(default_target, def_thread); 437*043036a2SApple OSS Distributions increment_mock_time_us(clutch_root_bucket_wcel_us[TH_BUCKET_SHARE_DF] + 1); 438*043036a2SApple OSS Distributions enqueue_thread(default_target, in_thread); 439*043036a2SApple OSS Distributions ret = dequeue_thread_expect(default_target, in_thread); 440*043036a2SApple OSS Distributions T_QUIET; T_EXPECT_TRUE(ret, "unexpected bucket"); 441*043036a2SApple OSS Distributions root_bucket_arg = SELECTION_OPENED_WARP_WINDOW | CTS_VERSION; 442*043036a2SApple OSS Distributions ret = tracepoint_expect(CLUTCH_THREAD_SELECT, 1, 0, TH_BUCKET_SHARE_IN, root_bucket_arg); 443*043036a2SApple OSS Distributions T_EXPECT_TRUE(ret, "IN warped ahead, tracepoint"); 444*043036a2SApple OSS Distributions 445*043036a2SApple OSS Distributions /* Expect warp window to close and default starvation avoidance window to begin */ 446*043036a2SApple OSS Distributions enqueue_thread(default_target, in_thread); 447*043036a2SApple OSS Distributions increment_mock_time_us(clutch_root_bucket_warp_us[TH_BUCKET_SHARE_IN] + 1); 448*043036a2SApple OSS Distributions ret = dequeue_thread_expect(default_target, def_thread); 449*043036a2SApple OSS Distributions T_QUIET; T_EXPECT_TRUE(ret, "unexpected bucket"); 450*043036a2SApple OSS Distributions root_bucket_arg = WARP_WINDOW_CLOSE(TH_BUCKET_SHARE_IN, false) | SELECTION_OPENED_STARVATION_AVOIDANCE_WINDOW | CTS_VERSION; 451*043036a2SApple OSS Distributions ret = tracepoint_expect(CLUTCH_THREAD_SELECT, 0, 0, TH_BUCKET_SHARE_DF, root_bucket_arg); 452*043036a2SApple OSS Distributions T_EXPECT_TRUE(ret, "IN closed warp and DEF opened starvation avoidance, tracepoint"); 453*043036a2SApple OSS Distributions 454*043036a2SApple OSS Distributions /* Expect default starvation avoidance window to close and refresh warp for user_initiated with natural EDF */ 455*043036a2SApple OSS Distributions enqueue_thread(default_target, def_thread); 456*043036a2SApple OSS Distributions increment_mock_time_us(clutch_root_bucket_wcel_us[TH_BUCKET_SHARE_DF] + 1); 457*043036a2SApple OSS Distributions ret = dequeue_thread_expect(default_target, in_thread); 458*043036a2SApple OSS Distributions T_QUIET; T_EXPECT_TRUE(ret, "unexpected bucket"); 459*043036a2SApple OSS Distributions root_bucket_arg = STARVATION_AVOIDANCE_WINDOW_CLOSE(TH_BUCKET_SHARE_DF, false) | SELECTION_WAS_EDF | CTS_VERSION; 460*043036a2SApple OSS Distributions ret = tracepoint_expect(CLUTCH_THREAD_SELECT, 1, 0, TH_BUCKET_SHARE_IN, root_bucket_arg); 461*043036a2SApple OSS Distributions T_EXPECT_TRUE(ret, "DEF closed starvation avoidance window and IN refreshed warp, tracepoint"); 462*043036a2SApple OSS Distributions 463*043036a2SApple OSS Distributions /* Expect foreground to warp ahead of starved default bucket */ 464*043036a2SApple OSS Distributions increment_mock_time_us(clutch_root_bucket_wcel_us[TH_BUCKET_SHARE_DF] + 1); 465*043036a2SApple OSS Distributions test_thread_t fg_thread = create_thread(TH_BUCKET_SHARE_FG, same_tg, root_bucket_to_highest_pri[TH_BUCKET_SHARE_FG]); 466*043036a2SApple OSS Distributions enqueue_thread(default_target, fg_thread); 467*043036a2SApple OSS Distributions ret = dequeue_thread_expect(default_target, fg_thread); 468*043036a2SApple OSS Distributions T_QUIET; T_EXPECT_TRUE(ret, "unexpected bucket"); 469*043036a2SApple OSS Distributions root_bucket_arg = SELECTION_OPENED_WARP_WINDOW | CTS_VERSION; 470*043036a2SApple OSS Distributions ret = tracepoint_expect(CLUTCH_THREAD_SELECT, 2, 0, TH_BUCKET_SHARE_FG, root_bucket_arg); 471*043036a2SApple OSS Distributions T_EXPECT_TRUE(ret, "FG opened warp window, tracepoint"); 472*043036a2SApple OSS Distributions 473*043036a2SApple OSS Distributions /* Expect foreground to close warp window and default to open starvation avoidance window */ 474*043036a2SApple OSS Distributions increment_mock_time_us(clutch_root_bucket_warp_us[TH_BUCKET_SHARE_FG] + 1); 475*043036a2SApple OSS Distributions enqueue_thread(default_target, fg_thread); 476*043036a2SApple OSS Distributions ret = dequeue_thread_expect(default_target, def_thread); 477*043036a2SApple OSS Distributions T_QUIET; T_EXPECT_TRUE(ret, "unexpected bucket"); 478*043036a2SApple OSS Distributions root_bucket_arg = WARP_WINDOW_CLOSE(TH_BUCKET_SHARE_FG, false) | SELECTION_OPENED_STARVATION_AVOIDANCE_WINDOW | CTS_VERSION; 479*043036a2SApple OSS Distributions ret = tracepoint_expect(CLUTCH_THREAD_SELECT, 0, 0, TH_BUCKET_SHARE_DF, root_bucket_arg); 480*043036a2SApple OSS Distributions T_EXPECT_TRUE(ret, "FG closed warp window and DEF opened starvation avoidance window, tracepoint"); 481*043036a2SApple OSS Distributions 482*043036a2SApple OSS Distributions /* Expect default to close starvation avoidance window */ 483*043036a2SApple OSS Distributions increment_mock_time_us(clutch_root_bucket_wcel_us[TH_BUCKET_SHARE_DF] + 1); 484*043036a2SApple OSS Distributions enqueue_thread(default_target, def_thread); 485*043036a2SApple OSS Distributions ret = dequeue_thread_expect(default_target, fg_thread); 486*043036a2SApple OSS Distributions T_QUIET; T_EXPECT_TRUE(ret, "unexpected bucket"); 487*043036a2SApple OSS Distributions root_bucket_arg = STARVATION_AVOIDANCE_WINDOW_CLOSE(TH_BUCKET_SHARE_DF, false) | SELECTION_WAS_EDF | CTS_VERSION; 488*043036a2SApple OSS Distributions ret = tracepoint_expect(CLUTCH_THREAD_SELECT, 2, 0, TH_BUCKET_SHARE_FG, root_bucket_arg); 489*043036a2SApple OSS Distributions T_EXPECT_TRUE(ret, "DEF closed starvation avoidance window and FG refreshed warp, tracepoint"); 490*043036a2SApple OSS Distributions 491*043036a2SApple OSS Distributions /* 492*043036a2SApple OSS Distributions * Expect user_initiated to experience a full-length warp window 493*043036a2SApple OSS Distributions * (none spent on expired default starvation avoidance window rdar://120562509) 494*043036a2SApple OSS Distributions */ 495*043036a2SApple OSS Distributions increment_mock_time_us(clutch_root_bucket_wcel_us[TH_BUCKET_SHARE_DF] + 1); 496*043036a2SApple OSS Distributions enqueue_thread(default_target, in_thread); 497*043036a2SApple OSS Distributions ret = dequeue_thread_expect(default_target, in_thread); 498*043036a2SApple OSS Distributions T_QUIET; T_EXPECT_TRUE(ret, "unexpected bucket"); 499*043036a2SApple OSS Distributions root_bucket_arg = SELECTION_OPENED_WARP_WINDOW | CTS_VERSION; 500*043036a2SApple OSS Distributions ret = tracepoint_expect(CLUTCH_THREAD_SELECT, 1, 0, TH_BUCKET_SHARE_IN, root_bucket_arg); 501*043036a2SApple OSS Distributions T_EXPECT_TRUE(ret, "IN opened warp window, tracepoint"); 502*043036a2SApple OSS Distributions enqueue_thread(default_target, in_thread); 503*043036a2SApple OSS Distributions increment_mock_time_us(clutch_root_bucket_warp_us[TH_BUCKET_SHARE_IN] - 1); 504*043036a2SApple OSS Distributions ret = dequeue_thread_expect(default_target, in_thread); 505*043036a2SApple OSS Distributions T_QUIET; T_EXPECT_TRUE(ret, "unexpected bucket"); 506*043036a2SApple OSS Distributions root_bucket_arg = CTS_VERSION; 507*043036a2SApple OSS Distributions ret = tracepoint_expect(CLUTCH_THREAD_SELECT, 1, 0, TH_BUCKET_SHARE_IN, root_bucket_arg); 508*043036a2SApple OSS Distributions T_EXPECT_TRUE(ret, "IN had full-length warp window, tracepoint"); 509*043036a2SApple OSS Distributions 510*043036a2SApple OSS Distributions SCHED_POLICY_PASS("Correct warp/starvation avoidance window expiration"); 511*043036a2SApple OSS Distributions } 512*043036a2SApple OSS Distributions 513*043036a2SApple OSS Distributions SCHED_POLICY_T_DECL(runq_interactivity_starts_maxed, 514*043036a2SApple OSS Distributions "A new Clutch bucket group should start with max interactivity score") 515*043036a2SApple OSS Distributions { 516*043036a2SApple OSS Distributions int ret; 517*043036a2SApple OSS Distributions init_runqueue_harness(); 518*043036a2SApple OSS Distributions 519*043036a2SApple OSS Distributions struct thread_group *non_interactive_tg = create_tg(clutch_interactivity_score_max - 1); 520*043036a2SApple OSS Distributions test_thread_t non_interactive_tg_thread = create_thread(TH_BUCKET_SHARE_DF, non_interactive_tg, root_bucket_to_highest_pri[TH_BUCKET_SHARE_DF]); 521*043036a2SApple OSS Distributions enqueue_thread(default_target, non_interactive_tg_thread); 522*043036a2SApple OSS Distributions 523*043036a2SApple OSS Distributions struct thread_group *new_tg = create_tg(INITIAL_INTERACTIVITY_SCORE); 524*043036a2SApple OSS Distributions test_thread_t new_tg_thread = create_thread(TH_BUCKET_SHARE_DF, new_tg, root_bucket_to_highest_pri[TH_BUCKET_SHARE_DF]); 525*043036a2SApple OSS Distributions enqueue_thread(default_target, new_tg_thread); 526*043036a2SApple OSS Distributions 527*043036a2SApple OSS Distributions ret = dequeue_thread_expect(default_target, new_tg_thread); 528*043036a2SApple OSS Distributions T_EXPECT_TRUE(ret, "New TG Clutch bucket is interactive"); 529*043036a2SApple OSS Distributions 530*043036a2SApple OSS Distributions ret = dequeue_thread_expect(default_target, non_interactive_tg_thread); 531*043036a2SApple OSS Distributions T_EXPECT_TRUE(ret, "Non-interactive thread comes second"); 532*043036a2SApple OSS Distributions 533*043036a2SApple OSS Distributions SCHED_POLICY_PASS("Interactivity score initialized correctly"); 534*043036a2SApple OSS Distributions } 535