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

Side by Side Diff: src/platform-macos.cc

Issue 147150: Reimplement profiler sampler on Mac OS X to get it working under Chromium. (Closed)
Patch Set: moved thread resuming and got rid of thread_suspended flag Created 11 years, 5 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
« no previous file with comments | « src/platform-linux.cc ('k') | src/platform-win32.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. 1 // Copyright 2006-2008 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 20 matching lines...) Expand all
31 #include <ucontext.h> 31 #include <ucontext.h>
32 #include <unistd.h> 32 #include <unistd.h>
33 #include <sys/mman.h> 33 #include <sys/mman.h>
34 #include <mach/mach_init.h> 34 #include <mach/mach_init.h>
35 35
36 #include <AvailabilityMacros.h> 36 #include <AvailabilityMacros.h>
37 37
38 #include <pthread.h> 38 #include <pthread.h>
39 #include <semaphore.h> 39 #include <semaphore.h>
40 #include <signal.h> 40 #include <signal.h>
41 #include <mach/mach.h>
41 #include <mach/semaphore.h> 42 #include <mach/semaphore.h>
42 #include <mach/task.h> 43 #include <mach/task.h>
43 #include <sys/time.h> 44 #include <sys/time.h>
44 #include <sys/resource.h> 45 #include <sys/resource.h>
45 #include <sys/types.h> 46 #include <sys/types.h>
46 #include <stdarg.h> 47 #include <stdarg.h>
47 #include <stdlib.h> 48 #include <stdlib.h>
48 49
49 #include <errno.h> 50 #include <errno.h>
50 51
(...skipping 417 matching lines...) Expand 10 before | Expand all | Expand 10 after
468 } 469 }
469 470
470 471
471 Semaphore* OS::CreateSemaphore(int count) { 472 Semaphore* OS::CreateSemaphore(int count) {
472 return new MacOSSemaphore(count); 473 return new MacOSSemaphore(count);
473 } 474 }
474 475
475 476
476 #ifdef ENABLE_LOGGING_AND_PROFILING 477 #ifdef ENABLE_LOGGING_AND_PROFILING
477 478
478 static Sampler* active_sampler_ = NULL; 479 class Sampler::PlatformData : public Malloced {
480 public:
481 explicit PlatformData(Sampler* sampler)
482 : sampler_(sampler),
483 task_self_(mach_task_self()),
484 profiled_thread_(0),
485 sampler_thread_(0) {
486 }
479 487
480 static void ProfilerSignalHandler(int signal, siginfo_t* info, void* context) { 488 Sampler* sampler_;
481 USE(info); 489 // Note: for profiled_thread_ Mach primitives are used instead of PThread's
482 if (signal != SIGPROF) return; 490 // because the latter doesn't provide thread manipulation primitives required.
483 if (active_sampler_ == NULL) return; 491 // For details, consult "Mac OS X Internals" book, Section 7.3.
492 mach_port_t task_self_;
493 thread_act_t profiled_thread_;
494 pthread_t sampler_thread_;
484 495
485 TickSample sample; 496 // Sampler thread handler.
497 void Runner() {
498 // Loop until the sampler is disengaged.
499 while (sampler_->IsActive()) {
500 TickSample sample;
486 501
487 // If profiling, we extract the current pc and sp. 502 // If profiling, we record the pc and sp of the profiled thread.
488 if (active_sampler_->IsProfiling()) { 503 if (sampler_->IsProfiling()
489 // Extracting the sample from the context is extremely machine dependent. 504 && KERN_SUCCESS == thread_suspend(profiled_thread_)) {
490 ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context);
491 mcontext_t& mcontext = ucontext->uc_mcontext;
492 #if V8_HOST_ARCH_X64 505 #if V8_HOST_ARCH_X64
493 UNIMPLEMENTED(); 506 thread_state_flavor_t flavor = x86_THREAD_STATE64;
494 USE(mcontext); 507 x86_thread_state64_t state;
495 sample.pc = 0; 508 mach_msg_type_number_t count = x86_THREAD_STATE64_COUNT;
496 sample.sp = 0; 509 #elif V8_HOST_ARCH_IA32
497 sample.fp = 0; 510 thread_state_flavor_t flavor = i386_THREAD_STATE;
511 i386_thread_state_t state;
512 mach_msg_type_number_t count = i386_THREAD_STATE_COUNT;
513 #else
514 #error Unsupported Mac OS X host architecture.
515 #endif // V8_TARGET_ARCH_IA32
516 if (KERN_SUCCESS == thread_get_state(profiled_thread_,
517 flavor,
518 (natural_t*)&state,
519 &count)) {
520 #if V8_HOST_ARCH_X64
521 UNIMPLEMENTED();
522 sample.pc = 0;
523 sample.sp = 0;
524 sample.fp = 0;
498 #elif V8_HOST_ARCH_IA32 525 #elif V8_HOST_ARCH_IA32
499 #if __DARWIN_UNIX03 526 #if __DARWIN_UNIX03
500 sample.pc = mcontext->__ss.__eip; 527 sample.pc = state.__eip;
501 sample.sp = mcontext->__ss.__esp; 528 sample.sp = state.__esp;
502 sample.fp = mcontext->__ss.__ebp; 529 sample.fp = state.__ebp;
503 #else // !__DARWIN_UNIX03 530 #else // !__DARWIN_UNIX03
504 sample.pc = mcontext->ss.eip; 531 sample.pc = state.eip;
505 sample.sp = mcontext->ss.esp; 532 sample.sp = state.esp;
506 sample.fp = mcontext->ss.ebp; 533 sample.fp = state.ebp;
507 #endif // __DARWIN_UNIX03 534 #endif // __DARWIN_UNIX03
508 #else 535 #else
509 #error Unsupported Mac OS X host architecture. 536 #error Unsupported Mac OS X host architecture.
510 #endif // V8_HOST_ARCH_IA32 537 #endif // V8_HOST_ARCH_IA32
538 sampler_->SampleStack(&sample);
539 }
540 thread_resume(profiled_thread_);
541 }
542
543 // We always sample the VM state.
544 sample.state = Logger::state();
545 // Invoke tick handler with program counter and stack pointer.
546 sampler_->Tick(&sample);
547
548 // Wait until next sampling.
549 usleep(sampler_->interval_ * 1000);
550 }
511 } 551 }
512 552 };
513 // We always sample the VM state.
514 sample.state = Logger::state();
515
516 active_sampler_->Tick(&sample);
517 }
518 553
519 554
520 class Sampler::PlatformData : public Malloced { 555 // Entry point for sampler thread.
521 public: 556 static void* SamplerEntry(void* arg) {
522 PlatformData() { 557 Sampler::PlatformData* data =
523 signal_handler_installed_ = false; 558 reinterpret_cast<Sampler::PlatformData*>(arg);
524 } 559 data->Runner();
525 560 return 0;
526 bool signal_handler_installed_; 561 }
527 struct sigaction old_signal_handler_;
528 struct itimerval old_timer_value_;
529 };
530 562
531 563
532 Sampler::Sampler(int interval, bool profiling) 564 Sampler::Sampler(int interval, bool profiling)
533 : interval_(interval), profiling_(profiling), active_(false) { 565 : interval_(interval), profiling_(profiling), active_(false) {
534 data_ = new PlatformData(); 566 data_ = new PlatformData(this);
535 } 567 }
536 568
537 569
538 Sampler::~Sampler() { 570 Sampler::~Sampler() {
539 delete data_; 571 delete data_;
540 } 572 }
541 573
542 574
543 void Sampler::Start() { 575 void Sampler::Start() {
544 // There can only be one active sampler at the time on POSIX 576 // If we are profiling, we need to be able to access the calling
545 // platforms. 577 // thread.
546 if (active_sampler_ != NULL) return; 578 if (IsProfiling()) {
579 data_->profiled_thread_ = mach_thread_self();
580 }
547 581
548 // Request profiling signals. 582 // Create sampler thread with high priority.
549 struct sigaction sa; 583 // According to POSIX spec, when SCHED_FIFO policy is used, a thread
550 sa.sa_sigaction = ProfilerSignalHandler; 584 // runs until it exits or blocks.
551 sigemptyset(&sa.sa_mask); 585 pthread_attr_t sched_attr;
552 sa.sa_flags = SA_SIGINFO; 586 sched_param fifo_param;
553 if (sigaction(SIGPROF, &sa, &data_->old_signal_handler_) != 0) return; 587 pthread_attr_init(&sched_attr);
554 data_->signal_handler_installed_ = true; 588 pthread_attr_setinheritsched(&sched_attr, PTHREAD_EXPLICIT_SCHED);
589 pthread_attr_setschedpolicy(&sched_attr, SCHED_FIFO);
590 fifo_param.sched_priority = sched_get_priority_max(SCHED_FIFO);
591 pthread_attr_setschedparam(&sched_attr, &fifo_param);
555 592
556 // Set the itimer to generate a tick for each interval.
557 itimerval itimer;
558 itimer.it_interval.tv_sec = interval_ / 1000;
559 itimer.it_interval.tv_usec = (interval_ % 1000) * 1000;
560 itimer.it_value.tv_sec = itimer.it_interval.tv_sec;
561 itimer.it_value.tv_usec = itimer.it_interval.tv_usec;
562 setitimer(ITIMER_PROF, &itimer, &data_->old_timer_value_);
563
564 // Set this sampler as the active sampler.
565 active_sampler_ = this;
566 active_ = true; 593 active_ = true;
594 pthread_create(&data_->sampler_thread_, &sched_attr, SamplerEntry, data_);
567 } 595 }
568 596
569 597
570 void Sampler::Stop() { 598 void Sampler::Stop() {
571 // Restore old signal handler 599 // Seting active to false triggers termination of the sampler
572 if (data_->signal_handler_installed_) { 600 // thread.
573 setitimer(ITIMER_PROF, &data_->old_timer_value_, NULL); 601 active_ = false;
574 sigaction(SIGPROF, &data_->old_signal_handler_, 0); 602
575 data_->signal_handler_installed_ = false; 603 // Wait for sampler thread to terminate.
604 pthread_join(data_->sampler_thread_, NULL);
605
606 // Deallocate Mach port for thread.
607 if (IsProfiling()) {
608 mach_port_deallocate(data_->task_self_, data_->profiled_thread_);
576 } 609 }
577
578 // This sampler is no longer the active sampler.
579 active_sampler_ = NULL;
580 active_ = false;
581 } 610 }
582 611
583 #endif // ENABLE_LOGGING_AND_PROFILING 612 #endif // ENABLE_LOGGING_AND_PROFILING
584 613
585 } } // namespace v8::internal 614 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/platform-linux.cc ('k') | src/platform-win32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698