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