blob: 212358f78669538e41422aad25ea5cd54870502d [file] [log] [blame]
sewardjde4a1d02002-03-22 01:27:54 +00001
2/*--------------------------------------------------------------------*/
njn31513b42005-06-01 03:09:59 +00003/*--- Profiling machinery. m_profile.c ---*/
sewardjde4a1d02002-03-22 01:27:54 +00004/*--------------------------------------------------------------------*/
5
6/*
njnb9c427c2004-12-01 14:14:42 +00007 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
sewardjde4a1d02002-03-22 01:27:54 +00009
njn53612422005-03-12 16:22:54 +000010 Copyright (C) 2000-2005 Julian Seward
sewardjde4a1d02002-03-22 01:27:54 +000011 jseward@acm.org
sewardjde4a1d02002-03-22 01:27:54 +000012
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26 02111-1307, USA.
27
njn25e49d8e72002-09-23 09:36:25 +000028 The GNU General Public License is contained in the file COPYING.
sewardjde4a1d02002-03-22 01:27:54 +000029*/
30
njnc7561b92005-06-19 01:24:32 +000031#include "pub_core_basics.h"
njn132bfcc2005-06-04 19:16:06 +000032#include "pub_core_libcassert.h"
njn36a20fa2005-06-03 03:08:39 +000033#include "pub_core_libcprint.h"
njn31513b42005-06-01 03:09:59 +000034#include "pub_core_profile.h"
sewardjde4a1d02002-03-22 01:27:54 +000035
36/* get rid of these, if possible */
37#include <signal.h>
38#include <sys/time.h>
39
sewardjde4a1d02002-03-22 01:27:54 +000040
njn25e49d8e72002-09-23 09:36:25 +000041#define VGP_M_STACK 20
42#define VGP_MAX_CCS 50
43
njn25e49d8e72002-09-23 09:36:25 +000044/* All zeroed initially because they're static */
sewardjde4a1d02002-03-22 01:27:54 +000045static Int vgp_nticks;
njn25e49d8e72002-09-23 09:36:25 +000046
47static Int vgp_counts [VGP_MAX_CCS];
48static Int vgp_entries[VGP_MAX_CCS];
49static Char* vgp_names [VGP_MAX_CCS];
sewardjde4a1d02002-03-22 01:27:54 +000050
51static Int vgp_sp;
njn25e49d8e72002-09-23 09:36:25 +000052static UInt vgp_stack[VGP_M_STACK];
53
54/* These definitions override the panicking ones in vg_profile.c */
55
njn31066fd2005-03-26 00:42:02 +000056void VG_(register_profile_event) ( Int n, Char* name )
njn25e49d8e72002-09-23 09:36:25 +000057{
58 /* Adjust for negative values */
59 n += VgpUnc;
60 if (n >= VGP_MAX_CCS) {
61 VG_(printf)("\nProfile event #%d higher than VGP_MAX_CCS of %d.\n"
62 "If you really need this many profile events, increase\n"
63 "VGP_MAX_CCS and recompile Valgrind.\n",
64 n, VGP_MAX_CCS);
njn67993252004-11-22 18:02:32 +000065 VG_(tool_panic)("profile event too high");
njn25e49d8e72002-09-23 09:36:25 +000066 }
67 if (vgp_names[n] != NULL) {
njn02bc4b82005-05-15 17:28:26 +000068 VG_(printf)("\nProfile event #%d being registered as '%s'\n"
69 "already registered as '%s'.\n"
nethercote7cc9c232004-01-21 15:08:04 +000070 "Note that tool and core event numbers must not overlap.\n",
njn25e49d8e72002-09-23 09:36:25 +000071 n, name, vgp_names[n]);
njn67993252004-11-22 18:02:32 +000072 VG_(tool_panic)("profile event already registered");
njn25e49d8e72002-09-23 09:36:25 +000073 }
74
75 vgp_names[n] = name;
76}
sewardjde4a1d02002-03-22 01:27:54 +000077
njn31513b42005-06-01 03:09:59 +000078static void tick ( int sigNo )
sewardjde4a1d02002-03-22 01:27:54 +000079{
80 Int cc;
81 vgp_nticks++;
82 cc = vgp_stack[vgp_sp];
njnca82cc02004-11-22 17:18:48 +000083 tl_assert(cc >= 0 && cc < VGP_MAX_CCS);
sewardjde4a1d02002-03-22 01:27:54 +000084 vgp_counts[ cc ]++;
85}
86
njn31066fd2005-03-26 00:42:02 +000087void VG_(init_profiling) ( void )
sewardjde4a1d02002-03-22 01:27:54 +000088{
89 struct itimerval value;
njn25e49d8e72002-09-23 09:36:25 +000090 Int ret;
sewardjde4a1d02002-03-22 01:27:54 +000091
njn31513b42005-06-01 03:09:59 +000092#ifndef VG_DO_PROFILING
93 VG_(printf)("valgrind: you must compile with VG_DO_PROFILING defined\n");
94 VG_(printf)(" before using --profile=yes. Aborting.\n");
95 VG_(exit)(1);
96#endif
97
njn25e49d8e72002-09-23 09:36:25 +000098 /* Register core events... tricky macro definition causes
njn31066fd2005-03-26 00:42:02 +000099 VG_(register_profile_event)() to be called once for each core event
njn25e49d8e72002-09-23 09:36:25 +0000100 in VGP_CORE_LIST. */
njnca82cc02004-11-22 17:18:48 +0000101 tl_assert(VgpUnc == 0);
njn31066fd2005-03-26 00:42:02 +0000102# define VGP_PAIR(n,name) VG_(register_profile_event)(n,name)
njn25e49d8e72002-09-23 09:36:25 +0000103 VGP_CORE_LIST;
104# undef VGP_PAIR
sewardjde4a1d02002-03-22 01:27:54 +0000105
sewardjde4a1d02002-03-22 01:27:54 +0000106 vgp_sp = -1;
njn31066fd2005-03-26 00:42:02 +0000107 VG_(pushcc) ( VgpUnc );
sewardjde4a1d02002-03-22 01:27:54 +0000108
109 value.it_interval.tv_sec = 0;
110 value.it_interval.tv_usec = 10 * 1000;
111 value.it_value = value.it_interval;
112
njn31513b42005-06-01 03:09:59 +0000113 signal(SIGPROF, tick );
sewardjde4a1d02002-03-22 01:27:54 +0000114 ret = setitimer(ITIMER_PROF, &value, NULL);
njn31513b42005-06-01 03:09:59 +0000115 if (ret != 0) VG_(core_panic)("vgp_init_profiling");
sewardjde4a1d02002-03-22 01:27:54 +0000116}
117
njn31066fd2005-03-26 00:42:02 +0000118void VG_(done_profiling) ( void )
sewardjde4a1d02002-03-22 01:27:54 +0000119{
120 Int i;
njn25e49d8e72002-09-23 09:36:25 +0000121 VG_(printf)("\nProfiling done, %d ticks\n", vgp_nticks);
122 for (i = 0; i < VGP_MAX_CCS; i++)
123 if (NULL != vgp_names[i])
124 VG_(printf)(
125 "%2d: %4d (%3d %%%%) ticks, %10d entries for %s\n",
126 i, vgp_counts[i],
127 (Int)(1000.0 * (double)vgp_counts[i] / (double)vgp_nticks),
128 vgp_entries[i], vgp_names[i] );
sewardjde4a1d02002-03-22 01:27:54 +0000129}
130
njn31066fd2005-03-26 00:42:02 +0000131void VG_(pushcc) ( UInt cc )
sewardjde4a1d02002-03-22 01:27:54 +0000132{
njn25e49d8e72002-09-23 09:36:25 +0000133 if (vgp_sp >= VGP_M_STACK-1) {
134 VG_(printf)(
njn02bc4b82005-05-15 17:28:26 +0000135 "\nMaximum profile stack depth (%d) reached for event #%d ('%s').\n"
njn31066fd2005-03-26 00:42:02 +0000136 "This is probably due to a VG_(pushcc)() without a matching\n"
137 "VG_(popcc)(). Make sure they all match.\n"
njn25e49d8e72002-09-23 09:36:25 +0000138 "Or if you are nesting profiling events very deeply, increase\n"
139 "VGP_M_STACK and recompile Valgrind.\n",
140 VGP_M_STACK, cc, vgp_names[cc]);
njn31513b42005-06-01 03:09:59 +0000141 VG_(core_panic)("Profiling stack overflow");
njn25e49d8e72002-09-23 09:36:25 +0000142 }
sewardjde4a1d02002-03-22 01:27:54 +0000143 vgp_sp++;
144 vgp_stack[vgp_sp] = cc;
145 vgp_entries[ cc ] ++;
146}
147
njn31066fd2005-03-26 00:42:02 +0000148void VG_(popcc) ( UInt cc )
sewardjde4a1d02002-03-22 01:27:54 +0000149{
njn25e49d8e72002-09-23 09:36:25 +0000150 if (vgp_sp <= 0) {
151 VG_(printf)(
njn31066fd2005-03-26 00:42:02 +0000152 "\nProfile stack underflow. This is due to a VG_(popcc)() without\n"
153 "a matching VG_(pushcc)(). Make sure they all match.\n");
njn31513b42005-06-01 03:09:59 +0000154 VG_(core_panic)("Profiling stack underflow");
njn25e49d8e72002-09-23 09:36:25 +0000155 }
156 if (vgp_stack[vgp_sp] != cc) {
157 Int i;
njn31513b42005-06-01 03:09:59 +0000158 VG_(printf)("profiling problem:\n");
njn25e49d8e72002-09-23 09:36:25 +0000159 VG_(printf)("popping %s, stack looks like:\n", vgp_names[cc]);
160 for (i = vgp_sp; i >= 0; i--)
161 VG_(printf)("%2d: %s\n", i, vgp_names[vgp_stack[i]]);
162 VG_(exit)(1);
163 }
sewardjde4a1d02002-03-22 01:27:54 +0000164 vgp_sp--;
165}
166
njn31513b42005-06-01 03:09:59 +0000167/*--------------------------------------------------------------------*/
168/*--- end ---*/
169/*--------------------------------------------------------------------*/
sewardjde4a1d02002-03-22 01:27:54 +0000170
njn31513b42005-06-01 03:09:59 +0000171