• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved.
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 #include "ffrt_profiler_manager.h"
17 
18 #include <sys/types.h>
19 #include <sys/stat.h>
20 #include <unistd.h>
21 #include <map>
22 
23 #include "logging.h"
24 #include "init_param.h"
25 #include "common.h"
26 #include "ffrt_profiler_common.h"
27 #include "plugin_service_types.pb.h"
28 #include "command_poller.h"
29 #include "epoll_event_poller.h"
30 #include "event_notifier.h"
31 
32 namespace {
33 constexpr int DEFAULT_EVENT_POLLING_INTERVAL = 5000;
34 constexpr uint32_t PAGE_BYTES = 4096;
35 constexpr uint32_t BUFFER_SIZE = (1UL << 23);
36 const std::string VERSION = "1.02";
37 std::shared_ptr<Writer> g_buffWriter = nullptr;
38 }
39 
40 namespace OHOS::Developtools::Profiler {
FfrtProfilerManager()41 FfrtProfilerManager::FfrtProfilerManager()
42 {
43 }
44 
~FfrtProfilerManager()45 FfrtProfilerManager::~FfrtProfilerManager()
46 {
47     StopFfrtProfiler();
48 }
49 
Init()50 void FfrtProfilerManager::Init()
51 {
52     auto commandPoller = std::make_shared<CommandPoller>(shared_from_this());
53     CHECK_NOTNULL(commandPoller, NO_RETVAL, "create CommandPoller FAILED!");
54     CHECK_TRUE(commandPoller->OnConnect(), NO_RETVAL, "FfrtProfilerManager::Init connect FAILED");
55     SetCommandPoller(commandPoller);
56     RegisterAgentPlugin("ffrt-profiler");
57 }
58 
CheckConfig()59 bool FfrtProfilerManager::CheckConfig()
60 {
61     std::set<int32_t> pidCache;
62     for (const auto& pid : config_.pid()) {
63         if (pid > 0) {
64             struct stat statBuf;
65             std::string pidPath = "/proc/" + std::to_string(pid) + "/status";
66             if (stat(pidPath.c_str(), &statBuf) != 0) {
67                 PROFILER_LOG_ERROR(LOG_CORE, "%s: hook process does not exist", __func__);
68                 return false;
69             } else {
70                 auto [iter, ret] = pidCache.emplace(pid);
71                 if (ret) {
72                     ffrtCtx_.emplace_back(std::make_shared<FfrtProfilerCtx>(pid));
73                     paramValue_ += std::to_string(pid) + ",";
74                 }
75                 continue;
76             }
77         }
78     }
79 
80     for (const auto& name : config_.startup_process_name()) {
81         if (name.empty()) {
82             continue;
83         }
84         int pidValue = -1;
85         bool isExist = COMMON::IsProcessExist(name, pidValue);
86         if (isExist) {
87             PROFILER_LOG_ERROR(LOG_CORE, "FfrtProfilerManager Process %s already exists", name.c_str());
88             return false;
89         } else {
90             paramValue_ += name + ",";
91             ffrtCtx_.emplace_back(std::make_shared<FfrtProfilerCtx>(name));
92         }
93     }
94 
95     for (const auto& name : config_.restart_process_name()) {
96         if (name.empty()) {
97             continue;
98         }
99 
100         int pidValue = -1;
101         bool isExist = COMMON::IsProcessExist(name, pidValue);
102         if (isExist) {
103             auto [iter, ret] = pidCache.emplace(pidValue);
104             if (!ret) {
105                 PROFILER_LOG_ERROR(LOG_CORE,
106                     "FfrtProfilerManager process %s pid is %d, duplicate of pid list in config",
107                     name.c_str(), pidValue);
108                 return false;
109             }
110             paramValue_ += name + ",";
111             ffrtCtx_.emplace_back(std::make_shared<FfrtProfilerCtx>(pidValue, name, true));
112         } else {
113             PROFILER_LOG_ERROR(LOG_CORE, "FfrtProfilerManager Process %s does not exist", name.c_str());
114             return false;
115         }
116     }
117 
118     if (config_.flush_interval() == 0) {
119         config_.set_flush_interval(1);
120     }
121 
122     if (config_.clock_id() == FfrtProfilerConfig::UNKNOW) {
123         PROFILER_LOG_ERROR(LOG_CORE, "FfrtProfilerManager clock_id is unknow");
124         return false;
125     }
126     return true;
127 }
128 
GetClockId(FfrtProfilerConfig::ClockId clockType)129 clockid_t FfrtProfilerManager::GetClockId(FfrtProfilerConfig::ClockId clockType)
130 {
131     std::map<FfrtProfilerConfig::ClockId, clockid_t> clockMap = {
132         {FfrtProfilerConfig::BOOTTIME, CLOCK_BOOTTIME},
133         {FfrtProfilerConfig::REALTIME, CLOCK_REALTIME},
134         {FfrtProfilerConfig::REALTIME_COARSE, CLOCK_REALTIME_COARSE},
135         {FfrtProfilerConfig::MONOTONIC, CLOCK_MONOTONIC},
136         {FfrtProfilerConfig::MONOTONIC_COARSE, CLOCK_MONOTONIC_COARSE},
137         {FfrtProfilerConfig::MONOTONIC_RAW, CLOCK_MONOTONIC_RAW},
138     };
139 
140     return clockMap.find(clockType) != clockMap.end() ? clockMap[clockType] : CLOCK_BOOTTIME;
141 }
142 
StartFfrtProfiler()143 bool FfrtProfilerManager::StartFfrtProfiler()
144 {
145     if (!CheckConfig()) {
146         PROFILER_LOG_ERROR(LOG_CORE, "StartFfrtProfiler CheckConfig failed");
147         return false;
148     }
149     if (paramValue_.empty() || ffrtCtx_.empty()) {
150         PROFILER_LOG_ERROR(LOG_CORE, "StartFfrtProfiler ctx is empty");
151         return false;
152     }
153 
154     for (auto& item : ffrtCtx_) {
155         CHECK_TRUE(HandleFfrtProfilerContext(item), false, "HandleFfrtProfilerContext failed");
156     }
157 
158     socketService_ = std::make_shared<FfrtProfilerSocketService>(shared_from_this());
159     socketService_->SetConfig(config_.smb_pages() * PAGE_BYTES, config_.flush_interval(),
160         config_.block(), GetClockId(config_.clock_id()));
161 
162     int ret = SystemSetParameter(PARAM_KAY.c_str(), paramValue_.c_str());
163     PROFILER_LOG_INFO(LOG_CORE, "StartFfrtProfiler parameter: %s", paramValue_.c_str());
164     if (ret < 0) {
165         PROFILER_LOG_ERROR(LOG_CORE, "StartFfrtProfiler set parameter failed");
166         return false;
167     } else {
168         PROFILER_LOG_INFO(LOG_CORE, "StartFfrtProfiler set parameter success");
169     }
170     return true;
171 }
172 
StopFfrtProfiler()173 void FfrtProfilerManager::StopFfrtProfiler()
174 {
175     int ret = SystemSetParameter(PARAM_KAY.c_str(), "");
176     if (ret < 0) {
177         PROFILER_LOG_ERROR(LOG_CORE, "StopFfrtProfiler set parameter failed");
178     } else {
179         PROFILER_LOG_INFO(LOG_CORE, "StopFfrtProfiler set parameter success");
180     }
181 
182     socketService_ = nullptr;
183 
184     for (const auto& item : ffrtCtx_) {
185         if (item->eventPoller != nullptr) {
186             HILOG_BASE_ERROR(LOG_CORE, "eventPoller unset!");
187             if (item->eventNotifier != nullptr) {
188                 item->eventPoller->RemoveFileDescriptor(item->eventNotifier->GetFd());
189             }
190             item->eventPoller->Stop();
191             item->eventPoller->Finalize();
192             item->eventPoller = nullptr;
193         }
194 
195         if (item->shareMemoryBlock != nullptr) {
196             ShareMemoryAllocator::GetInstance().ReleaseMemoryBlockLocal(item->smbName);
197             item->shareMemoryBlock = nullptr;
198         }
199         if (item->eventNotifier != nullptr) {
200             item->eventNotifier = nullptr;
201         }
202         item->handle = nullptr;
203     }
204 }
205 
HandleFfrtProfilerContext(const std::shared_ptr<FfrtProfilerCtx> & ctx)206 bool FfrtProfilerManager::HandleFfrtProfilerContext(const std::shared_ptr<FfrtProfilerCtx>& ctx)
207 {
208     if (ctx == nullptr) {
209         return false;
210     }
211     if (ctx->pid > 0) {
212         ctx->smbName = "ffrt_profiler_smb_" + std::to_string(ctx->pid);
213     } else if (!ctx->processName.empty()) {
214         ctx->smbName = "ffrt_profiler_smb_" + ctx->processName;
215     } else {
216         PROFILER_LOG_ERROR(LOG_CORE, "HandleHookContext context error, pid: %d, process name: %s",
217             ctx->pid, ctx->processName.c_str());
218         return false;
219     }
220 
221     uint32_t bufferSize = static_cast<uint32_t>(config_.smb_pages() * PAGE_BYTES);
222     ctx->shareMemoryBlock = ShareMemoryAllocator::GetInstance().CreateMemoryBlockLocal(ctx->smbName, bufferSize);
223     CHECK_TRUE(ctx->shareMemoryBlock != nullptr, false, "CreateMemoryBlockLocal FAIL %s", ctx->smbName.c_str());
224 
225     ctx->eventNotifier = EventNotifier::Create(0, EventNotifier::NONBLOCK);
226     CHECK_NOTNULL(ctx->eventNotifier, false, "create EventNotifier for %s failed!", ctx->smbName.c_str());
227 
228     // start event poller task
229     ctx->eventPoller = std::make_unique<EpollEventPoller>(DEFAULT_EVENT_POLLING_INTERVAL);
230     CHECK_NOTNULL(ctx->eventPoller, false, "create event poller FAILED!");
231 
232     ctx->eventPoller->Init();
233     ctx->eventPoller->Start();
234 
235     PROFILER_LOG_INFO(LOG_CORE, "%s smbFd = %d, eventFd = %d\n", ctx->smbName.c_str(),
236         ctx->shareMemoryBlock->GetfileDescriptor(), ctx->eventNotifier->GetFd());
237 
238     ctx->handle = std::make_shared<FfrtProfilerHandle>(BUFFER_SIZE, isProtobufSerialize_);
239     if (isProtobufSerialize_) {
240         ctx->handle->SetWriter(g_buffWriter);
241     } else {
242         ctx->handle->SetWriter(const_cast<WriterStructPtr>(writerAdapter_->GetStruct()));
243     }
244 
245     ctx->eventPoller->AddFileDescriptor(
246         ctx->eventNotifier->GetFd(),
247         [this, ctx] { this->ReadShareMemory(ctx); }
248     );
249     PROFILER_LOG_DEBUG(LOG_CORE, "ffrt profiler context: pid: %d, processName: %s, eventFd: %d, shmFd: %d",
250         ctx->pid, ctx->processName.c_str(), ctx->eventNotifier->GetFd(), ctx->shareMemoryBlock->GetfileDescriptor());
251     return true;
252 }
253 
ReadShareMemory(std::shared_ptr<FfrtProfilerCtx> ctx)254 void FfrtProfilerManager::ReadShareMemory(std::shared_ptr<FfrtProfilerCtx> ctx)
255 {
256     ctx->eventNotifier->Take();
257     while (true) {
258         bool ret = ctx->shareMemoryBlock->TakeData([&](const int8_t data[], uint32_t size) -> bool {
259             ctx->handle->SerializeData(data, size);
260             return true;
261         });
262         if (!ret) {
263             break;
264         }
265     }
266 }
267 
GetFfrtProfilerCtx(int32_t pid,const std::string & name)268 std::pair<int, int> FfrtProfilerManager::GetFfrtProfilerCtx(int32_t pid, const std::string& name)
269 {
270     for (const auto& item : ffrtCtx_) {
271         if (item->pid == pid || item->processName == name) {
272             if (item->restart && (item->pid == pid)) {
273                 return {0, 0};
274             }
275             PROFILER_LOG_DEBUG(LOG_CORE, "GetFfrtProfilerCtx: pid: %d, name: %s, eventFd: %d, shmFd: %d",
276                 pid, name.c_str(), item->eventNotifier->GetFd(), item->shareMemoryBlock->GetfileDescriptor());
277             item->handle->SetTargetProcessInfo(pid, name);
278             return {item->eventNotifier->GetFd(), item->shareMemoryBlock->GetfileDescriptor()};
279         }
280     }
281     return {-1, -1};
282 }
283 
LoadPlugin(const std::string & pluginPath)284 bool FfrtProfilerManager::LoadPlugin(const std::string& pluginPath)
285 {
286     return true;
287 }
288 
UnloadPlugin(const std::string & pluginPath)289 bool FfrtProfilerManager::UnloadPlugin(const std::string& pluginPath)
290 {
291     return true;
292 }
293 
UnloadPlugin(const uint32_t pluginId)294 bool FfrtProfilerManager::UnloadPlugin(const uint32_t pluginId)
295 {
296     return true;
297 }
298 
CreatePluginSession(const std::vector<ProfilerPluginConfig> & config)299 bool FfrtProfilerManager::CreatePluginSession(const std::vector<ProfilerPluginConfig>& config)
300 {
301     std::string cfgData = config[0].config_data();
302     if (config_.ParseFromArray(reinterpret_cast<const uint8_t*>(cfgData.c_str()), cfgData.size()) <= 0) {
303         PROFILER_LOG_ERROR(LOG_CORE, "%s:parseFromArray failed!", __func__);
304         return false;
305     }
306     return true;
307 }
308 
DestroyPluginSession(const std::vector<uint32_t> & pluginIds)309 bool FfrtProfilerManager::DestroyPluginSession(const std::vector<uint32_t>& pluginIds)
310 {
311     socketService_ = nullptr;
312     return true;
313 }
314 
StartPluginSession(const std::vector<uint32_t> & pluginIds,const std::vector<ProfilerPluginConfig> & config,PluginResult & result)315 bool FfrtProfilerManager::StartPluginSession(const std::vector<uint32_t>& pluginIds,
316     const std::vector<ProfilerPluginConfig>& config, PluginResult& result)
317 {
318     return StartFfrtProfiler();
319 }
320 
StopPluginSession(const std::vector<uint32_t> & pluginIds)321 bool FfrtProfilerManager::StopPluginSession(const std::vector<uint32_t>& pluginIds)
322 {
323     StopFfrtProfiler();
324     return true;
325 }
326 
ReportPluginBasicData(const std::vector<uint32_t> & pluginIds)327 bool FfrtProfilerManager::ReportPluginBasicData(const std::vector<uint32_t>& pluginIds)
328 {
329     return true;
330 }
331 
CreateWriter(std::string pluginName,uint32_t bufferSize,int smbFd,int eventFd,bool isProtobufSerialize)332 bool FfrtProfilerManager::CreateWriter(std::string pluginName, uint32_t bufferSize, int smbFd, int eventFd,
333     bool isProtobufSerialize)
334 {
335     PROFILER_LOG_INFO(LOG_CORE, "ffrt CreateWriter isProtobufSerialize: %d", isProtobufSerialize);
336     writer_ = std::make_shared<BufferWriter>("ffrt-profiler", VERSION, bufferSize, smbFd, eventFd, agentIndex_);
337     isProtobufSerialize_ = isProtobufSerialize;
338     if (!isProtobufSerialize_) {
339         writerAdapter_ = std::make_shared<WriterAdapter>(isProtobufSerialize_);
340         writerAdapter_->SetWriter(writer_);
341     } else {
342         g_buffWriter = writer_;
343     }
344     return true;
345 }
346 
ResetWriter(uint32_t pluginId)347 bool FfrtProfilerManager::ResetWriter(uint32_t pluginId)
348 {
349     g_buffWriter = nullptr;
350     return true;
351 }
352 
SetCommandPoller(const std::shared_ptr<CommandPoller> & p)353 void FfrtProfilerManager::SetCommandPoller(const std::shared_ptr<CommandPoller>& p)
354 {
355     commandPoller_ = p;
356 }
357 
RegisterAgentPlugin(const std::string & pluginPath)358 bool FfrtProfilerManager::RegisterAgentPlugin(const std::string& pluginPath)
359 {
360     RegisterPluginRequest request;
361     request.set_request_id(commandPoller_->GetRequestId());
362     request.set_path("builtin/" + pluginPath);
363     request.set_sha256("");
364     request.set_name(pluginPath);
365     request.set_buffer_size_hint(0);
366     RegisterPluginResponse response;
367 
368     if (commandPoller_->RegisterPlugin(request, response)) {
369         if (response.status() == ResponseStatus::OK) {
370             PROFILER_LOG_DEBUG(LOG_CORE, "response.plugin_id() = %d", response.plugin_id());
371             agentIndex_ = static_cast<int>(response.plugin_id());
372             PROFILER_LOG_DEBUG(LOG_CORE, "RegisterPlugin OK");
373         } else {
374             PROFILER_LOG_DEBUG(LOG_CORE, "RegisterPlugin FAIL 1");
375             return false;
376         }
377     } else {
378         PROFILER_LOG_DEBUG(LOG_CORE, "RegisterPlugin FAIL 2");
379         return false;
380     }
381     return true;
382 }
383 } // namespace OHOS::Developtools::Profiler
384