1 /* Copyright (C) 2001-2022 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3 
4    The GNU C Library is free software; you can redistribute it and/or
5    modify it under the terms of the GNU Lesser General Public
6    License as published by the Free Software Foundation; either
7    version 2.1 of the License, or (at your option) any later version.
8 
9    The GNU C Library is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    Lesser General Public License for more details.
13 
14    You should have received a copy of the GNU Lesser General Public
15    License along with the GNU C Library; if not, see
16    <https://www.gnu.org/licenses/>.  */
17 
18 #include <errno.h>
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <sys/profil.h>
22 
23 #include <bits/wordsize.h>
24 
25 #define NELEMS(a)	(sizeof (a)/sizeof ((a)[0]))
26 
27 size_t taddr[] =
28   {
29     0x00001000,		/* elf32/hppa */
30     0x08048000,		/* Linux elf32/x86 */
31     0x80000000,		/* Linux elf32/m68k */
32     0x00400000,		/* Linux elf32/mips */
33     0x01800000,		/* Linux elf32/ppc */
34     0x00010000		/* Linux elf32/sparc */
35 #if __WORDSIZE > 32
36     ,
37     0x4000000000000000,	/* Linux elf64/ia64 */
38     0x0000000120000000,	/* Linux elf64/alpha */
39     0x4000000000001000,	/* elf64/hppa */
40     0x0000000100000000	/* Linux elf64/sparc */
41 #endif
42   };
43 
44 unsigned int buf[NELEMS (taddr)][0x10000 / sizeof (int)];
45 unsigned int bshort[5][0x100 / sizeof (int)];
46 unsigned int blong[1][0x1000 / sizeof (int)];
47 unsigned int vlong[1][0x2000 / sizeof (int)];
48 
49 static long int
fac(long int n)50 fac (long int n)
51 {
52   if (n == 0)
53     return 1;
54   return n * fac (n - 1);
55 }
56 
57 int
main(int argc,char ** argv)58 main (int argc, char **argv)
59 {
60   unsigned int ovfl = 0, profcnt = 0;
61   struct timeval tv, start;
62   struct prof prof[32];
63   double t_tick, delta;
64   long int sum = 0;
65   int i, j;
66 
67   for (i = 0; i < NELEMS (taddr); ++i)
68     {
69       prof[profcnt].pr_base = buf[i];
70       prof[profcnt].pr_size = sizeof (buf[i]);
71       prof[profcnt].pr_off = taddr[i];
72       prof[profcnt].pr_scale = 0x10000;
73       ++profcnt;
74     }
75 
76   prof[profcnt].pr_base = blong[0];
77   prof[profcnt].pr_size = sizeof (blong[0]);
78   prof[profcnt].pr_off = 0x80001000;
79   prof[profcnt].pr_scale = 0x10000;
80   ++profcnt;
81 
82   prof[profcnt].pr_base = bshort[0];
83   prof[profcnt].pr_size = sizeof (bshort[0]);
84   prof[profcnt].pr_off = 0x80000080;
85   prof[profcnt].pr_scale = 0x10000;
86   ++profcnt;
87 
88   prof[profcnt].pr_base = bshort[1];
89   prof[profcnt].pr_size = sizeof (bshort[1]);
90   prof[profcnt].pr_off = 0x80000f80;
91   prof[profcnt].pr_scale = 0x10000;
92   ++profcnt;
93 
94   prof[profcnt].pr_base = bshort[2];
95   prof[profcnt].pr_size = sizeof (bshort[2]);
96   prof[profcnt].pr_off = 0x80001080;
97   prof[profcnt].pr_scale = 0x10000;
98   ++profcnt;
99 
100   prof[profcnt].pr_base = bshort[3];
101   prof[profcnt].pr_size = sizeof (bshort[3]);
102   prof[profcnt].pr_off = 0x80001f80;
103   prof[profcnt].pr_scale = 0x10000;
104   ++profcnt;
105 
106   prof[profcnt].pr_base = bshort[4];
107   prof[profcnt].pr_size = sizeof (bshort[4]);
108   prof[profcnt].pr_off = 0x80002080;
109   prof[profcnt].pr_scale = 0x10000;
110   ++profcnt;
111 
112   prof[profcnt].pr_base = vlong[0];
113   prof[profcnt].pr_size = sizeof (vlong[0]);
114   prof[profcnt].pr_off = 0x80000080;
115   prof[profcnt].pr_scale = 0x10000;
116   ++profcnt;
117 
118   /* Set up overflow counter (must be last on Irix).  */
119   prof[profcnt].pr_base = &ovfl;
120   prof[profcnt].pr_size = sizeof (ovfl);
121   prof[profcnt].pr_off = 0;
122   prof[profcnt].pr_scale = 2;
123   ++profcnt;
124 
125   /* Turn it on.  */
126   if (sprofil (prof, profcnt, &tv, PROF_UINT) < 0)
127     {
128       if (errno == ENOSYS)
129 	exit (0);
130       perror ("sprofil");
131       exit (1);
132     }
133 
134   t_tick = tv.tv_sec + 1e-6 * tv.tv_usec;
135   printf ("profiling period = %g ms\n", 1e3 * t_tick);
136 
137   gettimeofday (&start, NULL);
138   do
139     {
140       for (i = 0; i < 21; ++i)
141 	sum += fac (i);
142 
143       gettimeofday (&tv, NULL);
144       timersub (&tv, &start, &tv);
145       delta = tv.tv_sec + 1e-6 * tv.tv_usec;
146     }
147   while (delta < 1000 * t_tick);
148 
149   printf ("sum = 0x%lx\n", sum);
150 
151   /* Turn it off.  */
152   if (sprofil (NULL, 0, NULL, 0) < 0)
153     {
154       if (errno == ENOSYS)
155 	exit (0);
156       perror ("sprofil");
157       exit (1);
158     }
159 
160   printf ("overflow = %u\n", ovfl);
161   for (i = 0; i < NELEMS (taddr); ++i)
162     for (j = 0; j < 0x10000 / sizeof (int); ++j)
163       if (buf[i][j] != 0)
164 	printf ("%0*Zx\t%u\t(buffer %d)\n",
165 		(int) (sizeof (size_t) * 2),
166 		(taddr[i] + ((char *) &buf[i][j] - (char *) &buf[i][0])),
167 		buf[i][j], i);
168 
169   return 0;
170 }
171