1*2540d485SJames Clark // SPDX-License-Identifier: GPL-2.0 2*2540d485SJames Clark #include <errno.h> 3*2540d485SJames Clark #include <limits.h> 4*2540d485SJames Clark #include <pthread.h> 5*2540d485SJames Clark #include <stdio.h> 6*2540d485SJames Clark #include <stdlib.h> 7*2540d485SJames Clark #include <string.h> 8*2540d485SJames Clark #include <linux/compiler.h> 9*2540d485SJames Clark #include "../tests.h" 10*2540d485SJames Clark 11*2540d485SJames Clark #define MAX_THREADS 25 12*2540d485SJames Clark 13*2540d485SJames Clark static int iterations = 500; 14*2540d485SJames Clark int named_threads_work = 1234; 15*2540d485SJames Clark 16*2540d485SJames Clark typedef void *(*thread_fn_t)(void *); 17*2540d485SJames Clark 18*2540d485SJames Clark #define DEFINE_THREAD(n) \ 19*2540d485SJames Clark noinline void *named_threads_thread##n(void *arg __maybe_unused) \ 20*2540d485SJames Clark { \ 21*2540d485SJames Clark pthread_setname_np(pthread_self(), "thread" #n); \ 22*2540d485SJames Clark for (int i = 0; i < iterations; i++) \ 23*2540d485SJames Clark named_threads_work += 3; \ 24*2540d485SJames Clark \ 25*2540d485SJames Clark return NULL; \ 26*2540d485SJames Clark } 27*2540d485SJames Clark 28*2540d485SJames Clark #define THREAD_LIST(macro) \ 29*2540d485SJames Clark macro(1) \ 30*2540d485SJames Clark macro(2) \ 31*2540d485SJames Clark macro(3) \ 32*2540d485SJames Clark macro(4) \ 33*2540d485SJames Clark macro(5) \ 34*2540d485SJames Clark macro(6) \ 35*2540d485SJames Clark macro(7) \ 36*2540d485SJames Clark macro(8) \ 37*2540d485SJames Clark macro(9) \ 38*2540d485SJames Clark macro(10) \ 39*2540d485SJames Clark macro(11) \ 40*2540d485SJames Clark macro(12) \ 41*2540d485SJames Clark macro(13) \ 42*2540d485SJames Clark macro(14) \ 43*2540d485SJames Clark macro(15) \ 44*2540d485SJames Clark macro(16) \ 45*2540d485SJames Clark macro(17) \ 46*2540d485SJames Clark macro(18) \ 47*2540d485SJames Clark macro(19) \ 48*2540d485SJames Clark macro(20) \ 49*2540d485SJames Clark macro(21) \ 50*2540d485SJames Clark macro(22) \ 51*2540d485SJames Clark macro(23) \ 52*2540d485SJames Clark macro(24) \ 53*2540d485SJames Clark macro(25) 54*2540d485SJames Clark 55*2540d485SJames Clark #define DECLARE_THREAD(n) void *named_threads_thread##n(void *arg); 56*2540d485SJames Clark 57*2540d485SJames Clark THREAD_LIST(DECLARE_THREAD) 58*2540d485SJames Clark THREAD_LIST(DEFINE_THREAD) 59*2540d485SJames Clark 60*2540d485SJames Clark #define THREAD_ENTRY(n) named_threads_thread##n, 61*2540d485SJames Clark 62*2540d485SJames Clark static thread_fn_t thread_fns[MAX_THREADS] = { 63*2540d485SJames Clark THREAD_LIST(THREAD_ENTRY) 64*2540d485SJames Clark }; 65*2540d485SJames Clark 66*2540d485SJames Clark /* 67*2540d485SJames Clark * Creates argv[0] threads that run a unique function named "thread[x]" which performs 68*2540d485SJames Clark * a multiplication in a loop for argv[1] loops. 69*2540d485SJames Clark */ 70*2540d485SJames Clark static int named_threads(int argc, const char **argv) 71*2540d485SJames Clark { 72*2540d485SJames Clark pthread_t threads[MAX_THREADS]; 73*2540d485SJames Clark int nr_threads = 1; 74*2540d485SJames Clark int err = 0; 75*2540d485SJames Clark 76*2540d485SJames Clark if (argc > 0) 77*2540d485SJames Clark nr_threads = atoi(argv[0]); 78*2540d485SJames Clark 79*2540d485SJames Clark if (nr_threads <= 0 || nr_threads > MAX_THREADS) { 80*2540d485SJames Clark fprintf(stderr, "Error: num threads must be 1 - %d\n", MAX_THREADS); 81*2540d485SJames Clark return 1; 82*2540d485SJames Clark } 83*2540d485SJames Clark 84*2540d485SJames Clark if (argc > 1) 85*2540d485SJames Clark iterations = atoi(argv[1]); 86*2540d485SJames Clark 87*2540d485SJames Clark if (iterations < 0) { 88*2540d485SJames Clark fprintf(stderr, "Error: iterations must be non-negative\n"); 89*2540d485SJames Clark return 1; 90*2540d485SJames Clark } 91*2540d485SJames Clark 92*2540d485SJames Clark for (int i = 0; i < nr_threads; i++) { 93*2540d485SJames Clark int ret; 94*2540d485SJames Clark 95*2540d485SJames Clark ret = pthread_create(&threads[i], NULL, thread_fns[i], NULL); 96*2540d485SJames Clark if (ret) { 97*2540d485SJames Clark fprintf(stderr, "Error: failed to create thread%d: %s\n", 98*2540d485SJames Clark i + 1, strerror(ret)); 99*2540d485SJames Clark return 1; 100*2540d485SJames Clark } 101*2540d485SJames Clark } 102*2540d485SJames Clark 103*2540d485SJames Clark for (int i = 0; i < nr_threads; i++) 104*2540d485SJames Clark pthread_join(threads[i], NULL); 105*2540d485SJames Clark 106*2540d485SJames Clark return err; 107*2540d485SJames Clark } 108*2540d485SJames Clark 109*2540d485SJames Clark DEFINE_WORKLOAD(named_threads); 110