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

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

Issue 6667025: Update platform-solaris to support runtime profiling. (Closed)
Patch Set: Created 9 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
« no previous file with comments | « no previous file | no next file » | 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-2009 the V8 project authors. All rights reserved. 1 // Copyright 2006-2009 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 594 matching lines...) Expand 10 before | Expand all | Expand 10 after
605 return new SolarisSemaphore(count); 605 return new SolarisSemaphore(count);
606 } 606 }
607 607
608 608
609 #ifdef ENABLE_LOGGING_AND_PROFILING 609 #ifdef ENABLE_LOGGING_AND_PROFILING
610 610
611 static Sampler* active_sampler_ = NULL; 611 static Sampler* active_sampler_ = NULL;
612 static pthread_t vm_tid_ = 0; 612 static pthread_t vm_tid_ = 0;
613 613
614 614
615 static pthread_t GetThreadID() {
616 return pthread_self();
617 }
618
619
615 static void ProfilerSignalHandler(int signal, siginfo_t* info, void* context) { 620 static void ProfilerSignalHandler(int signal, siginfo_t* info, void* context) {
616 USE(info); 621 USE(info);
617 if (signal != SIGPROF) return; 622 if (signal != SIGPROF) return;
618 if (active_sampler_ == NULL || !active_sampler_->IsActive()) return; 623 if (active_sampler_ == NULL || !active_sampler_->IsActive()) return;
619 if (vm_tid_ != pthread_self()) return; 624 if (vm_tid_ != GetThreadID()) return;
620 625
621 TickSample sample_obj; 626 TickSample sample_obj;
622 TickSample* sample = CpuProfiler::TickSampleEvent(); 627 TickSample* sample = CpuProfiler::TickSampleEvent();
623 if (sample == NULL) sample = &sample_obj; 628 if (sample == NULL) sample = &sample_obj;
624 629
625 // Extracting the sample from the context is extremely machine dependent. 630 // Extracting the sample from the context is extremely machine dependent.
626 ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context); 631 ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context);
627 mcontext_t& mcontext = ucontext->uc_mcontext; 632 mcontext_t& mcontext = ucontext->uc_mcontext;
628 sample->state = Top::current_vm_state(); 633 sample->state = Top::current_vm_state();
629 634
630 #if V8_HOST_ARCH_IA32 635 #if V8_HOST_ARCH_IA32
631 sample->pc = reinterpret_cast<Address>(mcontext.gregs[KDIREG_EIP]); 636 sample->pc = reinterpret_cast<Address>(mcontext.gregs[KDIREG_EIP]);
632 sample->sp = reinterpret_cast<Address>(mcontext.gregs[KDIREG_ESP]); 637 sample->sp = reinterpret_cast<Address>(mcontext.gregs[KDIREG_ESP]);
633 sample->fp = reinterpret_cast<Address>(mcontext.gregs[KDIREG_EBP]); 638 sample->fp = reinterpret_cast<Address>(mcontext.gregs[KDIREG_EBP]);
634 #elif V8_HOST_ARCH_X64 639 #elif V8_HOST_ARCH_X64
635 sample->pc = reinterpret_cast<Address>(mcontext.gregs[KDIREG_RIP]); 640 sample->pc = reinterpret_cast<Address>(mcontext.gregs[KDIREG_RIP]);
636 sample->sp = reinterpret_cast<Address>(mcontext.gregs[KDIREG_RSP]); 641 sample->sp = reinterpret_cast<Address>(mcontext.gregs[KDIREG_RSP]);
637 sample->fp = reinterpret_cast<Address>(mcontext.gregs[KDIREG_RBP]); 642 sample->fp = reinterpret_cast<Address>(mcontext.gregs[KDIREG_RBP]);
638 #else 643 #else
639 UNIMPLEMENTED(); 644 UNIMPLEMENTED();
640 #endif 645 #endif
641 active_sampler_->SampleStack(sample); 646 active_sampler_->SampleStack(sample);
642 active_sampler_->Tick(sample); 647 active_sampler_->Tick(sample);
643 } 648 }
644 649
645 650
646 class Sampler::PlatformData : public Malloced { 651 class Sampler::PlatformData : public Malloced {
647 public: 652 public:
648 PlatformData() { 653 enum SleepInterval {
649 signal_handler_installed_ = false; 654 FULL_INTERVAL,
655 HALF_INTERVAL
656 };
657
658 explicit PlatformData(Sampler* sampler)
659 : sampler_(sampler),
660 signal_handler_installed_(false),
661 vm_tgid_(getpid()),
662 signal_sender_launched_(false) {
650 } 663 }
651 664
665 void SignalSender() {
666 while (sampler_->IsActive()) {
667 if (rate_limiter_.SuspendIfNecessary()) continue;
668 if (sampler_->IsProfiling() && RuntimeProfiler::IsEnabled()) {
669 SendProfilingSignal();
670 Sleep(HALF_INTERVAL);
671 RuntimeProfiler::NotifyTick();
672 Sleep(HALF_INTERVAL);
673 } else {
674 if (sampler_->IsProfiling()) SendProfilingSignal();
675 if (RuntimeProfiler::IsEnabled()) RuntimeProfiler::NotifyTick();
676 Sleep(FULL_INTERVAL);
677 }
678 }
679 }
680
681 void SendProfilingSignal() {
682 if (!signal_handler_installed_) return;
683 // There doesn't seem to be a robust way to deliver a signal to a
684 // particular thread that may have terminated already. We send the
685 // signal to the whole process hoping the right thread will get
686 // it.
687 kill(vm_tgid_, SIGPROF);
688 }
689
690 void Sleep(SleepInterval full_or_half) {
691 // Convert ms to us and subtract 100 us to compensate delays
692 // occuring during signal delivery.
693 useconds_t interval = sampler_->interval_ * 1000 - 100;
694 if (full_or_half == HALF_INTERVAL) interval /= 2;
695 int result = usleep(interval);
696 #ifdef DEBUG
697 if (result != 0 && errno != EINTR) {
698 fprintf(stderr,
699 "SignalSender usleep error; interval = %u, errno = %d\n",
700 interval,
701 errno);
702 ASSERT(result == 0 || errno == EINTR);
703 }
704 #endif
705 USE(result);
706 }
707
708 Sampler* sampler_;
652 bool signal_handler_installed_; 709 bool signal_handler_installed_;
653 struct sigaction old_signal_handler_; 710 struct sigaction old_signal_handler_;
654 struct itimerval old_timer_value_; 711 int vm_tgid_;
712 bool signal_sender_launched_;
713 pthread_t signal_sender_thread_;
714 RuntimeProfilerRateLimiter rate_limiter_;
655 }; 715 };
656 716
657 717
718 static void* SenderEntry(void* arg) {
719 Sampler::PlatformData* data =
720 reinterpret_cast<Sampler::PlatformData*>(arg);
721 data->SignalSender();
722 return 0;
723 }
724
725
658 Sampler::Sampler(int interval) 726 Sampler::Sampler(int interval)
659 : interval_(interval), 727 : interval_(interval),
660 profiling_(false), 728 profiling_(false),
661 active_(false), 729 active_(false),
662 samples_taken_(0) { 730 samples_taken_(0) {
663 data_ = new PlatformData(); 731 data_ = new PlatformData(this);
664 } 732 }
665 733
666 734
667 Sampler::~Sampler() { 735 Sampler::~Sampler() {
736 ASSERT(!data_->signal_sender_launched_);
668 delete data_; 737 delete data_;
669 } 738 }
670 739
671 740
672 void Sampler::Start() { 741 void Sampler::Start() {
673 // There can only be one active sampler at the time on POSIX 742 // There can only be one active sampler at the time on POSIX
674 // platforms. 743 // platforms.
675 if (active_sampler_ != NULL) return; 744 ASSERT(!IsActive());
745 vm_tid_ = GetThreadID();
676 746
677 // Request profiling signals. 747 // Request profiling signals.
678 struct sigaction sa; 748 struct sigaction sa;
679 sa.sa_sigaction = ProfilerSignalHandler; 749 sa.sa_sigaction = ProfilerSignalHandler;
680 sigemptyset(&sa.sa_mask); 750 sigemptyset(&sa.sa_mask);
681 sa.sa_flags = SA_SIGINFO; 751 sa.sa_flags = SA_RESTART | SA_SIGINFO;
682 if (sigaction(SIGPROF, &sa, &data_->old_signal_handler_) != 0) return; 752 data_->signal_handler_installed_ =
683 data_->signal_handler_installed_ = true; 753 sigaction(SIGPROF, &sa, &data_->old_signal_handler_) == 0;
684 754
685 // Set the itimer to generate a tick for each interval. 755 // Start a thread that sends SIGPROF signal to VM thread.
686 itimerval itimer; 756 // Sending the signal ourselves instead of relying on itimer provides
687 itimer.it_interval.tv_sec = interval_ / 1000; 757 // much better accuracy.
688 itimer.it_interval.tv_usec = (interval_ % 1000) * 1000; 758 SetActive(true);
689 itimer.it_value.tv_sec = itimer.it_interval.tv_sec; 759 if (pthread_create(
690 itimer.it_value.tv_usec = itimer.it_interval.tv_usec; 760 &data_->signal_sender_thread_, NULL, SenderEntry, data_) == 0) {
691 setitimer(ITIMER_PROF, &itimer, &data_->old_timer_value_); 761 data_->signal_sender_launched_ = true;
762 }
692 763
693 // Set this sampler as the active sampler. 764 // Set this sampler as the active sampler.
694 active_sampler_ = this; 765 active_sampler_ = this;
695 active_ = true;
696 } 766 }
697 767
698 768
699 void Sampler::Stop() { 769 void Sampler::Stop() {
770 SetActive(false);
771
772 // Wait for signal sender termination (it will exit after setting
773 // active_ to false).
774 if (data_->signal_sender_launched_) {
775 Top::WakeUpRuntimeProfilerThreadBeforeShutdown();
776 pthread_join(data_->signal_sender_thread_, NULL);
777 data_->signal_sender_launched_ = false;
778 }
779
700 // Restore old signal handler 780 // Restore old signal handler
701 if (data_->signal_handler_installed_) { 781 if (data_->signal_handler_installed_) {
702 setitimer(ITIMER_PROF, &data_->old_timer_value_, NULL);
703 sigaction(SIGPROF, &data_->old_signal_handler_, 0); 782 sigaction(SIGPROF, &data_->old_signal_handler_, 0);
704 data_->signal_handler_installed_ = false; 783 data_->signal_handler_installed_ = false;
705 } 784 }
706 785
707 // This sampler is no longer the active sampler. 786 // This sampler is no longer the active sampler.
708 active_sampler_ = NULL; 787 active_sampler_ = NULL;
709 active_ = false;
710 } 788 }
711 789
712 #endif // ENABLE_LOGGING_AND_PROFILING 790 #endif // ENABLE_LOGGING_AND_PROFILING
713 791
714 } } // namespace v8::internal 792 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698