Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(210)

Unified Diff: third_party/tcmalloc/chromium/src/profile-handler.cc

Issue 9666033: Experiment for updating the tcmalloc chromium branch to r144 (gperftools 2.0). (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « third_party/tcmalloc/chromium/src/profile-handler.h ('k') | third_party/tcmalloc/chromium/src/profiler.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: third_party/tcmalloc/chromium/src/profile-handler.cc
diff --git a/third_party/tcmalloc/chromium/src/profile-handler.cc b/third_party/tcmalloc/chromium/src/profile-handler.cc
index 1946f7c5819cde4b7e196cbe304e96e22d1be1cc..20e5cca90cfcba984248c93968bf83e9e2d26527 100644
--- a/third_party/tcmalloc/chromium/src/profile-handler.cc
+++ b/third_party/tcmalloc/chromium/src/profile-handler.cc
@@ -46,6 +46,7 @@
#include <string>
#include "base/dynamic_annotations.h"
+#include "base/googleinit.h"
#include "base/logging.h"
#include "base/spinlock.h"
#include "maybe_threads.h"
@@ -139,6 +140,9 @@ class ProfileHandler {
// Counts the number of callbacks registered.
int32 callback_count_ GUARDED_BY(control_lock_);
+ // Is profiling allowed at all?
+ bool allowed_;
+
// Whether or not the threading system provides interval timers that are
// shared by all threads in a process.
enum {
@@ -199,6 +203,10 @@ class ProfileHandler {
// Disables (ignores) the timer interrupt signal.
void DisableHandler() EXCLUSIVE_LOCKS_REQUIRED(control_lock_);
+ // Returns true if the handler is not being used by something else.
+ // This checks the kernel's signal handler table.
+ bool IsSignalHandlerAvailable();
+
// SIGPROF/SIGALRM handler. Iterate over and call all the registered callbacks.
static void SignalHandler(int sig, siginfo_t* sinfo, void* ucontext);
@@ -239,6 +247,7 @@ ProfileHandler* ProfileHandler::Instance() {
ProfileHandler::ProfileHandler()
: interrupts_(0),
callback_count_(0),
+ allowed_(true),
timer_sharing_(TIMERS_UNTOUCHED) {
SpinLockHolder cl(&control_lock_);
@@ -255,6 +264,19 @@ ProfileHandler::ProfileHandler()
frequency_ = kDefaultFrequency;
}
+ if (!allowed_) {
+ return;
+ }
+
+ // If something else is using the signal handler,
+ // assume it has priority over us and stop.
+ if (!IsSignalHandlerAvailable()) {
+ RAW_LOG(INFO, "Disabling profiler because %s handler is already in use.",
+ timer_type_ == ITIMER_REAL ? "SIGALRM" : "SIGPROF");
+ allowed_ = false;
+ return;
+ }
+
// Ignore signals until we decide to turn profiling on. (Paranoia;
// should already be ignored.)
DisableHandler();
@@ -267,6 +289,10 @@ ProfileHandler::~ProfileHandler() {
void ProfileHandler::RegisterThread() {
SpinLockHolder cl(&control_lock_);
+ if (!allowed_) {
+ return;
+ }
+
// We try to detect whether timers are being shared by setting a
// timer in the first call to this function, then checking whether
// it's set in the second call.
@@ -312,6 +338,7 @@ void ProfileHandler::RegisterThread() {
ProfileHandlerToken* ProfileHandler::RegisterCallback(
ProfileHandlerCallback callback, void* callback_arg) {
+
ProfileHandlerToken* token = new ProfileHandlerToken(callback, callback_arg);
SpinLockHolder cl(&control_lock_);
@@ -386,9 +413,13 @@ void ProfileHandler::GetState(ProfileHandlerState* state) {
}
state->frequency = frequency_;
state->callback_count = callback_count_;
+ state->allowed = allowed_;
}
void ProfileHandler::StartTimer() {
+ if (!allowed_) {
+ return;
+ }
struct itimerval timer;
timer.it_interval.tv_sec = 0;
timer.it_interval.tv_usec = 1000000 / frequency_;
@@ -397,12 +428,18 @@ void ProfileHandler::StartTimer() {
}
void ProfileHandler::StopTimer() {
+ if (!allowed_) {
+ return;
+ }
struct itimerval timer;
memset(&timer, 0, sizeof timer);
setitimer(timer_type_, &timer, 0);
}
bool ProfileHandler::IsTimerRunning() {
+ if (!allowed_) {
+ return false;
+ }
struct itimerval current_timer;
RAW_CHECK(0 == getitimer(timer_type_, &current_timer), "getitimer");
return (current_timer.it_value.tv_sec != 0 ||
@@ -410,6 +447,9 @@ bool ProfileHandler::IsTimerRunning() {
}
void ProfileHandler::EnableHandler() {
+ if (!allowed_) {
+ return;
+ }
struct sigaction sa;
sa.sa_sigaction = SignalHandler;
sa.sa_flags = SA_RESTART | SA_SIGINFO;
@@ -419,6 +459,9 @@ void ProfileHandler::EnableHandler() {
}
void ProfileHandler::DisableHandler() {
+ if (!allowed_) {
+ return;
+ }
struct sigaction sa;
sa.sa_handler = SIG_IGN;
sa.sa_flags = SA_RESTART;
@@ -427,14 +470,33 @@ void ProfileHandler::DisableHandler() {
RAW_CHECK(sigaction(signal_number, &sa, NULL) == 0, "sigprof (disable)");
}
+bool ProfileHandler::IsSignalHandlerAvailable() {
+ struct sigaction sa;
+ const int signal_number = (timer_type_ == ITIMER_PROF ? SIGPROF : SIGALRM);
+ RAW_CHECK(sigaction(signal_number, NULL, &sa) == 0, "is-signal-handler avail");
+
+ // We only take over the handler if the current one is unset.
+ // It must be SIG_IGN or SIG_DFL, not some other function.
+ // SIG_IGN must be allowed because when profiling is allowed but
+ // not actively in use, this code keeps the handler set to SIG_IGN.
+ // That setting will be inherited across fork+exec. In order for
+ // any child to be able to use profiling, SIG_IGN must be treated
+ // as available.
+ return sa.sa_handler == SIG_IGN || sa.sa_handler == SIG_DFL;
+}
+
void ProfileHandler::SignalHandler(int sig, siginfo_t* sinfo, void* ucontext) {
int saved_errno = errno;
- RAW_CHECK(instance_ != NULL, "ProfileHandler is not initialized");
+ // At this moment, instance_ must be initialized because the handler is
+ // enabled in RegisterThread or RegisterCallback only after
+ // ProfileHandler::Instance runs.
+ ProfileHandler* instance = ANNOTATE_UNPROTECTED_READ(instance_);
+ RAW_CHECK(instance != NULL, "ProfileHandler is not initialized");
{
- SpinLockHolder sl(&instance_->signal_lock_);
- ++instance_->interrupts_;
- for (CallbackIterator it = instance_->callbacks_.begin();
- it != instance_->callbacks_.end();
+ SpinLockHolder sl(&instance->signal_lock_);
+ ++instance->interrupts_;
+ for (CallbackIterator it = instance->callbacks_.begin();
+ it != instance->callbacks_.end();
++it) {
(*it)->callback(sig, sinfo, ucontext, (*it)->callback_arg);
}
@@ -442,20 +504,9 @@ void ProfileHandler::SignalHandler(int sig, siginfo_t* sinfo, void* ucontext) {
errno = saved_errno;
}
-// The sole purpose of this class is to initialize the ProfileHandler singleton
-// when the global static objects are created. Note that the main thread will
-// be registered at this time.
-class ProfileHandlerInitializer {
- public:
- ProfileHandlerInitializer() {
- ProfileHandler::Instance()->RegisterThread();
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(ProfileHandlerInitializer);
-};
-// ProfileHandlerInitializer singleton
-static ProfileHandlerInitializer profile_handler_initializer;
+// This module initializer registers the main thread, so it must be
+// executed in the context of the main thread.
+REGISTER_MODULE_INITIALIZER(profile_main, ProfileHandlerRegisterThread());
extern "C" void ProfileHandlerRegisterThread() {
ProfileHandler::Instance()->RegisterThread();
« no previous file with comments | « third_party/tcmalloc/chromium/src/profile-handler.h ('k') | third_party/tcmalloc/chromium/src/profiler.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698