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

Side by Side 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2009, Google Inc. 1 // Copyright (c) 2009, Google Inc.
2 // All rights reserved. 2 // All rights reserved.
3 // 3 //
4 // Redistribution and use in source and binary forms, with or without 4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are 5 // modification, are permitted provided that the following conditions are
6 // met: 6 // met:
7 // 7 //
8 // * Redistributions of source code must retain the above copyright 8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer. 9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above 10 // * Redistributions in binary form must reproduce the above
(...skipping 28 matching lines...) Expand all
39 #if !(defined(__CYGWIN__) || defined(__CYGWIN32__)) 39 #if !(defined(__CYGWIN__) || defined(__CYGWIN32__))
40 40
41 #include <stdio.h> 41 #include <stdio.h>
42 #include <errno.h> 42 #include <errno.h>
43 #include <sys/time.h> 43 #include <sys/time.h>
44 44
45 #include <list> 45 #include <list>
46 #include <string> 46 #include <string>
47 47
48 #include "base/dynamic_annotations.h" 48 #include "base/dynamic_annotations.h"
49 #include "base/googleinit.h"
49 #include "base/logging.h" 50 #include "base/logging.h"
50 #include "base/spinlock.h" 51 #include "base/spinlock.h"
51 #include "maybe_threads.h" 52 #include "maybe_threads.h"
52 53
53 using std::list; 54 using std::list;
54 using std::string; 55 using std::string;
55 56
56 // This structure is used by ProfileHandlerRegisterCallback and 57 // This structure is used by ProfileHandlerRegisterCallback and
57 // ProfileHandlerUnregisterCallback as a handle to a registered callback. 58 // ProfileHandlerUnregisterCallback as a handle to a registered callback.
58 struct ProfileHandlerToken { 59 struct ProfileHandlerToken {
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
132 133
133 // SIGPROF/SIGALRM interrupt frequency, read-only after construction. 134 // SIGPROF/SIGALRM interrupt frequency, read-only after construction.
134 int32 frequency_; 135 int32 frequency_;
135 136
136 // ITIMER_PROF (which uses SIGPROF), or ITIMER_REAL (which uses SIGALRM) 137 // ITIMER_PROF (which uses SIGPROF), or ITIMER_REAL (which uses SIGALRM)
137 int timer_type_; 138 int timer_type_;
138 139
139 // Counts the number of callbacks registered. 140 // Counts the number of callbacks registered.
140 int32 callback_count_ GUARDED_BY(control_lock_); 141 int32 callback_count_ GUARDED_BY(control_lock_);
141 142
143 // Is profiling allowed at all?
144 bool allowed_;
145
142 // Whether or not the threading system provides interval timers that are 146 // Whether or not the threading system provides interval timers that are
143 // shared by all threads in a process. 147 // shared by all threads in a process.
144 enum { 148 enum {
145 // No timer initialization attempted yet. 149 // No timer initialization attempted yet.
146 TIMERS_UNTOUCHED, 150 TIMERS_UNTOUCHED,
147 // First thread has registered and set timer. 151 // First thread has registered and set timer.
148 TIMERS_ONE_SET, 152 TIMERS_ONE_SET,
149 // Timers are shared by all threads. 153 // Timers are shared by all threads.
150 TIMERS_SHARED, 154 TIMERS_SHARED,
151 // Timers are separate in each thread. 155 // Timers are separate in each thread.
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
192 // thread. This actually checks the kernel's interval timer setting. (It is 196 // thread. This actually checks the kernel's interval timer setting. (It is
193 // used to detect whether timers are shared or separate.) 197 // used to detect whether timers are shared or separate.)
194 bool IsTimerRunning() EXCLUSIVE_LOCKS_REQUIRED(control_lock_); 198 bool IsTimerRunning() EXCLUSIVE_LOCKS_REQUIRED(control_lock_);
195 199
196 // Sets the timer interrupt signal handler. 200 // Sets the timer interrupt signal handler.
197 void EnableHandler() EXCLUSIVE_LOCKS_REQUIRED(control_lock_); 201 void EnableHandler() EXCLUSIVE_LOCKS_REQUIRED(control_lock_);
198 202
199 // Disables (ignores) the timer interrupt signal. 203 // Disables (ignores) the timer interrupt signal.
200 void DisableHandler() EXCLUSIVE_LOCKS_REQUIRED(control_lock_); 204 void DisableHandler() EXCLUSIVE_LOCKS_REQUIRED(control_lock_);
201 205
206 // Returns true if the handler is not being used by something else.
207 // This checks the kernel's signal handler table.
208 bool IsSignalHandlerAvailable();
209
202 // SIGPROF/SIGALRM handler. Iterate over and call all the registered callbacks . 210 // SIGPROF/SIGALRM handler. Iterate over and call all the registered callbacks .
203 static void SignalHandler(int sig, siginfo_t* sinfo, void* ucontext); 211 static void SignalHandler(int sig, siginfo_t* sinfo, void* ucontext);
204 212
205 DISALLOW_COPY_AND_ASSIGN(ProfileHandler); 213 DISALLOW_COPY_AND_ASSIGN(ProfileHandler);
206 }; 214 };
207 215
208 ProfileHandler* ProfileHandler::instance_ = NULL; 216 ProfileHandler* ProfileHandler::instance_ = NULL;
209 pthread_once_t ProfileHandler::once_ = PTHREAD_ONCE_INIT; 217 pthread_once_t ProfileHandler::once_ = PTHREAD_ONCE_INIT;
210 218
211 const int32 ProfileHandler::kMaxFrequency; 219 const int32 ProfileHandler::kMaxFrequency;
(...skipping 20 matching lines...) Expand all
232 // (but doesn't do anything) even when pthreads isn't linked in. 240 // (but doesn't do anything) even when pthreads isn't linked in.
233 Init(); 241 Init();
234 assert(instance_ != NULL); 242 assert(instance_ != NULL);
235 } 243 }
236 return instance_; 244 return instance_;
237 } 245 }
238 246
239 ProfileHandler::ProfileHandler() 247 ProfileHandler::ProfileHandler()
240 : interrupts_(0), 248 : interrupts_(0),
241 callback_count_(0), 249 callback_count_(0),
250 allowed_(true),
242 timer_sharing_(TIMERS_UNTOUCHED) { 251 timer_sharing_(TIMERS_UNTOUCHED) {
243 SpinLockHolder cl(&control_lock_); 252 SpinLockHolder cl(&control_lock_);
244 253
245 timer_type_ = (getenv("CPUPROFILE_REALTIME") ? ITIMER_REAL : ITIMER_PROF); 254 timer_type_ = (getenv("CPUPROFILE_REALTIME") ? ITIMER_REAL : ITIMER_PROF);
246 255
247 // Get frequency of interrupts (if specified) 256 // Get frequency of interrupts (if specified)
248 char junk; 257 char junk;
249 const char* fr = getenv("CPUPROFILE_FREQUENCY"); 258 const char* fr = getenv("CPUPROFILE_FREQUENCY");
250 if (fr != NULL && (sscanf(fr, "%u%c", &frequency_, &junk) == 1) && 259 if (fr != NULL && (sscanf(fr, "%u%c", &frequency_, &junk) == 1) &&
251 (frequency_ > 0)) { 260 (frequency_ > 0)) {
252 // Limit to kMaxFrequency 261 // Limit to kMaxFrequency
253 frequency_ = (frequency_ > kMaxFrequency) ? kMaxFrequency : frequency_; 262 frequency_ = (frequency_ > kMaxFrequency) ? kMaxFrequency : frequency_;
254 } else { 263 } else {
255 frequency_ = kDefaultFrequency; 264 frequency_ = kDefaultFrequency;
256 } 265 }
257 266
267 if (!allowed_) {
268 return;
269 }
270
271 // If something else is using the signal handler,
272 // assume it has priority over us and stop.
273 if (!IsSignalHandlerAvailable()) {
274 RAW_LOG(INFO, "Disabling profiler because %s handler is already in use.",
275 timer_type_ == ITIMER_REAL ? "SIGALRM" : "SIGPROF");
276 allowed_ = false;
277 return;
278 }
279
258 // Ignore signals until we decide to turn profiling on. (Paranoia; 280 // Ignore signals until we decide to turn profiling on. (Paranoia;
259 // should already be ignored.) 281 // should already be ignored.)
260 DisableHandler(); 282 DisableHandler();
261 } 283 }
262 284
263 ProfileHandler::~ProfileHandler() { 285 ProfileHandler::~ProfileHandler() {
264 Reset(); 286 Reset();
265 } 287 }
266 288
267 void ProfileHandler::RegisterThread() { 289 void ProfileHandler::RegisterThread() {
268 SpinLockHolder cl(&control_lock_); 290 SpinLockHolder cl(&control_lock_);
269 291
292 if (!allowed_) {
293 return;
294 }
295
270 // We try to detect whether timers are being shared by setting a 296 // We try to detect whether timers are being shared by setting a
271 // timer in the first call to this function, then checking whether 297 // timer in the first call to this function, then checking whether
272 // it's set in the second call. 298 // it's set in the second call.
273 // 299 //
274 // Note that this detection method requires that the first two calls 300 // Note that this detection method requires that the first two calls
275 // to RegisterThread must be made from different threads. (Subsequent 301 // to RegisterThread must be made from different threads. (Subsequent
276 // calls will see timer_sharing_ set to either TIMERS_SEPARATE or 302 // calls will see timer_sharing_ set to either TIMERS_SEPARATE or
277 // TIMERS_SHARED, and won't try to detect the timer sharing type.) 303 // TIMERS_SHARED, and won't try to detect the timer sharing type.)
278 // 304 //
279 // Also note that if timer settings were inherited across new thread 305 // Also note that if timer settings were inherited across new thread
(...skipping 25 matching lines...) Expand all
305 // Nothing needed. 331 // Nothing needed.
306 break; 332 break;
307 case TIMERS_SEPARATE: 333 case TIMERS_SEPARATE:
308 StartTimer(); 334 StartTimer();
309 break; 335 break;
310 } 336 }
311 } 337 }
312 338
313 ProfileHandlerToken* ProfileHandler::RegisterCallback( 339 ProfileHandlerToken* ProfileHandler::RegisterCallback(
314 ProfileHandlerCallback callback, void* callback_arg) { 340 ProfileHandlerCallback callback, void* callback_arg) {
341
315 ProfileHandlerToken* token = new ProfileHandlerToken(callback, callback_arg); 342 ProfileHandlerToken* token = new ProfileHandlerToken(callback, callback_arg);
316 343
317 SpinLockHolder cl(&control_lock_); 344 SpinLockHolder cl(&control_lock_);
318 DisableHandler(); 345 DisableHandler();
319 { 346 {
320 SpinLockHolder sl(&signal_lock_); 347 SpinLockHolder sl(&signal_lock_);
321 callbacks_.push_back(token); 348 callbacks_.push_back(token);
322 } 349 }
323 // Start the timer if timer is shared and this is a first callback. 350 // Start the timer if timer is shared and this is a first callback.
324 if ((callback_count_ == 0) && (timer_sharing_ == TIMERS_SHARED)) { 351 if ((callback_count_ == 0) && (timer_sharing_ == TIMERS_SHARED)) {
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
379 DisableHandler(); 406 DisableHandler();
380 { 407 {
381 SpinLockHolder sl(&signal_lock_); // Protects interrupts_. 408 SpinLockHolder sl(&signal_lock_); // Protects interrupts_.
382 state->interrupts = interrupts_; 409 state->interrupts = interrupts_;
383 } 410 }
384 if (callback_count_ > 0) { 411 if (callback_count_ > 0) {
385 EnableHandler(); 412 EnableHandler();
386 } 413 }
387 state->frequency = frequency_; 414 state->frequency = frequency_;
388 state->callback_count = callback_count_; 415 state->callback_count = callback_count_;
416 state->allowed = allowed_;
389 } 417 }
390 418
391 void ProfileHandler::StartTimer() { 419 void ProfileHandler::StartTimer() {
420 if (!allowed_) {
421 return;
422 }
392 struct itimerval timer; 423 struct itimerval timer;
393 timer.it_interval.tv_sec = 0; 424 timer.it_interval.tv_sec = 0;
394 timer.it_interval.tv_usec = 1000000 / frequency_; 425 timer.it_interval.tv_usec = 1000000 / frequency_;
395 timer.it_value = timer.it_interval; 426 timer.it_value = timer.it_interval;
396 setitimer(timer_type_, &timer, 0); 427 setitimer(timer_type_, &timer, 0);
397 } 428 }
398 429
399 void ProfileHandler::StopTimer() { 430 void ProfileHandler::StopTimer() {
431 if (!allowed_) {
432 return;
433 }
400 struct itimerval timer; 434 struct itimerval timer;
401 memset(&timer, 0, sizeof timer); 435 memset(&timer, 0, sizeof timer);
402 setitimer(timer_type_, &timer, 0); 436 setitimer(timer_type_, &timer, 0);
403 } 437 }
404 438
405 bool ProfileHandler::IsTimerRunning() { 439 bool ProfileHandler::IsTimerRunning() {
440 if (!allowed_) {
441 return false;
442 }
406 struct itimerval current_timer; 443 struct itimerval current_timer;
407 RAW_CHECK(0 == getitimer(timer_type_, &current_timer), "getitimer"); 444 RAW_CHECK(0 == getitimer(timer_type_, &current_timer), "getitimer");
408 return (current_timer.it_value.tv_sec != 0 || 445 return (current_timer.it_value.tv_sec != 0 ||
409 current_timer.it_value.tv_usec != 0); 446 current_timer.it_value.tv_usec != 0);
410 } 447 }
411 448
412 void ProfileHandler::EnableHandler() { 449 void ProfileHandler::EnableHandler() {
450 if (!allowed_) {
451 return;
452 }
413 struct sigaction sa; 453 struct sigaction sa;
414 sa.sa_sigaction = SignalHandler; 454 sa.sa_sigaction = SignalHandler;
415 sa.sa_flags = SA_RESTART | SA_SIGINFO; 455 sa.sa_flags = SA_RESTART | SA_SIGINFO;
416 sigemptyset(&sa.sa_mask); 456 sigemptyset(&sa.sa_mask);
417 const int signal_number = (timer_type_ == ITIMER_PROF ? SIGPROF : SIGALRM); 457 const int signal_number = (timer_type_ == ITIMER_PROF ? SIGPROF : SIGALRM);
418 RAW_CHECK(sigaction(signal_number, &sa, NULL) == 0, "sigprof (enable)"); 458 RAW_CHECK(sigaction(signal_number, &sa, NULL) == 0, "sigprof (enable)");
419 } 459 }
420 460
421 void ProfileHandler::DisableHandler() { 461 void ProfileHandler::DisableHandler() {
462 if (!allowed_) {
463 return;
464 }
422 struct sigaction sa; 465 struct sigaction sa;
423 sa.sa_handler = SIG_IGN; 466 sa.sa_handler = SIG_IGN;
424 sa.sa_flags = SA_RESTART; 467 sa.sa_flags = SA_RESTART;
425 sigemptyset(&sa.sa_mask); 468 sigemptyset(&sa.sa_mask);
426 const int signal_number = (timer_type_ == ITIMER_PROF ? SIGPROF : SIGALRM); 469 const int signal_number = (timer_type_ == ITIMER_PROF ? SIGPROF : SIGALRM);
427 RAW_CHECK(sigaction(signal_number, &sa, NULL) == 0, "sigprof (disable)"); 470 RAW_CHECK(sigaction(signal_number, &sa, NULL) == 0, "sigprof (disable)");
428 } 471 }
429 472
473 bool ProfileHandler::IsSignalHandlerAvailable() {
474 struct sigaction sa;
475 const int signal_number = (timer_type_ == ITIMER_PROF ? SIGPROF : SIGALRM);
476 RAW_CHECK(sigaction(signal_number, NULL, &sa) == 0, "is-signal-handler avail") ;
477
478 // We only take over the handler if the current one is unset.
479 // It must be SIG_IGN or SIG_DFL, not some other function.
480 // SIG_IGN must be allowed because when profiling is allowed but
481 // not actively in use, this code keeps the handler set to SIG_IGN.
482 // That setting will be inherited across fork+exec. In order for
483 // any child to be able to use profiling, SIG_IGN must be treated
484 // as available.
485 return sa.sa_handler == SIG_IGN || sa.sa_handler == SIG_DFL;
486 }
487
430 void ProfileHandler::SignalHandler(int sig, siginfo_t* sinfo, void* ucontext) { 488 void ProfileHandler::SignalHandler(int sig, siginfo_t* sinfo, void* ucontext) {
431 int saved_errno = errno; 489 int saved_errno = errno;
432 RAW_CHECK(instance_ != NULL, "ProfileHandler is not initialized"); 490 // At this moment, instance_ must be initialized because the handler is
491 // enabled in RegisterThread or RegisterCallback only after
492 // ProfileHandler::Instance runs.
493 ProfileHandler* instance = ANNOTATE_UNPROTECTED_READ(instance_);
494 RAW_CHECK(instance != NULL, "ProfileHandler is not initialized");
433 { 495 {
434 SpinLockHolder sl(&instance_->signal_lock_); 496 SpinLockHolder sl(&instance->signal_lock_);
435 ++instance_->interrupts_; 497 ++instance->interrupts_;
436 for (CallbackIterator it = instance_->callbacks_.begin(); 498 for (CallbackIterator it = instance->callbacks_.begin();
437 it != instance_->callbacks_.end(); 499 it != instance->callbacks_.end();
438 ++it) { 500 ++it) {
439 (*it)->callback(sig, sinfo, ucontext, (*it)->callback_arg); 501 (*it)->callback(sig, sinfo, ucontext, (*it)->callback_arg);
440 } 502 }
441 } 503 }
442 errno = saved_errno; 504 errno = saved_errno;
443 } 505 }
444 506
445 // The sole purpose of this class is to initialize the ProfileHandler singleton 507 // This module initializer registers the main thread, so it must be
446 // when the global static objects are created. Note that the main thread will 508 // executed in the context of the main thread.
447 // be registered at this time. 509 REGISTER_MODULE_INITIALIZER(profile_main, ProfileHandlerRegisterThread());
448 class ProfileHandlerInitializer {
449 public:
450 ProfileHandlerInitializer() {
451 ProfileHandler::Instance()->RegisterThread();
452 }
453
454 private:
455 DISALLOW_COPY_AND_ASSIGN(ProfileHandlerInitializer);
456 };
457 // ProfileHandlerInitializer singleton
458 static ProfileHandlerInitializer profile_handler_initializer;
459 510
460 extern "C" void ProfileHandlerRegisterThread() { 511 extern "C" void ProfileHandlerRegisterThread() {
461 ProfileHandler::Instance()->RegisterThread(); 512 ProfileHandler::Instance()->RegisterThread();
462 } 513 }
463 514
464 extern "C" ProfileHandlerToken* ProfileHandlerRegisterCallback( 515 extern "C" ProfileHandlerToken* ProfileHandlerRegisterCallback(
465 ProfileHandlerCallback callback, void* callback_arg) { 516 ProfileHandlerCallback callback, void* callback_arg) {
466 return ProfileHandler::Instance()->RegisterCallback(callback, callback_arg); 517 return ProfileHandler::Instance()->RegisterCallback(callback, callback_arg);
467 } 518 }
468 519
(...skipping 26 matching lines...) Expand all
495 extern "C" void ProfileHandlerUnregisterCallback(ProfileHandlerToken* token) { 546 extern "C" void ProfileHandlerUnregisterCallback(ProfileHandlerToken* token) {
496 } 547 }
497 548
498 extern "C" void ProfileHandlerReset() { 549 extern "C" void ProfileHandlerReset() {
499 } 550 }
500 551
501 extern "C" void ProfileHandlerGetState(ProfileHandlerState* state) { 552 extern "C" void ProfileHandlerGetState(ProfileHandlerState* state) {
502 } 553 }
503 554
504 #endif // OS_CYGWIN 555 #endif // OS_CYGWIN
OLDNEW
« 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