1 /* SPDX-License-Identifier: GPL-2.0 */
2 #include <pthread.h>
3 #include <stdlib.h>
4 #include <signal.h>
5 #include <unistd.h>
6 #include <linux/compiler.h>
7 #include "../tests.h"
8
9 static volatile sig_atomic_t done;
10
11 /* We want to check this symbol in perf report */
12 noinline void test_loop(void);
13
sighandler(int sig __maybe_unused)14 static void sighandler(int sig __maybe_unused)
15 {
16 done = 1;
17 }
18
test_loop(void)19 noinline void test_loop(void)
20 {
21 while (!done);
22 }
23
thfunc(void * arg)24 static void *thfunc(void *arg)
25 {
26 void (*loop_fn)(void) = arg;
27
28 loop_fn();
29 return NULL;
30 }
31
thloop(int argc,const char ** argv)32 static int thloop(int argc, const char **argv)
33 {
34 int nt = 2, sec = 1, err = 1;
35 pthread_t *thread_list = NULL;
36
37 if (argc > 0)
38 sec = atoi(argv[0]);
39
40 if (sec <= 0) {
41 fprintf(stderr, "Error: seconds (%d) must be >= 1\n", sec);
42 return 1;
43 }
44
45 if (argc > 1)
46 nt = atoi(argv[1]);
47
48 if (nt <= 0) {
49 fprintf(stderr, "Error: thread count (%d) must be >= 1\n", nt);
50 return 1;
51 }
52
53 signal(SIGINT, sighandler);
54 signal(SIGALRM, sighandler);
55
56 thread_list = calloc(nt, sizeof(pthread_t));
57 if (thread_list == NULL) {
58 fprintf(stderr, "Error: malloc failed for %d threads\n", nt);
59 goto out;
60 }
61 for (int i = 1; i < nt; i++) {
62 int ret = pthread_create(&thread_list[i], NULL, thfunc, test_loop);
63
64 if (ret) {
65 fprintf(stderr, "Error: failed to create thread %d\n", i);
66 done = 1; // Ensure started threads terminate.
67 goto out;
68 }
69 }
70 alarm(sec);
71 test_loop();
72 err = 0;
73 out:
74 for (int i = 1; i < nt; i++) {
75 if (thread_list && thread_list[i])
76 pthread_join(thread_list[i], /*retval=*/NULL);
77 }
78 free(thread_list);
79 return err;
80 }
81
82 DEFINE_WORKLOAD(thloop);
83