profil01.c revision 8ed20e6ce21b1ab367615b5fd5195f7ce6fbe1e8
1/*
2 *   Copyright (c) International Business Machines  Corp., 2002
3 *   Copyright (C) 2014 Linux Test Project, Inc.
4 *
5 *   This program is free software;  you can redistribute it and/or modify
6 *   it under the terms of the GNU General Public License as published by
7 *   the Free Software Foundation; either version 2 of the License, or
8 *   (at your option) any later version.
9 *
10 *   This program is distributed in the hope that it will be useful,
11 *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
12 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
13 *   the GNU General Public License for more details.
14 */
15/*
16 * ALGORITHM
17 *	Set up a profiling buffer, turn profiling on, set a timer for
18 *	cpu time, spin the pc and wait for timer to go off.
19 *	The profiling buffer should contain some info, highly concentrated.
20 *	We just do a "looks reasonable" check.
21 */
22
23#include <stdio.h>
24#include <signal.h>
25#include <unistd.h>
26#include <errno.h>
27#include <sys/types.h>
28#include "test.h"
29#include "safe_macros.h"
30#include "usctest.h"
31
32#define PROFIL_TIME 5
33
34/* should be large enough to hold data for test_profil() .text
35 * on x86_64 this is ~600 bytes, so 16k should enough for all arches */
36#define PROFIL_BUFLEN (16*1024)
37
38char *TCID = "profil01";
39int TST_TOTAL = 1;
40
41static volatile sig_atomic_t profil_done;
42
43static void alrm_handler(int sig)
44{
45	(void) sig;
46	profil_done = 1;
47}
48
49static void test_profil(void)
50{
51	unsigned short buf[PROFIL_BUFLEN] = { 0 };
52	volatile int data[8] = { 0 };
53	size_t offset = (size_t) &test_profil, count = 0;
54	int ret, i;
55
56	/* reset for test looping */
57	profil_done = 0;
58
59	/* profil_count in glibc calculates offset as
60	 *   i = (pc - pc_offset - (void *) 0) / 2
61	 *   i = i * pc_scale / 65536
62	 * set scale to 2*65536 to have 1:1 mapping for $pc */
63	ret = profil(buf, sizeof(buf), offset, 2*65536);
64	if (ret)
65		tst_brkm(TBROK, NULL, "profil returned: %d\n", ret);
66
67	signal(SIGALRM, alrm_handler);
68	alarm(PROFIL_TIME);
69
70	while (!profil_done) {
71		if (data[0])
72			data[0] = -data[7];
73		else
74			data[1] = data[0] / 2;
75		if (data[2])
76			data[2] = data[1] * 2;
77		else
78			data[3] = data[2] + data[0];
79		if (data[4])
80			data[4] = data[3] - data[1];
81		else
82			data[5] = data[4] * data[2];
83		if (data[6])
84			data[6] = data[5] + data[3];
85		else
86			data[7] = data[6] - data[4];
87	}
88
89	for (i = 0; i < PROFIL_BUFLEN; i++)
90		if (buf[i]) {
91			tst_resm(TINFO, "buf[0x%04x]=%d", i, buf[i]);
92			count += buf[i];
93		}
94
95	if (count > 0)
96		tst_resm(TPASS, "profil recorded some data");
97	else
98		tst_resm(TFAIL, "profil failed to record anything");
99}
100
101int main(int ac, char *av[])
102{
103	int lc;
104	const char *msg;
105
106	msg = parse_opts(ac, av, NULL, NULL);
107	if (msg != NULL)
108		tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
109
110	for (lc = 0; TEST_LOOPING(lc); lc++)
111		test_profil();
112
113	tst_exit();
114}
115