1#include <nightmare_test.h>
2
3/* ---------- Worker Thread ---------- */
4
5NIGHTMARE_THREAD_ENTRY(thread_spawn_smoke_worker) {
6 NIGHTMARE_THREAD_ENTRY_INIT();
7 struct nightmare_thread *nth = nightmare_get_thread();
8 atomic_uint *counter = (atomic_uint *) nth->local.data;
9
10 /* Do a little chaos to exercise scheduler */
11 nightmare_chaos_pause();
12
13 /* Mark that this thread ran */
14 atomic_fetch_add(counter, 1);
15
16 NIGHTMARE_PROGRESS();
17 NIGHTMARE_THREAD_ENTRY_EXIT();
18}
19
20/* ---------- Reset / Init ---------- */
21
22NIGHTMARE_IMPL_RESET(thread_spawn_smoke) {
23 NIGHTMARE_FN_INIT();
24 /* Nothing to clean up (for now) */
25}
26
27NIGHTMARE_IMPL_INIT(thread_spawn_smoke) {
28 NIGHTMARE_FN_INIT();
29 /* nothing special to set up */
30}
31
32/* ---------- Start / Stop ---------- */
33
34NIGHTMARE_IMPL_START(thread_spawn_smoke) {
35 const size_t nthreads = SELF->default_threads;
36
37 atomic_uint *counter = kmalloc(sizeof(*counter));
38 *counter = 0;
39
40 /* share through thread-local */
41 nightmare_set_local(d: counter, l: sizeof(*counter));
42
43 /* Add a single role: N worker threads */
44 nightmare_add_role(t: SELF, type: NIGHTMARE_ROLE_GENERIC, name: "spawn_smoke_worker",
45 worker: thread_spawn_smoke_worker, count: nthreads, arg: counter);
46
47 /* Spawn threads */
48 struct nightmare_thread_group grp;
49 nightmare_spawn_roles(SELF, &grp);
50
51 /* Wait until every worker has incremented once */
52 time_t timeout = SELF->default_runtime_ms;
53
54 while (atomic_load(counter) < nthreads) {
55 NIGHTMARE_PROGRESS();
56
57 if (nightmare_watchdog_expired(w: SELF->watchdog, timeout_ms: timeout))
58 NIGHTMARE_RETURN_ERROR(NIGHTMARE_ERR_FAIL);
59
60 scheduler_yield();
61 }
62
63 /* Join worker threads */
64 nightmare_join_roles(&grp);
65
66 NIGHTMARE_RETURN_ERROR(NIGHTMARE_ERR_OK);
67}
68
69NIGHTMARE_IMPL_STOP(thread_spawn_smoke) {
70 NIGHTMARE_FN_INIT();
71 /* Graceful stop not needed, workers already exit */
72}
73
74NIGHTMARE_IMPL_SHUTDOWN(thread_spawn_smoke) {
75 NIGHTMARE_FN_INIT();
76 /* Forced stop not needed */
77}
78
79/* ---------- Report ---------- */
80
81NIGHTMARE_IMPL_REPORT(thread_spawn_smoke) {
82 NIGHTMARE_FN_INIT();
83 REPORT->write_fn(REPORT, "thread_spawn_smoke: all threads ran\n", 38);
84}
85
86/* ---------- Register Test ---------- */
87
88NIGHTMARE_DEFINE_TEST(thread_spawn_smoke, 2000, /* 2 seconds */
89 5000); /* spawn 5000 threads */
90