xref: /linux/tools/perf/tests/workloads/leafloop.c (revision 637315cb400eed1dbe721954fea437a61a2d65b2)
1 /* SPDX-License-Identifier: GPL-2.0 */
2 #include <signal.h>
3 #include <stdlib.h>
4 #include <linux/compiler.h>
5 #include <unistd.h>
6 #include "../tests.h"
7 
8 /* We want to check these symbols in perf script */
9 noinline void leaf(void);
10 noinline void parent(void);
11 
12 static volatile sig_atomic_t done asm("leafloop_done");
13 
14 static void sighandler(int sig __maybe_unused)
15 {
16 	done = 1;
17 }
18 
19 #if defined(__aarch64__)
20 /*
21  * Write leaf() in assembly so it stays as a minimal leaf function with no
22  * stack frame and won't get silently broken in the future by any Perf wide
23  * compilation options like -fstack-protector-all.
24  */
25 asm(
26 	".pushsection .text,\"ax\",%progbits\n"
27 	".global leaf\n"
28 	".type leaf, %function\n"
29 	"leaf:\n"
30 	"	adrp	x1, leafloop_done\n"
31 	"	ldr	w2, [x1, #:lo12:leafloop_done]\n"
32 	"	cbz	w2, leaf\n"
33 	"	ret\n"
34 	".size leaf, .-leaf\n"
35 	".popsection\n"
36 );
37 
38 #else
39 
40 noinline void leaf(void)
41 {
42 	while (!done)
43 		;
44 }
45 
46 #endif
47 
48 noinline void parent(void)
49 {
50 	leaf();
51 }
52 
53 static int leafloop(int argc, const char **argv)
54 {
55 	int sec = 1;
56 
57 	if (argc > 0)
58 		sec = atoi(argv[0]);
59 
60 	signal(SIGINT, sighandler);
61 	signal(SIGALRM, sighandler);
62 	alarm(sec);
63 
64 	parent();
65 	return 0;
66 }
67 
68 DEFINE_WORKLOAD(leafloop);
69