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