| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 668 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 679 } | 679 } |
| 680 | 680 |
| 681 | 681 |
| 682 class Thread::PlatformData : public Malloced { | 682 class Thread::PlatformData : public Malloced { |
| 683 public: | 683 public: |
| 684 PlatformData() : thread_(kNoThread) {} | 684 PlatformData() : thread_(kNoThread) {} |
| 685 | 685 |
| 686 pthread_t thread_; // Thread handle for pthread. | 686 pthread_t thread_; // Thread handle for pthread. |
| 687 }; | 687 }; |
| 688 | 688 |
| 689 Thread::Thread(Isolate* isolate, const Options& options) | 689 Thread::Thread(const Options& options) |
| 690 : data_(new PlatformData()), | 690 : data_(new PlatformData()), |
| 691 isolate_(isolate), | |
| 692 stack_size_(options.stack_size) { | 691 stack_size_(options.stack_size) { |
| 693 set_name(options.name); | 692 set_name(options.name); |
| 694 } | 693 } |
| 695 | 694 |
| 696 | 695 |
| 697 Thread::Thread(Isolate* isolate, const char* name) | 696 Thread::Thread(const char* name) |
| 698 : data_(new PlatformData()), | 697 : data_(new PlatformData()), |
| 699 isolate_(isolate), | |
| 700 stack_size_(0) { | 698 stack_size_(0) { |
| 701 set_name(name); | 699 set_name(name); |
| 702 } | 700 } |
| 703 | 701 |
| 704 | 702 |
| 705 Thread::~Thread() { | 703 Thread::~Thread() { |
| 706 delete data_; | 704 delete data_; |
| 707 } | 705 } |
| 708 | 706 |
| 709 | 707 |
| 710 static void* ThreadEntry(void* arg) { | 708 static void* ThreadEntry(void* arg) { |
| 711 Thread* thread = reinterpret_cast<Thread*>(arg); | 709 Thread* thread = reinterpret_cast<Thread*>(arg); |
| 712 // This is also initialized by the first argument to pthread_create() but we | 710 // This is also initialized by the first argument to pthread_create() but we |
| 713 // don't know which thread will run first (the original thread or the new | 711 // don't know which thread will run first (the original thread or the new |
| 714 // one) so we initialize it here too. | 712 // one) so we initialize it here too. |
| 715 prctl(PR_SET_NAME, | 713 prctl(PR_SET_NAME, |
| 716 reinterpret_cast<unsigned long>(thread->name()), // NOLINT | 714 reinterpret_cast<unsigned long>(thread->name()), // NOLINT |
| 717 0, 0, 0); | 715 0, 0, 0); |
| 718 thread->data()->thread_ = pthread_self(); | 716 thread->data()->thread_ = pthread_self(); |
| 719 ASSERT(thread->data()->thread_ != kNoThread); | 717 ASSERT(thread->data()->thread_ != kNoThread); |
| 720 Thread::SetThreadLocal(Isolate::isolate_key(), thread->isolate()); | |
| 721 thread->Run(); | 718 thread->Run(); |
| 722 return NULL; | 719 return NULL; |
| 723 } | 720 } |
| 724 | 721 |
| 725 | 722 |
| 726 void Thread::set_name(const char* name) { | 723 void Thread::set_name(const char* name) { |
| 727 strncpy(name_, name, sizeof(name_)); | 724 strncpy(name_, name, sizeof(name_)); |
| 728 name_[sizeof(name_) - 1] = '\0'; | 725 name_[sizeof(name_) - 1] = '\0'; |
| 729 } | 726 } |
| 730 | 727 |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 776 } | 773 } |
| 777 | 774 |
| 778 | 775 |
| 779 void Thread::YieldCPU() { | 776 void Thread::YieldCPU() { |
| 780 sched_yield(); | 777 sched_yield(); |
| 781 } | 778 } |
| 782 | 779 |
| 783 | 780 |
| 784 class LinuxMutex : public Mutex { | 781 class LinuxMutex : public Mutex { |
| 785 public: | 782 public: |
| 786 | |
| 787 LinuxMutex() { | 783 LinuxMutex() { |
| 788 pthread_mutexattr_t attrs; | 784 pthread_mutexattr_t attrs; |
| 789 int result = pthread_mutexattr_init(&attrs); | 785 int result = pthread_mutexattr_init(&attrs); |
| 790 ASSERT(result == 0); | 786 ASSERT(result == 0); |
| 791 result = pthread_mutexattr_settype(&attrs, PTHREAD_MUTEX_RECURSIVE); | 787 result = pthread_mutexattr_settype(&attrs, PTHREAD_MUTEX_RECURSIVE); |
| 792 ASSERT(result == 0); | 788 ASSERT(result == 0); |
| 793 result = pthread_mutex_init(&mutex_, &attrs); | 789 result = pthread_mutex_init(&mutex_, &attrs); |
| 794 ASSERT(result == 0); | 790 ASSERT(result == 0); |
| 795 } | 791 } |
| 796 | 792 |
| (...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1001 | 997 |
| 1002 | 998 |
| 1003 class SignalSender : public Thread { | 999 class SignalSender : public Thread { |
| 1004 public: | 1000 public: |
| 1005 enum SleepInterval { | 1001 enum SleepInterval { |
| 1006 HALF_INTERVAL, | 1002 HALF_INTERVAL, |
| 1007 FULL_INTERVAL | 1003 FULL_INTERVAL |
| 1008 }; | 1004 }; |
| 1009 | 1005 |
| 1010 explicit SignalSender(int interval) | 1006 explicit SignalSender(int interval) |
| 1011 : Thread(NULL, "SignalSender"), | 1007 : Thread("SignalSender"), |
| 1012 vm_tgid_(getpid()), | 1008 vm_tgid_(getpid()), |
| 1013 interval_(interval) {} | 1009 interval_(interval) {} |
| 1014 | 1010 |
| 1011 static void InstallSignalHandler() { |
| 1012 struct sigaction sa; |
| 1013 sa.sa_sigaction = ProfilerSignalHandler; |
| 1014 sigemptyset(&sa.sa_mask); |
| 1015 sa.sa_flags = SA_RESTART | SA_SIGINFO; |
| 1016 signal_handler_installed_ = |
| 1017 (sigaction(SIGPROF, &sa, &old_signal_handler_) == 0); |
| 1018 } |
| 1019 |
| 1020 static void RestoreSignalHandler() { |
| 1021 if (signal_handler_installed_) { |
| 1022 sigaction(SIGPROF, &old_signal_handler_, 0); |
| 1023 signal_handler_installed_ = false; |
| 1024 } |
| 1025 } |
| 1026 |
| 1015 static void AddActiveSampler(Sampler* sampler) { | 1027 static void AddActiveSampler(Sampler* sampler) { |
| 1016 ScopedLock lock(mutex_); | 1028 ScopedLock lock(mutex_); |
| 1017 SamplerRegistry::AddActiveSampler(sampler); | 1029 SamplerRegistry::AddActiveSampler(sampler); |
| 1018 if (instance_ == NULL) { | 1030 if (instance_ == NULL) { |
| 1019 // Install a signal handler. | 1031 // Start a thread that will send SIGPROF signal to VM threads, |
| 1020 struct sigaction sa; | 1032 // when CPU profiling will be enabled. |
| 1021 sa.sa_sigaction = ProfilerSignalHandler; | |
| 1022 sigemptyset(&sa.sa_mask); | |
| 1023 sa.sa_flags = SA_RESTART | SA_SIGINFO; | |
| 1024 signal_handler_installed_ = | |
| 1025 (sigaction(SIGPROF, &sa, &old_signal_handler_) == 0); | |
| 1026 | |
| 1027 // Start a thread that sends SIGPROF signal to VM threads. | |
| 1028 instance_ = new SignalSender(sampler->interval()); | 1033 instance_ = new SignalSender(sampler->interval()); |
| 1029 instance_->Start(); | 1034 instance_->Start(); |
| 1030 } else { | 1035 } else { |
| 1031 ASSERT(instance_->interval_ == sampler->interval()); | 1036 ASSERT(instance_->interval_ == sampler->interval()); |
| 1032 } | 1037 } |
| 1033 } | 1038 } |
| 1034 | 1039 |
| 1035 static void RemoveActiveSampler(Sampler* sampler) { | 1040 static void RemoveActiveSampler(Sampler* sampler) { |
| 1036 ScopedLock lock(mutex_); | 1041 ScopedLock lock(mutex_); |
| 1037 SamplerRegistry::RemoveActiveSampler(sampler); | 1042 SamplerRegistry::RemoveActiveSampler(sampler); |
| 1038 if (SamplerRegistry::GetState() == SamplerRegistry::HAS_NO_SAMPLERS) { | 1043 if (SamplerRegistry::GetState() == SamplerRegistry::HAS_NO_SAMPLERS) { |
| 1039 RuntimeProfiler::WakeUpRuntimeProfilerThreadBeforeShutdown(); | 1044 RuntimeProfiler::StopRuntimeProfilerThreadBeforeShutdown(instance_); |
| 1040 instance_->Join(); | |
| 1041 delete instance_; | 1045 delete instance_; |
| 1042 instance_ = NULL; | 1046 instance_ = NULL; |
| 1043 | 1047 RestoreSignalHandler(); |
| 1044 // Restore the old signal handler. | |
| 1045 if (signal_handler_installed_) { | |
| 1046 sigaction(SIGPROF, &old_signal_handler_, 0); | |
| 1047 signal_handler_installed_ = false; | |
| 1048 } | |
| 1049 } | 1048 } |
| 1050 } | 1049 } |
| 1051 | 1050 |
| 1052 // Implement Thread::Run(). | 1051 // Implement Thread::Run(). |
| 1053 virtual void Run() { | 1052 virtual void Run() { |
| 1054 SamplerRegistry::State state; | 1053 SamplerRegistry::State state; |
| 1055 while ((state = SamplerRegistry::GetState()) != | 1054 while ((state = SamplerRegistry::GetState()) != |
| 1056 SamplerRegistry::HAS_NO_SAMPLERS) { | 1055 SamplerRegistry::HAS_NO_SAMPLERS) { |
| 1057 bool cpu_profiling_enabled = | 1056 bool cpu_profiling_enabled = |
| 1058 (state == SamplerRegistry::HAS_CPU_PROFILING_SAMPLERS); | 1057 (state == SamplerRegistry::HAS_CPU_PROFILING_SAMPLERS); |
| 1059 bool runtime_profiler_enabled = RuntimeProfiler::IsEnabled(); | 1058 bool runtime_profiler_enabled = RuntimeProfiler::IsEnabled(); |
| 1059 if (cpu_profiling_enabled && !signal_handler_installed_) { |
| 1060 InstallSignalHandler(); |
| 1061 } else if (!cpu_profiling_enabled && signal_handler_installed_) { |
| 1062 RestoreSignalHandler(); |
| 1063 } |
| 1060 // When CPU profiling is enabled both JavaScript and C++ code is | 1064 // When CPU profiling is enabled both JavaScript and C++ code is |
| 1061 // profiled. We must not suspend. | 1065 // profiled. We must not suspend. |
| 1062 if (!cpu_profiling_enabled) { | 1066 if (!cpu_profiling_enabled) { |
| 1063 if (rate_limiter_.SuspendIfNecessary()) continue; | 1067 if (rate_limiter_.SuspendIfNecessary()) continue; |
| 1064 } | 1068 } |
| 1065 if (cpu_profiling_enabled && runtime_profiler_enabled) { | 1069 if (cpu_profiling_enabled && runtime_profiler_enabled) { |
| 1066 if (!SamplerRegistry::IterateActiveSamplers(&DoCpuProfile, this)) { | 1070 if (!SamplerRegistry::IterateActiveSamplers(&DoCpuProfile, this)) { |
| 1067 return; | 1071 return; |
| 1068 } | 1072 } |
| 1069 Sleep(HALF_INTERVAL); | 1073 Sleep(HALF_INTERVAL); |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1173 | 1177 |
| 1174 void Sampler::Stop() { | 1178 void Sampler::Stop() { |
| 1175 ASSERT(IsActive()); | 1179 ASSERT(IsActive()); |
| 1176 SignalSender::RemoveActiveSampler(this); | 1180 SignalSender::RemoveActiveSampler(this); |
| 1177 SetActive(false); | 1181 SetActive(false); |
| 1178 } | 1182 } |
| 1179 | 1183 |
| 1180 #endif // ENABLE_LOGGING_AND_PROFILING | 1184 #endif // ENABLE_LOGGING_AND_PROFILING |
| 1181 | 1185 |
| 1182 } } // namespace v8::internal | 1186 } } // namespace v8::internal |
| OLD | NEW |