• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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