1#include "sch/tests/test_internal.h"
2
3#define SCHED_PUSH_TEST_THREADS_MAX 1024
4
5static atomic_uint left = 0;
6static atomic_bool at_least_one_migrated = false;
7
8static 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
16TEST_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