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

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

Issue 13852005: Move *BSD and Solaris Sampler implementations into sampler.cc (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Removed class TickSample forward declaration Created 7 years, 8 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
« no previous file with comments | « src/platform-openbsd.cc ('k') | src/sampler.h » ('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 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 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 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
47 #include <signal.h> // sigemptyset(), etc 47 #include <signal.h> // sigemptyset(), etc
48 #include <sys/regset.h> 48 #include <sys/regset.h>
49 49
50 50
51 #undef MAP_TYPE 51 #undef MAP_TYPE
52 52
53 #include "v8.h" 53 #include "v8.h"
54 54
55 #include "platform-posix.h" 55 #include "platform-posix.h"
56 #include "platform.h" 56 #include "platform.h"
57 #include "simulator.h"
58 #include "v8threads.h" 57 #include "v8threads.h"
59 #include "vm-state-inl.h" 58 #include "vm-state-inl.h"
60 59
61 60
62 // It seems there is a bug in some Solaris distributions (experienced in 61 // It seems there is a bug in some Solaris distributions (experienced in
63 // SunOS 5.10 Generic_141445-09) which make it difficult or impossible to 62 // SunOS 5.10 Generic_141445-09) which make it difficult or impossible to
64 // access signbit() despite the availability of other C99 math functions. 63 // access signbit() despite the availability of other C99 math functions.
65 #ifndef signbit 64 #ifndef signbit
66 // Test sign - usually defined in math.h 65 // Test sign - usually defined in math.h
67 int signbit(double x) { 66 int signbit(double x) {
(...skipping 587 matching lines...) Expand 10 before | Expand all | Expand 10 after
655 CHECK(result == -1 && errno == EINTR); // Signal caused spurious wakeup. 654 CHECK(result == -1 && errno == EINTR); // Signal caused spurious wakeup.
656 } 655 }
657 } 656 }
658 657
659 658
660 Semaphore* OS::CreateSemaphore(int count) { 659 Semaphore* OS::CreateSemaphore(int count) {
661 return new SolarisSemaphore(count); 660 return new SolarisSemaphore(count);
662 } 661 }
663 662
664 663
665 static pthread_t GetThreadID() {
666 return pthread_self();
667 }
668
669
670 class Sampler::PlatformData : public Malloced {
671 public:
672 PlatformData()
673 : vm_tid_(GetThreadID()),
674 profiled_thread_id_(ThreadId::Current()) {}
675
676 pthread_t vm_tid() const { return vm_tid_; }
677 ThreadId profiled_thread_id() { return profiled_thread_id_; }
678
679 private:
680 pthread_t vm_tid_;
681 ThreadId profiled_thread_id_;
682 };
683
684
685 static void ProfilerSignalHandler(int signal, siginfo_t* info, void* context) {
686 USE(info);
687 if (signal != SIGPROF) return;
688 Isolate* isolate = Isolate::UncheckedCurrent();
689 if (isolate == NULL || !isolate->IsInitialized() || !isolate->IsInUse()) {
690 // We require a fully initialized and entered isolate.
691 return;
692 }
693 if (v8::Locker::IsActive() &&
694 !isolate->thread_manager()->IsLockedByCurrentThread()) {
695 return;
696 }
697
698 Sampler* sampler = isolate->logger()->sampler();
699 if (sampler == NULL || !sampler->IsActive()) return;
700
701 TickSample sample_obj;
702 TickSample* sample = isolate->cpu_profiler()->TickSampleEvent();
703 if (sample == NULL) sample = &sample_obj;
704
705 #if defined(USE_SIMULATOR)
706 #if V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_MIPS
707 ThreadId thread_id = sampler->platform_data()->profiled_thread_id();
708 Isolate::PerIsolateThreadData* per_thread_data = isolate->
709 FindPerThreadDataForThread(thread_id);
710 if (!per_thread_data) return;
711 Simulator* sim = per_thread_data->simulator();
712 // Check if there is active simulator before allocating TickSample.
713 if (!sim) return;
714 #endif
715 #endif // USE_SIMULATOR
716
717 // Extracting the sample from the context is extremely machine dependent.
718 ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context);
719 mcontext_t& mcontext = ucontext->uc_mcontext;
720 sample->state = isolate->current_vm_state();
721
722 #if defined(USE_SIMULATOR)
723 #if V8_TARGET_ARCH_ARM
724 sample->pc = reinterpret_cast<Address>(sim->get_register(Simulator::pc));
725 sample->sp = reinterpret_cast<Address>(sim->get_register(Simulator::sp));
726 sample->fp = reinterpret_cast<Address>(sim->get_register(Simulator::r11));
727 #elif V8_TARGET_ARCH_MIPS
728 sample->pc = reinterpret_cast<Address>(sim->get_register(Simulator::pc));
729 sample->sp = reinterpret_cast<Address>(sim->get_register(Simulator::sp));
730 sample->fp = reinterpret_cast<Address>(sim->get_register(Simulator::fp));
731 #endif
732 #else
733 sample->pc = reinterpret_cast<Address>(mcontext.gregs[REG_PC]);
734 sample->sp = reinterpret_cast<Address>(mcontext.gregs[REG_SP]);
735 sample->fp = reinterpret_cast<Address>(mcontext.gregs[REG_FP]);
736 #endif // USE_SIMULATOR
737
738 sampler->SampleStack(sample);
739 sampler->Tick(sample);
740 }
741
742
743 class SignalSender : public Thread {
744 public:
745 static const int kSignalSenderStackSize = 64 * KB;
746
747 explicit SignalSender(int interval)
748 : Thread(Thread::Options("SignalSender", kSignalSenderStackSize)),
749 interval_(interval) {}
750
751 static void SetUp() { if (!mutex_) mutex_ = OS::CreateMutex(); }
752 static void TearDown() { delete mutex_; }
753
754 static void InstallSignalHandler() {
755 struct sigaction sa;
756 sa.sa_sigaction = ProfilerSignalHandler;
757 sigemptyset(&sa.sa_mask);
758 sa.sa_flags = SA_RESTART | SA_SIGINFO;
759 signal_handler_installed_ =
760 (sigaction(SIGPROF, &sa, &old_signal_handler_) == 0);
761 }
762
763 static void RestoreSignalHandler() {
764 if (signal_handler_installed_) {
765 sigaction(SIGPROF, &old_signal_handler_, 0);
766 signal_handler_installed_ = false;
767 }
768 }
769
770 static void AddActiveSampler(Sampler* sampler) {
771 ScopedLock lock(mutex_);
772 SamplerRegistry::AddActiveSampler(sampler);
773 if (instance_ == NULL) {
774 // Start a thread that will send SIGPROF signal to VM threads,
775 // when CPU profiling will be enabled.
776 instance_ = new SignalSender(sampler->interval());
777 instance_->StartSynchronously();
778 } else {
779 ASSERT(instance_->interval_ == sampler->interval());
780 }
781 }
782
783 static void RemoveActiveSampler(Sampler* sampler) {
784 ScopedLock lock(mutex_);
785 SamplerRegistry::RemoveActiveSampler(sampler);
786 if (SamplerRegistry::GetState() == SamplerRegistry::HAS_NO_SAMPLERS) {
787 instance_->Join();
788 delete instance_;
789 instance_ = NULL;
790 RestoreSignalHandler();
791 }
792 }
793
794 // Implement Thread::Run().
795 virtual void Run() {
796 SamplerRegistry::State state;
797 while ((state = SamplerRegistry::GetState()) !=
798 SamplerRegistry::HAS_NO_SAMPLERS) {
799 // When CPU profiling is enabled both JavaScript and C++ code is
800 // profiled. We must not suspend.
801 if (state == SamplerRegistry::HAS_CPU_PROFILING_SAMPLERS) {
802 if (!signal_handler_installed_) InstallSignalHandler();
803 SamplerRegistry::IterateActiveSamplers(&DoCpuProfile, this);
804 } else if (signal_handler_installed_) {
805 RestoreSignalHandler();
806 }
807 Sleep(); // TODO(svenpanne) Figure out if OS:Sleep(interval_) is enough.
808 }
809 }
810
811 static void DoCpuProfile(Sampler* sampler, void* raw_sender) {
812 if (!sampler->IsProfiling()) return;
813 SignalSender* sender = reinterpret_cast<SignalSender*>(raw_sender);
814 sender->SendProfilingSignal(sampler->platform_data()->vm_tid());
815 }
816
817 void SendProfilingSignal(pthread_t tid) {
818 if (!signal_handler_installed_) return;
819 pthread_kill(tid, SIGPROF);
820 }
821
822 void Sleep() {
823 // Convert ms to us and subtract 100 us to compensate delays
824 // occuring during signal delivery.
825 useconds_t interval = interval_ * 1000 - 100;
826 int result = usleep(interval);
827 #ifdef DEBUG
828 if (result != 0 && errno != EINTR) {
829 fprintf(stderr,
830 "SignalSender usleep error; interval = %u, errno = %d\n",
831 interval,
832 errno);
833 ASSERT(result == 0 || errno == EINTR);
834 }
835 #endif
836 USE(result);
837 }
838
839 const int interval_;
840
841 // Protects the process wide state below.
842 static Mutex* mutex_;
843 static SignalSender* instance_;
844 static bool signal_handler_installed_;
845 static struct sigaction old_signal_handler_;
846
847 private:
848 DISALLOW_COPY_AND_ASSIGN(SignalSender);
849 };
850
851 Mutex* SignalSender::mutex_ = NULL;
852 SignalSender* SignalSender::instance_ = NULL;
853 struct sigaction SignalSender::old_signal_handler_;
854 bool SignalSender::signal_handler_installed_ = false;
855
856
857 void OS::SetUp() { 664 void OS::SetUp() {
858 // Seed the random number generator. 665 // Seed the random number generator.
859 // Convert the current time to a 64-bit integer first, before converting it 666 // Convert the current time to a 64-bit integer first, before converting it
860 // to an unsigned. Going directly will cause an overflow and the seed to be 667 // to an unsigned. Going directly will cause an overflow and the seed to be
861 // set to all ones. The seed will be identical for different instances that 668 // set to all ones. The seed will be identical for different instances that
862 // call this setup code within the same millisecond. 669 // call this setup code within the same millisecond.
863 uint64_t seed = static_cast<uint64_t>(TimeCurrentMillis()); 670 uint64_t seed = static_cast<uint64_t>(TimeCurrentMillis());
864 srandom(static_cast<unsigned int>(seed)); 671 srandom(static_cast<unsigned int>(seed));
865 limit_mutex = CreateMutex(); 672 limit_mutex = CreateMutex();
866 SignalSender::SetUp();
867 } 673 }
868 674
869 675
870 void OS::TearDown() { 676 void OS::TearDown() {
871 SignalSender::TearDown();
872 delete limit_mutex; 677 delete limit_mutex;
873 } 678 }
874 679
875 680
876 Sampler::Sampler(Isolate* isolate, int interval)
877 : isolate_(isolate),
878 interval_(interval),
879 profiling_(false),
880 active_(false),
881 samples_taken_(0) {
882 data_ = new PlatformData;
883 }
884
885
886 Sampler::~Sampler() {
887 ASSERT(!IsActive());
888 delete data_;
889 }
890
891
892 void Sampler::Start() {
893 ASSERT(!IsActive());
894 SetActive(true);
895 SignalSender::AddActiveSampler(this);
896 }
897
898
899 void Sampler::Stop() {
900 ASSERT(IsActive());
901 SignalSender::RemoveActiveSampler(this);
902 SetActive(false);
903 }
904
905 } } // namespace v8::internal 681 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/platform-openbsd.cc ('k') | src/sampler.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698