| // SPDX-License-Identifier: GPL-2.0 |
| // Carsten Haitzler <carsten.haitzler@arm.com>, 2021 |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <unistd.h> |
| #include <string.h> |
| #include <pthread.h> |
| |
| struct args { |
| pthread_t th; |
| unsigned int in; |
| void *ret; |
| }; |
| |
| static void *thrfn(void *arg) |
| { |
| struct args *a = arg; |
| unsigned int i, in = a->in; |
| |
| for (i = 0; i < 10000; i++) { |
| asm volatile ( |
| // force an unroll of thia add instruction so we can test long runs of code |
| #define SNIP1 "add %[in], %[in], #1\n" |
| // 10 |
| #define SNIP2 SNIP1 SNIP1 SNIP1 SNIP1 SNIP1 SNIP1 SNIP1 SNIP1 SNIP1 SNIP1 |
| // 100 |
| #define SNIP3 SNIP2 SNIP2 SNIP2 SNIP2 SNIP2 SNIP2 SNIP2 SNIP2 SNIP2 SNIP2 |
| // 1000 |
| #define SNIP4 SNIP3 SNIP3 SNIP3 SNIP3 SNIP3 SNIP3 SNIP3 SNIP3 SNIP3 SNIP3 |
| // 10000 |
| #define SNIP5 SNIP4 SNIP4 SNIP4 SNIP4 SNIP4 SNIP4 SNIP4 SNIP4 SNIP4 SNIP4 |
| // 100000 |
| SNIP5 SNIP5 SNIP5 SNIP5 SNIP5 SNIP5 SNIP5 SNIP5 SNIP5 SNIP5 |
| : /* out */ |
| : /* in */ [in] "r" (in) |
| : /* clobber */ |
| ); |
| } |
| } |
| |
| static pthread_t new_thr(void *(*fn) (void *arg), void *arg) |
| { |
| pthread_t t; |
| pthread_attr_t attr; |
| |
| pthread_attr_init(&attr); |
| pthread_create(&t, &attr, fn, arg); |
| return t; |
| } |
| |
| int main(int argc, char **argv) |
| { |
| unsigned int i, thr; |
| pthread_t threads[256]; |
| struct args args[256]; |
| |
| if (argc < 2) { |
| printf("ERR: %s [numthreads]\n", argv[0]); |
| exit(1); |
| } |
| |
| thr = atoi(argv[1]); |
| if ((thr > 256) || (thr < 1)) { |
| printf("ERR: threads 1-256\n"); |
| exit(1); |
| } |
| for (i = 0; i < thr; i++) { |
| args[i].in = rand(); |
| args[i].th = new_thr(thrfn, &(args[i])); |
| } |
| for (i = 0; i < thr; i++) |
| pthread_join(args[i].th, &(args[i].ret)); |
| return 0; |
| } |