xref: /linux/tools/perf/tests/workloads/thloop.c (revision 473f6c8f437b049f8ec015d57cd59bb983b1d85c)
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 
14 static void sighandler(int sig __maybe_unused)
15 {
16 	done = 1;
17 }
18 
19 noinline void test_loop(void)
20 {
21 	while (!done);
22 }
23 
24 static void *thfunc(void *arg)
25 {
26 	void (*loop_fn)(void) = arg;
27 
28 	loop_fn();
29 	return NULL;
30 }
31 
32 static int thloop(int argc, const char **argv)
33 {
34 	int nt = 2, err = 1;
35 	double sec = 1.0;
36 	pthread_t *thread_list = NULL;
37 
38 	if (argc > 0)
39 		sec = atof(argv[0]);
40 
41 	if (!(sec > 0.0)) {
42 		fprintf(stderr, "Error: seconds (%f) must be > 0\n", sec);
43 		return 1;
44 	}
45 
46 	if (argc > 1)
47 		nt = atoi(argv[1]);
48 
49 	if (nt <= 0) {
50 		fprintf(stderr, "Error: thread count (%d) must be >= 1\n", nt);
51 		return 1;
52 	}
53 
54 	signal(SIGINT, sighandler);
55 	signal(SIGALRM, sighandler);
56 
57 	thread_list = calloc(nt, sizeof(pthread_t));
58 	if (thread_list == NULL) {
59 		fprintf(stderr, "Error: malloc failed for %d threads\n", nt);
60 		goto out;
61 	}
62 	for (int i = 1; i < nt; i++) {
63 		int ret = pthread_create(&thread_list[i], NULL, thfunc, test_loop);
64 
65 		if (ret) {
66 			fprintf(stderr, "Error: failed to create thread %d\n", i);
67 			done = 1; // Ensure started threads terminate.
68 			goto out;
69 		}
70 	}
71 	if (sec < 1.0) {
72 		useconds_t usecs = (useconds_t)(sec * 1000000.0);
73 
74 		ualarm(usecs > 0 ? usecs : 1, 0);
75 	} else
76 		alarm((unsigned int)sec);
77 	test_loop();
78 	err = 0;
79 out:
80 	for (int i = 1; i < nt; i++) {
81 		if (thread_list && thread_list[i])
82 			pthread_join(thread_list[i], /*retval=*/NULL);
83 	}
84 	free(thread_list);
85 	return err;
86 }
87 
88 DEFINE_WORKLOAD(thloop);
89