1 /* 2 * Copyright (c) 2021-2024 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef PANDA_RUNTIME_TOOLING_SAMPLER_SAMPLING_PROFILER_H 17 #define PANDA_RUNTIME_TOOLING_SAMPLER_SAMPLING_PROFILER_H 18 19 #include <csignal> 20 21 #include "libpandabase/macros.h" 22 #include "libpandabase/os/pipe.h" 23 #include "runtime/include/panda_vm.h" 24 #include "runtime/include/runtime_notification.h" 25 #include "runtime/include/mem/panda_containers.h" 26 27 #include "runtime/tooling/sampler/sample_info.h" 28 #include "runtime/tooling/sampler/sample_writer.h" 29 #include "runtime/tooling/sampler/thread_communicator.h" 30 #include "runtime/tooling/sampler/lock_free_queue.h" 31 32 namespace ark::tooling::sampler { 33 34 namespace test { 35 class SamplerTest; 36 } // namespace test 37 38 // Panda sampling profiler 39 class Sampler final : public RuntimeListener { 40 public: 41 ~Sampler() override = default; 42 43 static PANDA_PUBLIC_API Sampler *Create(); 44 static PANDA_PUBLIC_API void Destroy(Sampler *sampler); 45 46 // Need to get comunicator inside the signal handler GetSampleCommunicator()47 static const ThreadCommunicator &GetSampleCommunicator() 48 { 49 ASSERT(instance_ != nullptr); 50 return instance_->GetCommunicator(); 51 } 52 GetCommunicator()53 const ThreadCommunicator &GetCommunicator() const 54 { 55 return communicator_; 56 } 57 GetSampleQueuePF()58 static const LockFreeQueue &GetSampleQueuePF() 59 { 60 ASSERT(instance_ != nullptr); 61 return instance_->GetQueuePF(); 62 } 63 GetQueuePF()64 const LockFreeQueue &GetQueuePF() 65 { 66 return loadedPfsQueue_; 67 } 68 SetSampleInterval(uint32_t us)69 void SetSampleInterval(uint32_t us) 70 { 71 ASSERT(isActive_ == false); 72 sampleInterval_ = static_cast<std::chrono::microseconds>(us); 73 } 74 SetSegvHandlerStatus(bool segvHandlerStatus)75 void SetSegvHandlerStatus(bool segvHandlerStatus) 76 { 77 isSegvHandlerEnable_ = segvHandlerStatus; 78 } 79 IsSegvHandlerEnable()80 bool IsSegvHandlerEnable() const 81 { 82 return isSegvHandlerEnable_; 83 } 84 85 PANDA_PUBLIC_API bool Start(const char *filename); 86 PANDA_PUBLIC_API void Stop(); 87 88 // Events: Notify profiler that managed thread created or finished 89 void ThreadStart(ManagedThread *managedThread) override; 90 void ThreadEnd(ManagedThread *managedThread) override; 91 void LoadModule(std::string_view name) override; 92 93 static constexpr uint32_t DEFAULT_SAMPLE_INTERVAL_US = 500; 94 95 private: 96 Sampler(); 97 98 void SamplerThreadEntry(); 99 void ListenerThreadEntry(std::string outputFile); 100 101 void AddThreadHandle(ManagedThread *thread); 102 void EraseThreadHandle(ManagedThread *thread); 103 104 void CollectThreads(); 105 void CollectModules(); 106 107 void WriteLoadedPandaFiles(StreamWriter *writerPtr); 108 ClearManagedThreadSet()109 void ClearManagedThreadSet() 110 { 111 os::memory::LockHolder holder(managedThreadsLock_); 112 managedThreads_.clear(); 113 } 114 ClearLoadedPfs()115 void ClearLoadedPfs() 116 { 117 os::memory::LockHolder holder(loadedPfsLock_); 118 loadedPfs_.clear(); 119 } 120 121 static Sampler *instance_; 122 123 Runtime *runtime_ {nullptr}; 124 // Remember agent thread id for security 125 os::thread::NativeHandleType listenerTid_ {0}; 126 os::thread::NativeHandleType samplerTid_ {0}; 127 std::unique_ptr<std::thread> samplerThread_ {nullptr}; 128 std::unique_ptr<std::thread> listenerThread_ {nullptr}; 129 ThreadCommunicator communicator_; 130 131 std::atomic<bool> isActive_ {false}; 132 bool isSegvHandlerEnable_ {true}; 133 134 PandaSet<os::thread::ThreadId> managedThreads_ GUARDED_BY(managedThreadsLock_); 135 os::memory::Mutex managedThreadsLock_; 136 137 LockFreeQueue loadedPfsQueue_; 138 139 PandaVector<FileInfo> loadedPfs_ GUARDED_BY(loadedPfsLock_); 140 os::memory::Mutex loadedPfsLock_; 141 142 std::chrono::microseconds sampleInterval_; 143 144 friend class test::SamplerTest; 145 146 NO_COPY_SEMANTIC(Sampler); 147 NO_MOVE_SEMANTIC(Sampler); 148 }; 149 150 } // namespace ark::tooling::sampler 151 152 #endif // PANDA_RUNTIME_TOOLING_SAMPLER_SAMPLING_PROFILER_H 153