xref: /aosp_15_r20/external/ltp/testcases/kernel/syscalls/profil/profil01.c (revision 49cdfc7efb34551c7342be41a7384b9c40d7cab7)
1*49cdfc7eSAndroid Build Coastguard Worker /*
2*49cdfc7eSAndroid Build Coastguard Worker  *   Copyright (c) International Business Machines  Corp., 2002
3*49cdfc7eSAndroid Build Coastguard Worker  *   Copyright (C) 2014 Linux Test Project, Inc.
4*49cdfc7eSAndroid Build Coastguard Worker  *
5*49cdfc7eSAndroid Build Coastguard Worker  *   This program is free software;  you can redistribute it and/or modify
6*49cdfc7eSAndroid Build Coastguard Worker  *   it under the terms of the GNU General Public License as published by
7*49cdfc7eSAndroid Build Coastguard Worker  *   the Free Software Foundation; either version 2 of the License, or
8*49cdfc7eSAndroid Build Coastguard Worker  *   (at your option) any later version.
9*49cdfc7eSAndroid Build Coastguard Worker  *
10*49cdfc7eSAndroid Build Coastguard Worker  *   This program is distributed in the hope that it will be useful,
11*49cdfc7eSAndroid Build Coastguard Worker  *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
12*49cdfc7eSAndroid Build Coastguard Worker  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
13*49cdfc7eSAndroid Build Coastguard Worker  *   the GNU General Public License for more details.
14*49cdfc7eSAndroid Build Coastguard Worker  */
15*49cdfc7eSAndroid Build Coastguard Worker /*
16*49cdfc7eSAndroid Build Coastguard Worker  * ALGORITHM
17*49cdfc7eSAndroid Build Coastguard Worker  *	Set up a profiling buffer, turn profiling on, set a timer for
18*49cdfc7eSAndroid Build Coastguard Worker  *	cpu time, spin the pc and wait for timer to go off.
19*49cdfc7eSAndroid Build Coastguard Worker  *	The profiling buffer should contain some info, highly concentrated.
20*49cdfc7eSAndroid Build Coastguard Worker  *	We just do a "looks reasonable" check.
21*49cdfc7eSAndroid Build Coastguard Worker  */
22*49cdfc7eSAndroid Build Coastguard Worker 
23*49cdfc7eSAndroid Build Coastguard Worker #include <stdio.h>
24*49cdfc7eSAndroid Build Coastguard Worker #include <signal.h>
25*49cdfc7eSAndroid Build Coastguard Worker #include <unistd.h>
26*49cdfc7eSAndroid Build Coastguard Worker #include <errno.h>
27*49cdfc7eSAndroid Build Coastguard Worker #include <sys/types.h>
28*49cdfc7eSAndroid Build Coastguard Worker #include "test.h"
29*49cdfc7eSAndroid Build Coastguard Worker #include "safe_macros.h"
30*49cdfc7eSAndroid Build Coastguard Worker #include "lapi/abisize.h"
31*49cdfc7eSAndroid Build Coastguard Worker #include "config.h"
32*49cdfc7eSAndroid Build Coastguard Worker 
33*49cdfc7eSAndroid Build Coastguard Worker char *TCID = "profil01";
34*49cdfc7eSAndroid Build Coastguard Worker 
35*49cdfc7eSAndroid Build Coastguard Worker #if HAVE_PROFIL
36*49cdfc7eSAndroid Build Coastguard Worker 
37*49cdfc7eSAndroid Build Coastguard Worker #define PROFIL_TIME 5
38*49cdfc7eSAndroid Build Coastguard Worker 
39*49cdfc7eSAndroid Build Coastguard Worker /* Should be large enough to hold data for test_profil() .text,
40*49cdfc7eSAndroid Build Coastguard Worker  * on x86_64 this is ~600 bytes, so 16k should enough for all arches.
41*49cdfc7eSAndroid Build Coastguard Worker  * We will monitor 16k on each side around current pc value,
42*49cdfc7eSAndroid Build Coastguard Worker  * just in case compiler put call to get_pc() below "data shuffling" code */
43*49cdfc7eSAndroid Build Coastguard Worker #define PROFIL_BUFLEN (32*1024)
44*49cdfc7eSAndroid Build Coastguard Worker 
45*49cdfc7eSAndroid Build Coastguard Worker int TST_TOTAL = 1;
46*49cdfc7eSAndroid Build Coastguard Worker 
47*49cdfc7eSAndroid Build Coastguard Worker static volatile sig_atomic_t profil_done;
48*49cdfc7eSAndroid Build Coastguard Worker 
alrm_handler(int sig)49*49cdfc7eSAndroid Build Coastguard Worker static void alrm_handler(int sig)
50*49cdfc7eSAndroid Build Coastguard Worker {
51*49cdfc7eSAndroid Build Coastguard Worker 	(void) sig;
52*49cdfc7eSAndroid Build Coastguard Worker 	profil_done = 1;
53*49cdfc7eSAndroid Build Coastguard Worker }
54*49cdfc7eSAndroid Build Coastguard Worker 
get_pc(void)55*49cdfc7eSAndroid Build Coastguard Worker static void __attribute__ ((noinline)) *get_pc(void)
56*49cdfc7eSAndroid Build Coastguard Worker {
57*49cdfc7eSAndroid Build Coastguard Worker #if defined(__s390__) && defined(TST_ABI32)
58*49cdfc7eSAndroid Build Coastguard Worker 	/* taken from glibc,
59*49cdfc7eSAndroid Build Coastguard Worker 	 *   sysdeps/unix/sysv/linux/s390/s390-32/profil-counter.h
60*49cdfc7eSAndroid Build Coastguard Worker 	 * 31-bit s390 pointers don't use the 32th bit, however integers do,
61*49cdfc7eSAndroid Build Coastguard Worker 	 * so wrap the value around at 31 bits */
62*49cdfc7eSAndroid Build Coastguard Worker 	return (void *)
63*49cdfc7eSAndroid Build Coastguard Worker 		((unsigned long) __builtin_return_address(0) & 0x7fffffffUL);
64*49cdfc7eSAndroid Build Coastguard Worker #else
65*49cdfc7eSAndroid Build Coastguard Worker 	return __builtin_return_address(0);
66*49cdfc7eSAndroid Build Coastguard Worker #endif
67*49cdfc7eSAndroid Build Coastguard Worker }
68*49cdfc7eSAndroid Build Coastguard Worker 
test_profil(void)69*49cdfc7eSAndroid Build Coastguard Worker static void test_profil(void)
70*49cdfc7eSAndroid Build Coastguard Worker {
71*49cdfc7eSAndroid Build Coastguard Worker 	unsigned short buf[PROFIL_BUFLEN] = { 0 };
72*49cdfc7eSAndroid Build Coastguard Worker 	volatile int data[8] = { 0 };
73*49cdfc7eSAndroid Build Coastguard Worker 	size_t offset = (size_t) get_pc() - PROFIL_BUFLEN/2, count = 0;
74*49cdfc7eSAndroid Build Coastguard Worker 	int ret, i;
75*49cdfc7eSAndroid Build Coastguard Worker 
76*49cdfc7eSAndroid Build Coastguard Worker 	/* reset for test looping */
77*49cdfc7eSAndroid Build Coastguard Worker 	profil_done = 0;
78*49cdfc7eSAndroid Build Coastguard Worker 
79*49cdfc7eSAndroid Build Coastguard Worker 	/* profil_count in glibc calculates offset as
80*49cdfc7eSAndroid Build Coastguard Worker 	 *   i = (pc - pc_offset - (void *) 0) / 2
81*49cdfc7eSAndroid Build Coastguard Worker 	 *   i = i * pc_scale / 65536
82*49cdfc7eSAndroid Build Coastguard Worker 	 * set scale to 2*65536 to have 1:1 mapping for $pc */
83*49cdfc7eSAndroid Build Coastguard Worker 	ret = profil(buf, sizeof(buf), offset, 2*65536);
84*49cdfc7eSAndroid Build Coastguard Worker 	if (ret)
85*49cdfc7eSAndroid Build Coastguard Worker 		tst_brkm(TBROK, NULL, "profil returned: %d", ret);
86*49cdfc7eSAndroid Build Coastguard Worker 
87*49cdfc7eSAndroid Build Coastguard Worker 	signal(SIGALRM, alrm_handler);
88*49cdfc7eSAndroid Build Coastguard Worker 	alarm(PROFIL_TIME);
89*49cdfc7eSAndroid Build Coastguard Worker 
90*49cdfc7eSAndroid Build Coastguard Worker 	while (!profil_done) {
91*49cdfc7eSAndroid Build Coastguard Worker 		if (data[0])
92*49cdfc7eSAndroid Build Coastguard Worker 			data[0] = -data[7];
93*49cdfc7eSAndroid Build Coastguard Worker 		else
94*49cdfc7eSAndroid Build Coastguard Worker 			data[1] = data[0] / 2;
95*49cdfc7eSAndroid Build Coastguard Worker 		if (data[2])
96*49cdfc7eSAndroid Build Coastguard Worker 			data[2] = data[1] * 2;
97*49cdfc7eSAndroid Build Coastguard Worker 		else
98*49cdfc7eSAndroid Build Coastguard Worker 			data[3] = data[2] + data[0];
99*49cdfc7eSAndroid Build Coastguard Worker 		if (data[4])
100*49cdfc7eSAndroid Build Coastguard Worker 			data[4] = data[3] - data[1];
101*49cdfc7eSAndroid Build Coastguard Worker 		else
102*49cdfc7eSAndroid Build Coastguard Worker 			data[5] = data[4] * data[2];
103*49cdfc7eSAndroid Build Coastguard Worker 		if (data[6])
104*49cdfc7eSAndroid Build Coastguard Worker 			data[6] = data[5] + data[3];
105*49cdfc7eSAndroid Build Coastguard Worker 		else
106*49cdfc7eSAndroid Build Coastguard Worker 			data[7] = data[6] - data[4];
107*49cdfc7eSAndroid Build Coastguard Worker 	}
108*49cdfc7eSAndroid Build Coastguard Worker 
109*49cdfc7eSAndroid Build Coastguard Worker 	for (i = 0; i < PROFIL_BUFLEN; i++)
110*49cdfc7eSAndroid Build Coastguard Worker 		if (buf[i]) {
111*49cdfc7eSAndroid Build Coastguard Worker 			tst_resm(TINFO, "buf[0x%04x]=%d", i, buf[i]);
112*49cdfc7eSAndroid Build Coastguard Worker 			count += buf[i];
113*49cdfc7eSAndroid Build Coastguard Worker 		}
114*49cdfc7eSAndroid Build Coastguard Worker 
115*49cdfc7eSAndroid Build Coastguard Worker 	if (count > 0)
116*49cdfc7eSAndroid Build Coastguard Worker 		tst_resm(TPASS, "profil recorded some data");
117*49cdfc7eSAndroid Build Coastguard Worker 	else
118*49cdfc7eSAndroid Build Coastguard Worker 		tst_resm(TFAIL, "profil failed to record anything");
119*49cdfc7eSAndroid Build Coastguard Worker }
120*49cdfc7eSAndroid Build Coastguard Worker 
main(int ac,char * av[])121*49cdfc7eSAndroid Build Coastguard Worker int main(int ac, char *av[])
122*49cdfc7eSAndroid Build Coastguard Worker {
123*49cdfc7eSAndroid Build Coastguard Worker 	int lc;
124*49cdfc7eSAndroid Build Coastguard Worker 
125*49cdfc7eSAndroid Build Coastguard Worker 	tst_parse_opts(ac, av, NULL, NULL);
126*49cdfc7eSAndroid Build Coastguard Worker 
127*49cdfc7eSAndroid Build Coastguard Worker 	for (lc = 0; TEST_LOOPING(lc); lc++)
128*49cdfc7eSAndroid Build Coastguard Worker 		test_profil();
129*49cdfc7eSAndroid Build Coastguard Worker 
130*49cdfc7eSAndroid Build Coastguard Worker 	tst_exit();
131*49cdfc7eSAndroid Build Coastguard Worker }
132*49cdfc7eSAndroid Build Coastguard Worker #else /* systems without profil() */
main(void)133*49cdfc7eSAndroid Build Coastguard Worker int main(void)
134*49cdfc7eSAndroid Build Coastguard Worker {
135*49cdfc7eSAndroid Build Coastguard Worker         tst_brkm(TCONF, NULL, "system doesn't have profil() support");
136*49cdfc7eSAndroid Build Coastguard Worker }
137*49cdfc7eSAndroid Build Coastguard Worker #endif
138