blob: 6ee6f687a834d9b52b22ff09ec75ea7fb463c209 [file] [log] [blame]
sewardjde4a1d02002-03-22 01:27:54 +00001
2/*--------------------------------------------------------------------*/
nethercote7cc9c232004-01-21 15:08:04 +00003/*--- Profiling machinery. #include this file into a tool to ---*/
4/*--- enable --profile=yes, but not for release versions of tools, ---*/
njn25e49d8e72002-09-23 09:36:25 +00005/*--- because it uses glibc code. ---*/
sewardjde4a1d02002-03-22 01:27:54 +00006/*--- vg_profile.c ---*/
7/*--------------------------------------------------------------------*/
8
9/*
njnb9c427c2004-12-01 14:14:42 +000010 This file is part of Valgrind, a dynamic binary instrumentation
11 framework.
sewardjde4a1d02002-03-22 01:27:54 +000012
njn53612422005-03-12 16:22:54 +000013 Copyright (C) 2000-2005 Julian Seward
sewardjde4a1d02002-03-22 01:27:54 +000014 jseward@acm.org
sewardjde4a1d02002-03-22 01:27:54 +000015
16 This program is free software; you can redistribute it and/or
17 modify it under the terms of the GNU General Public License as
18 published by the Free Software Foundation; either version 2 of the
19 License, or (at your option) any later version.
20
21 This program is distributed in the hope that it will be useful, but
22 WITHOUT ANY WARRANTY; without even the implied warranty of
23 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24 General Public License for more details.
25
26 You should have received a copy of the GNU General Public License
27 along with this program; if not, write to the Free Software
28 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
29 02111-1307, USA.
30
njn25e49d8e72002-09-23 09:36:25 +000031 The GNU General Public License is contained in the file COPYING.
sewardjde4a1d02002-03-22 01:27:54 +000032*/
33
njn25e49d8e72002-09-23 09:36:25 +000034#ifndef __VG_PROFILE_C
35#define __VG_PROFILE_C
sewardjde4a1d02002-03-22 01:27:54 +000036
nethercote46063202004-09-02 08:51:43 +000037#include "tool.h"
sewardjde4a1d02002-03-22 01:27:54 +000038
39/* get rid of these, if possible */
40#include <signal.h>
41#include <sys/time.h>
42
nethercote46063202004-09-02 08:51:43 +000043/* Override the empty definitions from tool.h */
njn25e49d8e72002-09-23 09:36:25 +000044#undef VGP_PUSHCC
45#undef VGP_POPCC
46#define VGP_PUSHCC(x) if (VG_(clo_profile)) VGP_(pushcc)(x)
47#define VGP_POPCC(x) if (VG_(clo_profile)) VGP_(popcc)(x)
sewardjde4a1d02002-03-22 01:27:54 +000048
njn25e49d8e72002-09-23 09:36:25 +000049#define VGP_M_STACK 20
50#define VGP_MAX_CCS 50
51
52
53/* All zeroed initially because they're static */
sewardjde4a1d02002-03-22 01:27:54 +000054static Int vgp_nticks;
njn25e49d8e72002-09-23 09:36:25 +000055
56static Int vgp_counts [VGP_MAX_CCS];
57static Int vgp_entries[VGP_MAX_CCS];
58static Char* vgp_names [VGP_MAX_CCS];
sewardjde4a1d02002-03-22 01:27:54 +000059
60static Int vgp_sp;
njn25e49d8e72002-09-23 09:36:25 +000061static UInt vgp_stack[VGP_M_STACK];
62
63/* These definitions override the panicking ones in vg_profile.c */
64
65void VGP_(register_profile_event) ( Int n, Char* name )
66{
67 /* Adjust for negative values */
68 n += VgpUnc;
69 if (n >= VGP_MAX_CCS) {
70 VG_(printf)("\nProfile event #%d higher than VGP_MAX_CCS of %d.\n"
71 "If you really need this many profile events, increase\n"
72 "VGP_MAX_CCS and recompile Valgrind.\n",
73 n, VGP_MAX_CCS);
njn67993252004-11-22 18:02:32 +000074 VG_(tool_panic)("profile event too high");
njn25e49d8e72002-09-23 09:36:25 +000075 }
76 if (vgp_names[n] != NULL) {
77 VG_(printf)("\nProfile event #%d being registered as `%s'\n"
78 "already registered as `%s'.\n"
nethercote7cc9c232004-01-21 15:08:04 +000079 "Note that tool and core event numbers must not overlap.\n",
njn25e49d8e72002-09-23 09:36:25 +000080 n, name, vgp_names[n]);
njn67993252004-11-22 18:02:32 +000081 VG_(tool_panic)("profile event already registered");
njn25e49d8e72002-09-23 09:36:25 +000082 }
83
84 vgp_names[n] = name;
85}
sewardjde4a1d02002-03-22 01:27:54 +000086
87void VGP_(tick) ( int sigNo )
88{
89 Int cc;
90 vgp_nticks++;
91 cc = vgp_stack[vgp_sp];
njnca82cc02004-11-22 17:18:48 +000092 tl_assert(cc >= 0 && cc < VGP_MAX_CCS);
sewardjde4a1d02002-03-22 01:27:54 +000093 vgp_counts[ cc ]++;
94}
95
96void VGP_(init_profiling) ( void )
97{
98 struct itimerval value;
njn25e49d8e72002-09-23 09:36:25 +000099 Int ret;
sewardjde4a1d02002-03-22 01:27:54 +0000100
njn25e49d8e72002-09-23 09:36:25 +0000101 /* Register core events... tricky macro definition causes
102 VGP_(register_profile_event)() to be called once for each core event
103 in VGP_CORE_LIST. */
njnca82cc02004-11-22 17:18:48 +0000104 tl_assert(VgpUnc == 0);
njn25e49d8e72002-09-23 09:36:25 +0000105# define VGP_PAIR(n,name) VGP_(register_profile_event)(n,name)
106 VGP_CORE_LIST;
107# undef VGP_PAIR
sewardjde4a1d02002-03-22 01:27:54 +0000108
sewardjde4a1d02002-03-22 01:27:54 +0000109 vgp_sp = -1;
sewardj671ff542002-05-07 09:25:30 +0000110 VGP_(pushcc) ( VgpUnc );
sewardjde4a1d02002-03-22 01:27:54 +0000111
112 value.it_interval.tv_sec = 0;
113 value.it_interval.tv_usec = 10 * 1000;
114 value.it_value = value.it_interval;
115
116 signal(SIGPROF, VGP_(tick) );
117 ret = setitimer(ITIMER_PROF, &value, NULL);
njn67993252004-11-22 18:02:32 +0000118 if (ret != 0) VG_(tool_panic)("vgp_init_profiling");
sewardjde4a1d02002-03-22 01:27:54 +0000119}
120
121void VGP_(done_profiling) ( void )
122{
123 Int i;
njn25e49d8e72002-09-23 09:36:25 +0000124 VG_(printf)("\nProfiling done, %d ticks\n", vgp_nticks);
125 for (i = 0; i < VGP_MAX_CCS; i++)
126 if (NULL != vgp_names[i])
127 VG_(printf)(
128 "%2d: %4d (%3d %%%%) ticks, %10d entries for %s\n",
129 i, vgp_counts[i],
130 (Int)(1000.0 * (double)vgp_counts[i] / (double)vgp_nticks),
131 vgp_entries[i], vgp_names[i] );
sewardjde4a1d02002-03-22 01:27:54 +0000132}
133
njn25e49d8e72002-09-23 09:36:25 +0000134void VGP_(pushcc) ( UInt cc )
sewardjde4a1d02002-03-22 01:27:54 +0000135{
njn25e49d8e72002-09-23 09:36:25 +0000136 if (vgp_sp >= VGP_M_STACK-1) {
137 VG_(printf)(
138 "\nMaximum profile stack depth (%d) reached for event #%d (`%s').\n"
139 "This is probably due to a VGP_(pushcc)() without a matching\n"
140 "VGP_(popcc)(). Make sure they all match.\n"
141 "Or if you are nesting profiling events very deeply, increase\n"
142 "VGP_M_STACK and recompile Valgrind.\n",
143 VGP_M_STACK, cc, vgp_names[cc]);
njn67993252004-11-22 18:02:32 +0000144 VG_(tool_panic)("Profiling stack overflow");
njn25e49d8e72002-09-23 09:36:25 +0000145 }
sewardjde4a1d02002-03-22 01:27:54 +0000146 vgp_sp++;
147 vgp_stack[vgp_sp] = cc;
148 vgp_entries[ cc ] ++;
149}
150
njn25e49d8e72002-09-23 09:36:25 +0000151void VGP_(popcc) ( UInt cc )
sewardjde4a1d02002-03-22 01:27:54 +0000152{
njn25e49d8e72002-09-23 09:36:25 +0000153 if (vgp_sp <= 0) {
154 VG_(printf)(
155 "\nProfile stack underflow. This is due to a VGP_(popcc)() without\n"
156 "a matching VGP_(pushcc)(). Make sure they all match.\n");
njn67993252004-11-22 18:02:32 +0000157 VG_(tool_panic)("Profiling stack underflow");
njn25e49d8e72002-09-23 09:36:25 +0000158 }
159 if (vgp_stack[vgp_sp] != cc) {
160 Int i;
161 VG_(printf)("popping %s, stack looks like:\n", vgp_names[cc]);
162 for (i = vgp_sp; i >= 0; i--)
163 VG_(printf)("%2d: %s\n", i, vgp_names[vgp_stack[i]]);
164 VG_(exit)(1);
165 }
sewardjde4a1d02002-03-22 01:27:54 +0000166 vgp_sp--;
167}
168
njn25e49d8e72002-09-23 09:36:25 +0000169#endif /* __VG_PROFILE_C */
sewardjde4a1d02002-03-22 01:27:54 +0000170
171/*--------------------------------------------------------------------*/
172/*--- end vg_profile.c ---*/
173/*--------------------------------------------------------------------*/