xref: /linux/tools/perf/tests/workloads/thloop.c (revision 9e906a9dead17d81d6c2687f65e159231d0e3286)
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