1 // Copyright (c) 2005, Google Inc.
2 // All rights reserved.
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above
11 // copyright notice, this list of conditions and the following disclaimer
12 // in the documentation and/or other materials provided with the
14 // * Neither the name of Google Inc. nor the names of its
15 // contributors may be used to endorse or promote products derived from
16 // this software without specific prior written permission.
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 // Author: Sanjay Ghemawat
32 // Chris Demetriou (refactoring)
34 // Profile current program by sampling stack-trace every so often
37 #include "getpc.h" // should be first to get the _GNU_SOURCE dfn
44 #include <unistd.h> // for getpid()
46 #if defined(HAVE_SYS_UCONTEXT_H)
47 #include <sys/ucontext.h>
48 #elif defined(HAVE_UCONTEXT_H)
50 #elif defined(HAVE_CYGWIN_SIGNAL_H)
51 #include <cygwin/signal.h>
52 typedef ucontext ucontext_t
;
53 #elif defined(__ANDROID__)
54 // Do not define ucontext_t here.
56 typedef int ucontext_t
; // just to quiet the compiler, mostly
60 #include <gperftools/profiler.h>
61 #include <gperftools/stacktrace.h>
62 #include "base/commandlineflags.h"
63 #include "base/logging.h"
64 #include "base/googleinit.h"
65 #include "base/spinlock.h"
66 #include "base/sysinfo.h" /* for GetUniquePathFromEnv, etc */
67 #include "profiledata.h"
68 #include "profile-handler.h"
69 #ifdef HAVE_CONFLICT_SIGNAL_H
70 #include "conflict-signal.h" /* used on msvc machines */
75 // Collects up all profile data. This is a singleton, which is
76 // initialized by a constructor at startup.
82 // Start profiler to write profile info into fname
83 bool Start(const char* fname
, const ProfilerOptions
* options
);
85 // Stop profiling and write the data to disk.
88 // Write the data to disk (and continue profiling).
93 void GetCurrentState(ProfilerState
* state
);
95 static CpuProfiler instance_
;
98 // This lock implements the locking requirements described in the ProfileData
99 // documentation, specifically:
101 // lock_ is held all over all collector_ method calls except for the 'Add'
102 // call made from the signal handler, to protect against concurrent use of
103 // collector_'s control routines. Code other than signal handler must
104 // unregister the signal handler before calling any collector_ method.
105 // 'Add' method in the collector is protected by a guarantee from
106 // ProfileHandle that only one instance of prof_handler can run at a time.
108 ProfileData collector_
;
110 // Filter function and its argument, if any. (NULL means include all
111 // samples). Set at start, read-only while running. Written while holding
112 // lock_, read and executed in the context of SIGPROF interrupt.
113 int (*filter_
)(void*);
116 // Opaque token returned by the profile handler. To be used when calling
117 // ProfileHandlerUnregisterCallback.
118 ProfileHandlerToken
* prof_handler_token_
;
120 // Sets up a callback to receive SIGPROF interrupt.
121 void EnableHandler();
123 // Disables receiving SIGPROF interrupt.
124 void DisableHandler();
126 // Signal handler that records the interrupted pc in the profile data.
127 static void prof_handler(int sig
, siginfo_t
*, void* signal_ucontext
,
131 // Profile data structure singleton: Constructor will check to see if
132 // profiling should be enabled. Destructor will write profile data
134 CpuProfiler
CpuProfiler::instance_
;
136 // Initialize profiling: activated if getenv("CPUPROFILE") exists.
137 CpuProfiler::CpuProfiler()
138 : prof_handler_token_(NULL
) {
139 // TODO(cgd) Move this code *out* of the CpuProfile constructor into a
140 // separate object responsible for initialization. With ProfileHandler there
141 // is no need to limit the number of profilers.
142 char fname
[PATH_MAX
];
143 if (!GetUniquePathFromEnv("CPUPROFILE", fname
)) {
146 // We don't enable profiling if setuid -- it's a security risk
148 if (getuid() != geteuid())
152 if (!Start(fname
, NULL
)) {
153 RAW_LOG(FATAL
, "Can't turn on cpu profiling for '%s': %s\n",
154 fname
, strerror(errno
));
158 bool CpuProfiler::Start(const char* fname
, const ProfilerOptions
* options
) {
159 SpinLockHolder
cl(&lock_
);
161 if (collector_
.enabled()) {
165 ProfileHandlerState prof_handler_state
;
166 ProfileHandlerGetState(&prof_handler_state
);
168 ProfileData::Options collector_options
;
169 collector_options
.set_frequency(prof_handler_state
.frequency
);
170 if (!collector_
.Start(fname
, collector_options
)) {
175 if (options
!= NULL
&& options
->filter_in_thread
!= NULL
) {
176 filter_
= options
->filter_in_thread
;
177 filter_arg_
= options
->filter_in_thread_arg
;
180 // Setup handler for SIGPROF interrupts
186 CpuProfiler::~CpuProfiler() {
190 // Stop profiling and write out any collected profile data
191 void CpuProfiler::Stop() {
192 SpinLockHolder
cl(&lock_
);
194 if (!collector_
.enabled()) {
198 // Unregister prof_handler to stop receiving SIGPROF interrupts before
199 // stopping the collector.
202 // DisableHandler waits for the currently running callback to complete and
203 // guarantees no future invocations. It is safe to stop the collector.
207 void CpuProfiler::FlushTable() {
208 SpinLockHolder
cl(&lock_
);
210 if (!collector_
.enabled()) {
214 // Unregister prof_handler to stop receiving SIGPROF interrupts before
215 // flushing the profile data.
218 // DisableHandler waits for the currently running callback to complete and
219 // guarantees no future invocations. It is safe to flush the profile data.
220 collector_
.FlushTable();
225 bool CpuProfiler::Enabled() {
226 SpinLockHolder
cl(&lock_
);
227 return collector_
.enabled();
230 void CpuProfiler::GetCurrentState(ProfilerState
* state
) {
231 ProfileData::State collector_state
;
233 SpinLockHolder
cl(&lock_
);
234 collector_
.GetCurrentState(&collector_state
);
237 state
->enabled
= collector_state
.enabled
;
238 state
->start_time
= static_cast<time_t>(collector_state
.start_time
);
239 state
->samples_gathered
= collector_state
.samples_gathered
;
240 int buf_size
= sizeof(state
->profile_name
);
241 strncpy(state
->profile_name
, collector_state
.profile_name
, buf_size
);
242 state
->profile_name
[buf_size
-1] = '\0';
245 void CpuProfiler::EnableHandler() {
246 RAW_CHECK(prof_handler_token_
== NULL
, "SIGPROF handler already registered");
247 prof_handler_token_
= ProfileHandlerRegisterCallback(prof_handler
, this);
248 RAW_CHECK(prof_handler_token_
!= NULL
, "Failed to set up SIGPROF handler");
251 void CpuProfiler::DisableHandler() {
252 RAW_CHECK(prof_handler_token_
!= NULL
, "SIGPROF handler is not registered");
253 ProfileHandlerUnregisterCallback(prof_handler_token_
);
254 prof_handler_token_
= NULL
;
257 // Signal handler that records the pc in the profile-data structure. We do no
258 // synchronization here. profile-handler.cc guarantees that at most one
259 // instance of prof_handler() will run at a time. All other routines that
260 // access the data touched by prof_handler() disable this signal handler before
261 // accessing the data and therefore cannot execute concurrently with
263 void CpuProfiler::prof_handler(int sig
, siginfo_t
*, void* signal_ucontext
,
264 void* cpu_profiler
) {
265 CpuProfiler
* instance
= static_cast<CpuProfiler
*>(cpu_profiler
);
267 if (instance
->filter_
== NULL
||
268 (*instance
->filter_
)(instance
->filter_arg_
)) {
269 void* stack
[ProfileData::kMaxStackDepth
];
271 // The top-most active routine doesn't show up as a normal
272 // frame, but as the "pc" value in the signal handler context.
273 stack
[0] = GetPC(*reinterpret_cast<ucontext_t
*>(signal_ucontext
));
275 // We skip the top two stack trace entries (this function and one
276 // signal handler frame) since they are artifacts of profiling and
277 // should not be measured. Other profiling related frames may be
278 // removed by "pprof" at analysis time. Instead of skipping the top
279 // frames, we could skip nothing, but that would increase the
280 // profile size unnecessarily.
281 int depth
= GetStackTraceWithContext(stack
+ 1, arraysize(stack
) - 1,
283 depth
++; // To account for pc value in stack[0];
285 instance
->collector_
.Add(depth
, stack
);
289 #if !(defined(__CYGWIN__) || defined(__CYGWIN32__))
291 extern "C" PERFTOOLS_DLL_DECL
void ProfilerRegisterThread() {
292 ProfileHandlerRegisterThread();
295 extern "C" PERFTOOLS_DLL_DECL
void ProfilerFlush() {
296 CpuProfiler::instance_
.FlushTable();
299 extern "C" PERFTOOLS_DLL_DECL
int ProfilingIsEnabledForAllThreads() {
300 return CpuProfiler::instance_
.Enabled();
303 extern "C" PERFTOOLS_DLL_DECL
int ProfilerStart(const char* fname
) {
304 return CpuProfiler::instance_
.Start(fname
, NULL
);
307 extern "C" PERFTOOLS_DLL_DECL
int ProfilerStartWithOptions(
308 const char *fname
, const ProfilerOptions
*options
) {
309 return CpuProfiler::instance_
.Start(fname
, options
);
312 extern "C" PERFTOOLS_DLL_DECL
void ProfilerStop() {
313 CpuProfiler::instance_
.Stop();
316 extern "C" PERFTOOLS_DLL_DECL
void ProfilerGetCurrentState(
317 ProfilerState
* state
) {
318 CpuProfiler::instance_
.GetCurrentState(state
);
323 // ITIMER_PROF doesn't work under cygwin. ITIMER_REAL is available, but doesn't
324 // work as well for profiling, and also interferes with alarm(). Because of
325 // these issues, unless a specific need is identified, profiler support is
326 // disabled under Cygwin.
327 extern "C" void ProfilerRegisterThread() { }
328 extern "C" void ProfilerFlush() { }
329 extern "C" int ProfilingIsEnabledForAllThreads() { return 0; }
330 extern "C" int ProfilerStart(const char* fname
) { return 0; }
331 extern "C" int ProfilerStartWithOptions(const char *fname
,
332 const ProfilerOptions
*options
) {
335 extern "C" void ProfilerStop() { }
336 extern "C" void ProfilerGetCurrentState(ProfilerState
* state
) {
337 memset(state
, 0, sizeof(*state
));
342 // DEPRECATED routines
343 extern "C" PERFTOOLS_DLL_DECL
void ProfilerEnable() { }
344 extern "C" PERFTOOLS_DLL_DECL
void ProfilerDisable() { }