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

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

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