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

Side by Side Diff: src/platform-freebsd.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.h ('k') | src/platform-linux.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 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 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
49 #include <stdarg.h> 49 #include <stdarg.h>
50 #include <limits.h> 50 #include <limits.h>
51 51
52 #undef MAP_TYPE 52 #undef MAP_TYPE
53 53
54 #include "v8.h" 54 #include "v8.h"
55 #include "v8threads.h" 55 #include "v8threads.h"
56 56
57 #include "platform-posix.h" 57 #include "platform-posix.h"
58 #include "platform.h" 58 #include "platform.h"
59 #include "simulator.h"
60 #include "vm-state-inl.h" 59 #include "vm-state-inl.h"
61 60
62 61
63 namespace v8 { 62 namespace v8 {
64 namespace internal { 63 namespace internal {
65 64
66 // 0 is never a valid thread id on FreeBSD since tids and pids share a 65 // 0 is never a valid thread id on FreeBSD since tids and pids share a
67 // name space and pid 0 is used to kill the group (see man 2 kill). 66 // name space and pid 0 is used to kill the group (see man 2 kill).
68 static const pthread_t kNoThread = (pthread_t) 0; 67 static const pthread_t kNoThread = (pthread_t) 0;
69 68
(...skipping 606 matching lines...) Expand 10 before | Expand all | Expand 10 after
676 CHECK(result == -1 && errno == EINTR); // Signal caused spurious wakeup. 675 CHECK(result == -1 && errno == EINTR); // Signal caused spurious wakeup.
677 } 676 }
678 } 677 }
679 678
680 679
681 Semaphore* OS::CreateSemaphore(int count) { 680 Semaphore* OS::CreateSemaphore(int count) {
682 return new FreeBSDSemaphore(count); 681 return new FreeBSDSemaphore(count);
683 } 682 }
684 683
685 684
686 static pthread_t GetThreadID() {
687 pthread_t thread_id = pthread_self();
688 return thread_id;
689 }
690
691
692 class Sampler::PlatformData : public Malloced {
693 public:
694 PlatformData()
695 : vm_tid_(GetThreadID()),
696 profiled_thread_id_(ThreadId::Current()) {}
697
698 pthread_t vm_tid() const { return vm_tid_; }
699 ThreadId profiled_thread_id() { return profiled_thread_id_; }
700
701 private:
702 pthread_t vm_tid_;
703 ThreadId profiled_thread_id_;
704 };
705
706
707 static void ProfilerSignalHandler(int signal, siginfo_t* info, void* context) {
708 USE(info);
709 if (signal != SIGPROF) return;
710 Isolate* isolate = Isolate::UncheckedCurrent();
711 if (isolate == NULL || !isolate->IsInitialized() || !isolate->IsInUse()) {
712 // We require a fully initialized and entered isolate.
713 return;
714 }
715 if (v8::Locker::IsActive() &&
716 !isolate->thread_manager()->IsLockedByCurrentThread()) {
717 return;
718 }
719
720 Sampler* sampler = isolate->logger()->sampler();
721 if (sampler == NULL || !sampler->IsActive()) return;
722
723 #if defined(USE_SIMULATOR)
724 #if V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_MIPS
725 ThreadId thread_id = sampler->platform_data()->profiled_thread_id();
726 Isolate::PerIsolateThreadData* per_thread_data = isolate->
727 FindPerThreadDataForThread(thread_id);
728 if (!per_thread_data) return;
729 Simulator* sim = per_thread_data->simulator();
730 // Check if there is active simulator before allocating TickSample.
731 if (!sim) return;
732 #endif
733 #endif // USE_SIMULATOR
734
735 TickSample sample_obj;
736 TickSample* sample = isolate->cpu_profiler()->TickSampleEvent();
737 if (sample == NULL) sample = &sample_obj;
738
739 // Extracting the sample from the context is extremely machine dependent.
740 ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context);
741 mcontext_t& mcontext = ucontext->uc_mcontext;
742 sample->state = isolate->current_vm_state();
743 #if defined(USE_SIMULATOR)
744 #if V8_TARGET_ARCH_ARM
745 sample->pc = reinterpret_cast<Address>(sim->get_register(Simulator::pc));
746 sample->sp = reinterpret_cast<Address>(sim->get_register(Simulator::sp));
747 sample->fp = reinterpret_cast<Address>(sim->get_register(Simulator::r11));
748 #elif V8_TARGET_ARCH_MIPS
749 sample->pc = reinterpret_cast<Address>(sim->get_register(Simulator::pc));
750 sample->sp = reinterpret_cast<Address>(sim->get_register(Simulator::sp));
751 sample->fp = reinterpret_cast<Address>(sim->get_register(Simulator::fp));
752 #endif
753 #else
754 #if V8_HOST_ARCH_IA32
755 sample->pc = reinterpret_cast<Address>(mcontext.mc_eip);
756 sample->sp = reinterpret_cast<Address>(mcontext.mc_esp);
757 sample->fp = reinterpret_cast<Address>(mcontext.mc_ebp);
758 #elif V8_HOST_ARCH_X64
759 sample->pc = reinterpret_cast<Address>(mcontext.mc_rip);
760 sample->sp = reinterpret_cast<Address>(mcontext.mc_rsp);
761 sample->fp = reinterpret_cast<Address>(mcontext.mc_rbp);
762 #elif V8_HOST_ARCH_ARM
763 sample->pc = reinterpret_cast<Address>(mcontext.mc_r15);
764 sample->sp = reinterpret_cast<Address>(mcontext.mc_r13);
765 sample->fp = reinterpret_cast<Address>(mcontext.mc_r11);
766 #endif // V8_HOST_ARCH_*
767 #endif // USE_SIMULATOR
768 sampler->SampleStack(sample);
769 sampler->Tick(sample);
770 }
771
772
773 class SignalSender : public Thread {
774 public:
775 static const int kSignalSenderStackSize = 64 * KB;
776
777 explicit SignalSender(int interval)
778 : Thread(Thread::Options("SignalSender", kSignalSenderStackSize)),
779 interval_(interval) {}
780
781 static void SetUp() { if (!mutex_) mutex_ = OS::CreateMutex(); }
782 static void TearDown() { delete mutex_; }
783
784 static void AddActiveSampler(Sampler* sampler) {
785 ScopedLock lock(mutex_);
786 SamplerRegistry::AddActiveSampler(sampler);
787 if (instance_ == NULL) {
788 // Install a signal handler.
789 struct sigaction sa;
790 sa.sa_sigaction = ProfilerSignalHandler;
791 sigemptyset(&sa.sa_mask);
792 sa.sa_flags = SA_RESTART | SA_SIGINFO;
793 signal_handler_installed_ =
794 (sigaction(SIGPROF, &sa, &old_signal_handler_) == 0);
795
796 // Start a thread that sends SIGPROF signal to VM threads.
797 instance_ = new SignalSender(sampler->interval());
798 instance_->StartSynchronously();
799 } else {
800 ASSERT(instance_->interval_ == sampler->interval());
801 }
802 }
803
804 static void RemoveActiveSampler(Sampler* sampler) {
805 ScopedLock lock(mutex_);
806 SamplerRegistry::RemoveActiveSampler(sampler);
807 if (SamplerRegistry::GetState() == SamplerRegistry::HAS_NO_SAMPLERS) {
808 instance_->Join();
809 delete instance_;
810 instance_ = NULL;
811
812 // Restore the old signal handler.
813 if (signal_handler_installed_) {
814 sigaction(SIGPROF, &old_signal_handler_, 0);
815 signal_handler_installed_ = false;
816 }
817 }
818 }
819
820 // Implement Thread::Run().
821 virtual void Run() {
822 SamplerRegistry::State state;
823 while ((state = SamplerRegistry::GetState()) !=
824 SamplerRegistry::HAS_NO_SAMPLERS) {
825 // When CPU profiling is enabled both JavaScript and C++ code is
826 // profiled. We must not suspend.
827 if (state == SamplerRegistry::HAS_CPU_PROFILING_SAMPLERS) {
828 SamplerRegistry::IterateActiveSamplers(&DoCpuProfile, this);
829 }
830 Sleep(); // TODO(svenpanne) Figure out if OS:Sleep(interval_) is enough.
831 }
832 }
833
834 static void DoCpuProfile(Sampler* sampler, void* raw_sender) {
835 if (!sampler->IsProfiling()) return;
836 SignalSender* sender = reinterpret_cast<SignalSender*>(raw_sender);
837 sender->SendProfilingSignal(sampler->platform_data()->vm_tid());
838 }
839
840 void SendProfilingSignal(pthread_t tid) {
841 if (!signal_handler_installed_) return;
842 pthread_kill(tid, SIGPROF);
843 }
844
845 void Sleep() {
846 // Convert ms to us and subtract 100 us to compensate delays
847 // occuring during signal delivery.
848 useconds_t interval = interval_ * 1000 - 100;
849 int result = usleep(interval);
850 #ifdef DEBUG
851 if (result != 0 && errno != EINTR) {
852 fprintf(stderr,
853 "SignalSender usleep error; interval = %u, errno = %d\n",
854 interval,
855 errno);
856 ASSERT(result == 0 || errno == EINTR);
857 }
858 #endif
859 USE(result);
860 }
861
862 const int interval_;
863
864 // Protects the process wide state below.
865 static Mutex* mutex_;
866 static SignalSender* instance_;
867 static bool signal_handler_installed_;
868 static struct sigaction old_signal_handler_;
869
870 private:
871 DISALLOW_COPY_AND_ASSIGN(SignalSender);
872 };
873
874 Mutex* SignalSender::mutex_ = NULL;
875 SignalSender* SignalSender::instance_ = NULL;
876 struct sigaction SignalSender::old_signal_handler_;
877 bool SignalSender::signal_handler_installed_ = false;
878
879
880 void OS::SetUp() { 685 void OS::SetUp() {
881 // Seed the random number generator. 686 // Seed the random number generator.
882 // Convert the current time to a 64-bit integer first, before converting it 687 // Convert the current time to a 64-bit integer first, before converting it
883 // to an unsigned. Going directly can cause an overflow and the seed to be 688 // to an unsigned. Going directly can cause an overflow and the seed to be
884 // set to all ones. The seed will be identical for different instances that 689 // set to all ones. The seed will be identical for different instances that
885 // call this setup code within the same millisecond. 690 // call this setup code within the same millisecond.
886 uint64_t seed = static_cast<uint64_t>(TimeCurrentMillis()); 691 uint64_t seed = static_cast<uint64_t>(TimeCurrentMillis());
887 srandom(static_cast<unsigned int>(seed)); 692 srandom(static_cast<unsigned int>(seed));
888 limit_mutex = CreateMutex(); 693 limit_mutex = CreateMutex();
889 SignalSender::SetUp();
890 } 694 }
891 695
892 696
893 void OS::TearDown() { 697 void OS::TearDown() {
894 SignalSender::TearDown();
895 delete limit_mutex; 698 delete limit_mutex;
896 } 699 }
897 700
898 701
899 Sampler::Sampler(Isolate* isolate, int interval)
900 : isolate_(isolate),
901 interval_(interval),
902 profiling_(false),
903 active_(false),
904 samples_taken_(0) {
905 data_ = new PlatformData;
906 }
907
908
909 Sampler::~Sampler() {
910 ASSERT(!IsActive());
911 delete data_;
912 }
913
914
915 void Sampler::Start() {
916 ASSERT(!IsActive());
917 SetActive(true);
918 SignalSender::AddActiveSampler(this);
919 }
920
921
922 void Sampler::Stop() {
923 ASSERT(IsActive());
924 SignalSender::RemoveActiveSampler(this);
925 SetActive(false);
926 }
927
928
929 } } // namespace v8::internal 702 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/platform.h ('k') | src/platform-linux.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698