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, 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