projects/linux·blob master · refs

88 lines · 1.7 KiB

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
9static volatile sig_atomic_t done;
10
11/* We want to check this symbol in perf report */
12noinline void test_loop(void);
13
14static void sighandler(int sig __maybe_unused)
15{
16 done = 1;
17}
18
19noinline void test_loop(void)
20{
21 while (!done);
22}
23
24static void *thfunc(void *arg)
25{
26 void (*loop_fn)(void) = arg;
27
28 loop_fn();
29 return NULL;
30}
31
32static 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;
79out:
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
88DEFINE_WORKLOAD(thloop);