| 1 | #include "sch/tests/test_internal.h" |
| 2 | |
| 3 | #define SCHED_PUSH_TEST_THREADS_MAX 1024 |
| 4 | |
| 5 | static atomic_uint32_t left = 0; |
| 6 | static atomic_bool at_least_one_migrated = false; |
| 7 | |
| 8 | static void sched_push_try(void *arg) { |
| 9 | cc_ignore(arg); |
| 10 | while (smp_id(cond: TOPC_NONE) == 0 && !atomic_load(&at_least_one_migrated)) |
| 11 | scheduler_yield(); |
| 12 | |
| 13 | atomic_dec(&left); |
| 14 | atomic_store(&at_least_one_migrated, true); |
| 15 | } |
| 16 | |
| 17 | TEST_DEFINE_INTEGRATION(sched, push_target, TEST_INTENSITY(32, 256, 1024), |
| 18 | .min_cores = 2) { |
| 19 | test_info("This test takes a bit. uncomment me to run it" ); |
| 20 | return TEST_SKIP(TEST_SKIP_NONE); |
| 21 | |
| 22 | size_t count = ctx->intensity_val ? ctx->intensity_val : 256; |
| 23 | if (count > SCHED_PUSH_TEST_THREADS_MAX) |
| 24 | count = SCHED_PUSH_TEST_THREADS_MAX; |
| 25 | |
| 26 | atomic_store(&left, (unsigned) count); |
| 27 | atomic_store(&at_least_one_migrated, false); |
| 28 | |
| 29 | struct thread **pushed = vnews(pushed, count, ALLOC_ZERO); |
| 30 | TEST_ASSERT_NONNULL(pushed); |
| 31 | |
| 32 | enum irql irql = irql_raise(new_level: IRQL_DISPATCH_LEVEL); |
| 33 | for (size_t i = 0; i < count; i++) { |
| 34 | pushed[i] = thread_spawn(("push_test_%zu" , i), sched_push_try, |
| 35 | .on_cpu = 0, .joinable = true); |
| 36 | } |
| 37 | irql_lower(old_level: irql); |
| 38 | |
| 39 | for (size_t i = 0; i < count; i++) { |
| 40 | if (pushed[i]) { |
| 41 | thread_join(t: pushed[i]); |
| 42 | } |
| 43 | } |
| 44 | |
| 45 | TEST_ASSERT_EQ(atomic_load(&left), 0); |
| 46 | |
| 47 | vfree(pushed); |
| 48 | return TEST_SUCCESS; |
| 49 | } |
| 50 | |