OLD | NEW |
---|---|
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 Loading... | |
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 |
OLD | NEW |