1// SPDX-License-Identifier: GPL-2.0
2// Carsten Haitzler <carsten.haitzler@arm.com>, 2021
3
4// define this for gettid()
5#define _GNU_SOURCE
6
7#include <stdio.h>
8#include <stdlib.h>
9#include <unistd.h>
10#include <string.h>
11#include <pthread.h>
12#include <sys/syscall.h>
13#ifndef SYS_gettid
14// gettid is 178 on arm64
15# define SYS_gettid 178
16#endif
17#define gettid() syscall(SYS_gettid)
18
19struct args {
20 unsigned int loops;
21 pthread_t th;
22 void *ret;
23};
24
25static void *thrfn(void *arg)
26{
27 struct args *a = arg;
28 int i = 0, len = a->loops;
29
30 if (getenv(name: "SHOW_TID")) {
31 unsigned long long tid = gettid();
32
33 printf(format: "%llu\n", tid);
34 }
35 asm volatile(
36 "loop:\n"
37 "add %w[i], %w[i], #1\n"
38 "cmp %w[i], %w[len]\n"
39 "blt loop\n"
40 : /* out */
41 : /* in */ [i] "r" (i), [len] "r" (len)
42 : /* clobber */
43 );
44 return (void *)(long)i;
45}
46
47static pthread_t new_thr(void *(*fn) (void *arg), void *arg)
48{
49 pthread_t t;
50 pthread_attr_t attr;
51
52 pthread_attr_init(attr: &attr);
53 pthread_create(newthread: &t, attr: &attr, start_routine: fn, arg: arg);
54 return t;
55}
56
57int main(int argc, char **argv)
58{
59 unsigned int i, len, thr;
60 struct args args[256];
61
62 if (argc < 3) {
63 printf(format: "ERR: %s [numthreads] [numloops (millions)]\n", argv[0]);
64 exit(status: 1);
65 }
66
67 thr = atoi(nptr: argv[1]);
68 if ((thr < 1) || (thr > 256)) {
69 printf(format: "ERR: threads 1-256\n");
70 exit(status: 1);
71 }
72 len = atoi(nptr: argv[2]);
73 if ((len < 1) || (len > 4000)) {
74 printf(format: "ERR: max loops 4000 (millions)\n");
75 exit(status: 1);
76 }
77 len *= 1000000;
78 for (i = 0; i < thr; i++) {
79 args[i].loops = len;
80 args[i].th = new_thr(fn: thrfn, arg: &(args[i]));
81 }
82 for (i = 0; i < thr; i++)
83 pthread_join(th: args[i].th, thread_return: &(args[i].ret));
84 return 0;
85}
86

source code of linux/tools/perf/tests/shell/coresight/thread_loop/thread_loop.c