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

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

Issue 6674002: Update platform-solaris to support runtime profiling (Closed)
Patch Set: use pthread_kill 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 pthread_kill(vm_tgid_, SIGPROF);
Vitaly Repeshko 2011/03/11 00:08:27 Does work with vm_tid_ here?
Vyacheslav Egorov (Chromium) 2011/03/11 00:30:47 This looks really suspicious. vm_tgid_ is not a pt
ry 2011/03/11 01:02:00 Oops. With that I get crashes
Vitaly Repeshko 2011/03/11 01:08:46 So if it crashes because of a stale thread handle,
684 }
685
686 void Sleep(SleepInterval full_or_half) {
687 // Convert ms to us and subtract 100 us to compensate delays
688 // occuring during signal delivery.
689 useconds_t interval = sampler_->interval_ * 1000 - 100;
690 if (full_or_half == HALF_INTERVAL) interval /= 2;
691 int result = usleep(interval);
692 #ifdef DEBUG
693 if (result != 0 && errno != EINTR) {
694 fprintf(stderr,
695 "SignalSender usleep error; interval = %u, errno = %d\n",
696 interval,
697 errno);
698 ASSERT(result == 0 || errno == EINTR);
699 }
700 #endif
701 USE(result);
702 }
703
704 Sampler* sampler_;
652 bool signal_handler_installed_; 705 bool signal_handler_installed_;
653 struct sigaction old_signal_handler_; 706 struct sigaction old_signal_handler_;
654 struct itimerval old_timer_value_; 707 int vm_tgid_;
708 bool signal_sender_launched_;
709 pthread_t signal_sender_thread_;
710 RuntimeProfilerRateLimiter rate_limiter_;
655 }; 711 };
656 712
657 713
714 static void* SenderEntry(void* arg) {
715 Sampler::PlatformData* data =
716 reinterpret_cast<Sampler::PlatformData*>(arg);
717 data->SignalSender();
718 return 0;
719 }
720
721
658 Sampler::Sampler(int interval) 722 Sampler::Sampler(int interval)
659 : interval_(interval), 723 : interval_(interval),
660 profiling_(false), 724 profiling_(false),
661 active_(false), 725 active_(false),
662 samples_taken_(0) { 726 samples_taken_(0) {
663 data_ = new PlatformData(); 727 data_ = new PlatformData(this);
664 } 728 }
665 729
666 730
667 Sampler::~Sampler() { 731 Sampler::~Sampler() {
732 ASSERT(!data_->signal_sender_launched_);
668 delete data_; 733 delete data_;
669 } 734 }
670 735
671 736
672 void Sampler::Start() { 737 void Sampler::Start() {
673 // There can only be one active sampler at the time on POSIX 738 // There can only be one active sampler at the time on POSIX
674 // platforms. 739 // platforms.
675 if (active_sampler_ != NULL) return; 740 ASSERT(!IsActive());
741 vm_tid_ = GetThreadID();
676 742
677 // Request profiling signals. 743 // Request profiling signals.
678 struct sigaction sa; 744 struct sigaction sa;
679 sa.sa_sigaction = ProfilerSignalHandler; 745 sa.sa_sigaction = ProfilerSignalHandler;
680 sigemptyset(&sa.sa_mask); 746 sigemptyset(&sa.sa_mask);
681 sa.sa_flags = SA_SIGINFO; 747 sa.sa_flags = SA_RESTART | SA_SIGINFO;
682 if (sigaction(SIGPROF, &sa, &data_->old_signal_handler_) != 0) return; 748 data_->signal_handler_installed_ =
683 data_->signal_handler_installed_ = true; 749 sigaction(SIGPROF, &sa, &data_->old_signal_handler_) == 0;
684 750
685 // Set the itimer to generate a tick for each interval. 751 // Start a thread that sends SIGPROF signal to VM thread.
686 itimerval itimer; 752 // Sending the signal ourselves instead of relying on itimer provides
687 itimer.it_interval.tv_sec = interval_ / 1000; 753 // much better accuracy.
688 itimer.it_interval.tv_usec = (interval_ % 1000) * 1000; 754 SetActive(true);
689 itimer.it_value.tv_sec = itimer.it_interval.tv_sec; 755 if (pthread_create(
690 itimer.it_value.tv_usec = itimer.it_interval.tv_usec; 756 &data_->signal_sender_thread_, NULL, SenderEntry, data_) == 0) {
691 setitimer(ITIMER_PROF, &itimer, &data_->old_timer_value_); 757 data_->signal_sender_launched_ = true;
758 }
692 759
693 // Set this sampler as the active sampler. 760 // Set this sampler as the active sampler.
694 active_sampler_ = this; 761 active_sampler_ = this;
695 active_ = true;
696 } 762 }
697 763
698 764
699 void Sampler::Stop() { 765 void Sampler::Stop() {
766 SetActive(false);
767
768 // Wait for signal sender termination (it will exit after setting
769 // active_ to false).
770 if (data_->signal_sender_launched_) {
771 Top::WakeUpRuntimeProfilerThreadBeforeShutdown();
772 pthread_join(data_->signal_sender_thread_, NULL);
773 data_->signal_sender_launched_ = false;
774 }
775
700 // Restore old signal handler 776 // Restore old signal handler
701 if (data_->signal_handler_installed_) { 777 if (data_->signal_handler_installed_) {
702 setitimer(ITIMER_PROF, &data_->old_timer_value_, NULL);
703 sigaction(SIGPROF, &data_->old_signal_handler_, 0); 778 sigaction(SIGPROF, &data_->old_signal_handler_, 0);
704 data_->signal_handler_installed_ = false; 779 data_->signal_handler_installed_ = false;
705 } 780 }
706 781
707 // This sampler is no longer the active sampler. 782 // This sampler is no longer the active sampler.
708 active_sampler_ = NULL; 783 active_sampler_ = NULL;
709 active_ = false;
710 } 784 }
711 785
786
712 #endif // ENABLE_LOGGING_AND_PROFILING 787 #endif // ENABLE_LOGGING_AND_PROFILING
713 788
714 } } // namespace v8::internal 789 } } // 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