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("SHOW_TID")) { 31 unsigned long long tid = gettid(); 32 33 printf("%llu\n", tid); 34 } 35 asm volatile( 36 "loop:\n" 37 "add %[i], %[i], #1\n" 38 "cmp %[i], %[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); 53 pthread_create(&t, &attr, fn, 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("ERR: %s [numthreads] [numloops (millions)]\n", argv[0]); 64 exit(1); 65 } 66 67 thr = atoi(argv[1]); 68 if ((thr < 1) || (thr > 256)) { 69 printf("ERR: threads 1-256\n"); 70 exit(1); 71 } 72 len = atoi(argv[2]); 73 if ((len < 1) || (len > 4000)) { 74 printf("ERR: max loops 4000 (millions)\n"); 75 exit(1); 76 } 77 len *= 1000000; 78 for (i = 0; i < thr; i++) { 79 args[i].loops = len; 80 args[i].th = new_thr(thrfn, &(args[i])); 81 } 82 for (i = 0; i < thr; i++) 83 pthread_join(args[i].th, &(args[i].ret)); 84 return 0; 85} 86