1// SPDX-License-Identifier: GPL-2.0
2// Carsten Haitzler <carsten.haitzler@arm.com>, 2021
3#include <stdio.h>
4#include <stdlib.h>
5#include <unistd.h>
6#include <string.h>
7#include <pthread.h>
8
9struct args {
10	pthread_t th;
11	unsigned int in;
12	void *ret;
13};
14
15static void *thrfn(void *arg)
16{
17	struct args *a = arg;
18	unsigned int i, in = a->in;
19
20	for (i = 0; i < 10000; i++) {
21		asm volatile (
22// force an unroll of thia add instruction so we can test long runs of code
23#define SNIP1 "add %[in], %[in], #1\n"
24// 10
25#define SNIP2 SNIP1 SNIP1 SNIP1 SNIP1 SNIP1 SNIP1 SNIP1 SNIP1 SNIP1 SNIP1
26// 100
27#define SNIP3 SNIP2 SNIP2 SNIP2 SNIP2 SNIP2 SNIP2 SNIP2 SNIP2 SNIP2 SNIP2
28// 1000
29#define SNIP4 SNIP3 SNIP3 SNIP3 SNIP3 SNIP3 SNIP3 SNIP3 SNIP3 SNIP3 SNIP3
30// 10000
31#define SNIP5 SNIP4 SNIP4 SNIP4 SNIP4 SNIP4 SNIP4 SNIP4 SNIP4 SNIP4 SNIP4
32// 100000
33			SNIP5 SNIP5 SNIP5 SNIP5 SNIP5 SNIP5 SNIP5 SNIP5 SNIP5 SNIP5
34			: /* out */
35			: /* in */ [in] "r" (in)
36			: /* clobber */
37		);
38	}
39}
40
41static pthread_t new_thr(void *(*fn) (void *arg), void *arg)
42{
43	pthread_t t;
44	pthread_attr_t attr;
45
46	pthread_attr_init(&attr);
47	pthread_create(&t, &attr, fn, arg);
48	return t;
49}
50
51int main(int argc, char **argv)
52{
53	unsigned int i, thr;
54	struct args args[256];
55
56	if (argc < 2) {
57		printf("ERR: %s [numthreads]\n", argv[0]);
58		exit(1);
59	}
60
61	thr = atoi(argv[1]);
62	if ((thr > 256) || (thr < 1)) {
63		printf("ERR: threads 1-256\n");
64		exit(1);
65	}
66	for (i = 0; i < thr; i++) {
67		args[i].in = rand();
68		args[i].th = new_thr(thrfn, &(args[i]));
69	}
70	for (i = 0; i < thr; i++)
71		pthread_join(args[i].th, &(args[i].ret));
72	return 0;
73}
74