15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2005, Google Inc. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// All rights reserved. 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Redistribution and use in source and binary forms, with or without 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// modification, are permitted provided that the following conditions are 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// met: 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// * Redistributions of source code must retain the above copyright 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// notice, this list of conditions and the following disclaimer. 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// * Redistributions in binary form must reproduce the above 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// copyright notice, this list of conditions and the following disclaimer 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// in the documentation and/or other materials provided with the 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// distribution. 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// * Neither the name of Google Inc. nor the names of its 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// contributors may be used to endorse or promote products derived from 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// this software without specific prior written permission. 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// --- 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Author: Sanjay Ghemawat 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Chris Demetriou (refactoring) 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Profile current program by sampling stack-trace every so often 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "config.h" 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "getpc.h" // should be first to get the _GNU_SOURCE dfn 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <signal.h> 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <assert.h> 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdio.h> 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <errno.h> 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string.h> 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_UNISTD_H 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <unistd.h> // for getpid() 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(HAVE_SYS_UCONTEXT_H) 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/ucontext.h> 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(HAVE_UCONTEXT_H) 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <ucontext.h> 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(HAVE_CYGWIN_SIGNAL_H) 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <cygwin/signal.h> 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef ucontext ucontext_t; 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef int ucontext_t; // just to quiet the compiler, mostly 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/time.h> 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string> 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <gperftools/profiler.h> 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <gperftools/stacktrace.h> 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/commandlineflags.h" 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/googleinit.h" 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/spinlock.h" 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/sysinfo.h" /* for GetUniquePathFromEnv, etc */ 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "profiledata.h" 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "profile-handler.h" 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_CONFLICT_SIGNAL_H 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "conflict-signal.h" /* used on msvc machines */ 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using std::string; 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Collects up all profile data. This is a singleton, which is 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// initialized by a constructor at startup. 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class CpuProfiler { 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CpuProfiler(); 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ~CpuProfiler(); 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Start profiler to write profile info into fname 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool Start(const char* fname, const ProfilerOptions* options); 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Stop profiling and write the data to disk. 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Stop(); 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Write the data to disk (and continue profiling). 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void FlushTable(); 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool Enabled(); 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void GetCurrentState(ProfilerState* state); 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static CpuProfiler instance_; 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This lock implements the locking requirements described in the ProfileData 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // documentation, specifically: 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // lock_ is held all over all collector_ method calls except for the 'Add' 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // call made from the signal handler, to protect against concurrent use of 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // collector_'s control routines. Code other than signal handler must 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // unregister the signal handler before calling any collector_ method. 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 'Add' method in the collector is protected by a guarantee from 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ProfileHandle that only one instance of prof_handler can run at a time. 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SpinLock lock_; 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProfileData collector_; 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Filter function and its argument, if any. (NULL means include all 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // samples). Set at start, read-only while running. Written while holding 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // lock_, read and executed in the context of SIGPROF interrupt. 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int (*filter_)(void*); 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* filter_arg_; 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Opaque token returned by the profile handler. To be used when calling 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ProfileHandlerUnregisterCallback. 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProfileHandlerToken* prof_handler_token_; 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Sets up a callback to receive SIGPROF interrupt. 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void EnableHandler(); 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Disables receiving SIGPROF interrupt. 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void DisableHandler(); 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Signal handler that records the interrupted pc in the profile data. 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static void prof_handler(int sig, siginfo_t*, void* signal_ucontext, 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* cpu_profiler); 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Profile data structure singleton: Constructor will check to see if 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// profiling should be enabled. Destructor will write profile data 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// out to disk. 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CpuProfiler CpuProfiler::instance_; 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Initialize profiling: activated if getenv("CPUPROFILE") exists. 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CpuProfiler::CpuProfiler() 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : prof_handler_token_(NULL) { 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(cgd) Move this code *out* of the CpuProfile constructor into a 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // separate object responsible for initialization. With ProfileHandler there 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // is no need to limit the number of profilers. 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char fname[PATH_MAX]; 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!GetUniquePathFromEnv("CPUPROFILE", fname)) { 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We don't enable profiling if setuid -- it's a security risk 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_GETEUID 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (getuid() != geteuid()) 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!Start(fname, NULL)) { 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_LOG(FATAL, "Can't turn on cpu profiling for '%s': %s\n", 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fname, strerror(errno)); 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CpuProfiler::Start(const char* fname, const ProfilerOptions* options) { 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SpinLockHolder cl(&lock_); 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (collector_.enabled()) { 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProfileHandlerState prof_handler_state; 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProfileHandlerGetState(&prof_handler_state); 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProfileData::Options collector_options; 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) collector_options.set_frequency(prof_handler_state.frequency); 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!collector_.Start(fname, collector_options)) { 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) filter_ = NULL; 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (options != NULL && options->filter_in_thread != NULL) { 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) filter_ = options->filter_in_thread; 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) filter_arg_ = options->filter_in_thread_arg; 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Setup handler for SIGPROF interrupts 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnableHandler(); 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CpuProfiler::~CpuProfiler() { 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Stop(); 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Stop profiling and write out any collected profile data 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CpuProfiler::Stop() { 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SpinLockHolder cl(&lock_); 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!collector_.enabled()) { 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Unregister prof_handler to stop receiving SIGPROF interrupts before 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // stopping the collector. 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DisableHandler(); 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // DisableHandler waits for the currently running callback to complete and 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // guarantees no future invocations. It is safe to stop the collector. 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) collector_.Stop(); 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CpuProfiler::FlushTable() { 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SpinLockHolder cl(&lock_); 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!collector_.enabled()) { 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Unregister prof_handler to stop receiving SIGPROF interrupts before 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // flushing the profile data. 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DisableHandler(); 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // DisableHandler waits for the currently running callback to complete and 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // guarantees no future invocations. It is safe to flush the profile data. 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) collector_.FlushTable(); 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnableHandler(); 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CpuProfiler::Enabled() { 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SpinLockHolder cl(&lock_); 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return collector_.enabled(); 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CpuProfiler::GetCurrentState(ProfilerState* state) { 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProfileData::State collector_state; 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SpinLockHolder cl(&lock_); 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) collector_.GetCurrentState(&collector_state); 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) state->enabled = collector_state.enabled; 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) state->start_time = static_cast<time_t>(collector_state.start_time); 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) state->samples_gathered = collector_state.samples_gathered; 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int buf_size = sizeof(state->profile_name); 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) strncpy(state->profile_name, collector_state.profile_name, buf_size); 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) state->profile_name[buf_size-1] = '\0'; 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CpuProfiler::EnableHandler() { 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_CHECK(prof_handler_token_ == NULL, "SIGPROF handler already registered"); 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) prof_handler_token_ = ProfileHandlerRegisterCallback(prof_handler, this); 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_CHECK(prof_handler_token_ != NULL, "Failed to set up SIGPROF handler"); 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CpuProfiler::DisableHandler() { 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_CHECK(prof_handler_token_ != NULL, "SIGPROF handler is not registered"); 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProfileHandlerUnregisterCallback(prof_handler_token_); 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) prof_handler_token_ = NULL; 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Signal handler that records the pc in the profile-data structure. We do no 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// synchronization here. profile-handler.cc guarantees that at most one 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// instance of prof_handler() will run at a time. All other routines that 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// access the data touched by prof_handler() disable this signal handler before 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// accessing the data and therefore cannot execute concurrently with 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// prof_handler(). 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CpuProfiler::prof_handler(int sig, siginfo_t*, void* signal_ucontext, 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* cpu_profiler) { 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CpuProfiler* instance = static_cast<CpuProfiler*>(cpu_profiler); 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (instance->filter_ == NULL || 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*instance->filter_)(instance->filter_arg_)) { 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* stack[ProfileData::kMaxStackDepth]; 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The top-most active routine doesn't show up as a normal 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // frame, but as the "pc" value in the signal handler context. 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stack[0] = GetPC(*reinterpret_cast<ucontext_t*>(signal_ucontext)); 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We skip the top two stack trace entries (this function and one 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // signal handler frame) since they are artifacts of profiling and 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // should not be measured. Other profiling related frames may be 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // removed by "pprof" at analysis time. Instead of skipping the top 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // frames, we could skip nothing, but that would increase the 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // profile size unnecessarily. 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int depth = GetStackTraceWithContext(stack + 1, arraysize(stack) - 1, 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2, signal_ucontext); 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) depth++; // To account for pc value in stack[0]; 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) instance->collector_.Add(depth, stack); 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !(defined(__CYGWIN__) || defined(__CYGWIN32__)) 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern "C" PERFTOOLS_DLL_DECL void ProfilerRegisterThread() { 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProfileHandlerRegisterThread(); 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern "C" PERFTOOLS_DLL_DECL void ProfilerFlush() { 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CpuProfiler::instance_.FlushTable(); 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern "C" PERFTOOLS_DLL_DECL int ProfilingIsEnabledForAllThreads() { 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return CpuProfiler::instance_.Enabled(); 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern "C" PERFTOOLS_DLL_DECL int ProfilerStart(const char* fname) { 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return CpuProfiler::instance_.Start(fname, NULL); 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern "C" PERFTOOLS_DLL_DECL int ProfilerStartWithOptions( 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char *fname, const ProfilerOptions *options) { 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return CpuProfiler::instance_.Start(fname, options); 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern "C" PERFTOOLS_DLL_DECL void ProfilerStop() { 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CpuProfiler::instance_.Stop(); 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern "C" PERFTOOLS_DLL_DECL void ProfilerGetCurrentState( 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProfilerState* state) { 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CpuProfiler::instance_.GetCurrentState(state); 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else // OS_CYGWIN 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ITIMER_PROF doesn't work under cygwin. ITIMER_REAL is available, but doesn't 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// work as well for profiling, and also interferes with alarm(). Because of 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// these issues, unless a specific need is identified, profiler support is 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// disabled under Cygwin. 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern "C" void ProfilerRegisterThread() { } 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern "C" void ProfilerFlush() { } 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern "C" int ProfilingIsEnabledForAllThreads() { return 0; } 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern "C" int ProfilerStart(const char* fname) { return 0; } 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern "C" int ProfilerStartWithOptions(const char *fname, 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ProfilerOptions *options) { 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern "C" void ProfilerStop() { } 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern "C" void ProfilerGetCurrentState(ProfilerState* state) { 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(state, 0, sizeof(*state)); 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // OS_CYGWIN 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// DEPRECATED routines 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern "C" PERFTOOLS_DLL_DECL void ProfilerEnable() { } 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern "C" PERFTOOLS_DLL_DECL void ProfilerDisable() { } 343