• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022-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 #include <asm/unistd.h>
17 #include <atomic>
18 #include <cinttypes>
19 #include <climits>
20 #include <ctime>
21 #include <cerrno>
22 #include <fcntl.h>
23 #include <fstream>
24 #include <linux/perf_event.h>
25 #include <memory>
26 #include <mutex>
27 #include <sched.h>
28 #include <sys/ioctl.h>
29 #include <sys/stat.h>
30 #include <unistd.h>
31 #include <vector>
32 #include <string>
33 
34 #include "common_define.h"
35 #include "common_utils.h"
36 #include "securec.h"
37 #include "hilog/log.h"
38 #include "param/sys_param.h"
39 #include "parameter.h"
40 #include "parameters.h"
41 #include "hitrace_meter.h"
42 #include "hitrace/tracechain.h"
43 
44 #ifdef LOG_DOMAIN
45 #undef LOG_DOMAIN
46 #define LOG_DOMAIN 0xD002D33
47 #endif
48 #ifdef LOG_TAG
49 #undef LOG_TAG
50 #define LOG_TAG "HitraceMeter"
51 #endif
52 
53 using namespace OHOS::HiviewDFX;
54 
55 namespace {
56 int g_markerFd = -1;
57 int g_appFd = -1;
58 std::once_flag g_onceFlag;
59 std::once_flag g_onceWriteMarkerFailedFlag;
60 std::atomic<CachedHandle> g_cachedHandle;
61 std::atomic<CachedHandle> g_appPidCachedHandle;
62 
63 std::atomic<bool> g_isHitraceMeterDisabled(false);
64 std::atomic<bool> g_isHitraceMeterInit(false);
65 std::atomic<bool> g_needReloadPid(false);
66 std::atomic<bool> g_pidHasReload(false);
67 
68 std::atomic<uint64_t> g_tagsProperty(HITRACE_TAG_NOT_READY);
69 std::atomic<uint64_t> g_appTag(HITRACE_TAG_NOT_READY);
70 std::atomic<int64_t> g_appTagMatchPid(-1);
71 
72 const std::string SANDBOX_PATH = "/data/storage/el2/log/";
73 const std::string PHYSICAL_PATH = "/data/app/el2/100/log/";
74 
75 constexpr int VAR_NAME_MAX_SIZE = 400;
76 constexpr int NAME_NORMAL_LEN = 512;
77 constexpr int BUFFER_LEN = 640;
78 constexpr int HITRACEID_LEN = 64;
79 
80 static const int PID_BUF_SIZE = 6;
81 static char g_pid[PID_BUF_SIZE];
82 static const std::string EMPTY_TRACE_NAME;
83 static char g_appName[NAME_NORMAL_LEN + 1] = {0};
84 static std::string g_appTracePrefix = "";
85 constexpr const int COMM_STR_MAX = 14;
86 constexpr const int PID_STR_MAX = 7;
87 constexpr const int PREFIX_MAX_SIZE = 128; // comm-pid (tgid) [cpu] .... ts.tns: tracing_mark_write:
88 constexpr const int TRACE_TXT_HEADER_MAX = 1024;
89 constexpr const int CPU_CORE_NUM = 16;
90 constexpr const int DEFAULT_CACHE_SIZE = 32 * 1024;
91 constexpr const int MAX_FILE_SIZE = 500 * 1024 * 1024;
92 constexpr const int NS_TO_MS = 1000;
93 int g_tgid = -1;
94 uint64_t g_traceEventNum = 0;
95 int g_writeOffset = 0;
96 int g_fileSize = 0;
97 TraceFlag g_appFlag(FLAG_MAIN_THREAD);
98 std::atomic<uint64_t> g_fileLimitSize(0);
99 std::unique_ptr<char[]> g_traceBuffer;
100 std::recursive_mutex g_appTraceMutex;
101 
102 static char g_markTypes[5] = {'B', 'E', 'S', 'F', 'C'};
103 enum MarkerType { MARKER_BEGIN, MARKER_END, MARKER_ASYNC_BEGIN, MARKER_ASYNC_END, MARKER_INT, MARKER_MAX };
104 
105 const uint64_t VALID_TAGS = HITRACE_TAG_FFRT | HITRACE_TAG_COMMONLIBRARY | HITRACE_TAG_HDF | HITRACE_TAG_NET |
106     HITRACE_TAG_NWEB | HITRACE_TAG_DISTRIBUTED_AUDIO | HITRACE_TAG_FILEMANAGEMENT | HITRACE_TAG_OHOS |
107     HITRACE_TAG_ABILITY_MANAGER | HITRACE_TAG_ZCAMERA | HITRACE_TAG_ZMEDIA | HITRACE_TAG_ZIMAGE | HITRACE_TAG_ZAUDIO |
108     HITRACE_TAG_DISTRIBUTEDDATA | HITRACE_TAG_GRAPHIC_AGP | HITRACE_TAG_ACE | HITRACE_TAG_NOTIFICATION |
109     HITRACE_TAG_MISC | HITRACE_TAG_MULTIMODALINPUT | HITRACE_TAG_RPC | HITRACE_TAG_ARK | HITRACE_TAG_WINDOW_MANAGER |
110     HITRACE_TAG_DISTRIBUTED_SCREEN | HITRACE_TAG_DISTRIBUTED_CAMERA | HITRACE_TAG_DISTRIBUTED_HARDWARE_FWK |
111     HITRACE_TAG_GLOBAL_RESMGR | HITRACE_TAG_DEVICE_MANAGER | HITRACE_TAG_SAMGR | HITRACE_TAG_POWER |
112     HITRACE_TAG_DISTRIBUTED_SCHEDULE | HITRACE_TAG_DISTRIBUTED_INPUT | HITRACE_TAG_BLUETOOTH | HITRACE_TAG_APP;
113 
114 const std::string TRACE_TXT_HEADER_FORMAT = R"(# tracer: nop
115 #
116 # entries-in-buffer/entries-written: %-21s   #P:%-3s
117 #
118 #                                          _-----=> irqs-off
119 #                                         / _----=> need-resched
120 #                                        | / _---=> hardirq/softirq
121 #                                        || / _--=> preempt-depth
122 #                                        ||| /     delay
123 #           TASK-PID       TGID    CPU#  ||||   TIMESTAMP  FUNCTION
124 #              | |           |       |   ||||      |         |
125 )";
126 
CreateCacheHandle()127 inline void CreateCacheHandle()
128 {
129     const char* devValue = "true";
130     g_cachedHandle = CachedParameterCreate(TRACE_TAG_ENABLE_FLAGS.c_str(), devValue);
131     g_appPidCachedHandle = CachedParameterCreate(TRACE_KEY_APP_PID.c_str(), devValue);
132 }
133 
UpdateSysParamTags()134 inline void UpdateSysParamTags()
135 {
136     // Get the system parameters of TRACE_TAG_ENABLE_FLAGS.
137     int changed = 0;
138     if (UNEXPECTANTLY(g_cachedHandle == nullptr || g_appPidCachedHandle == nullptr)) {
139         CreateCacheHandle();
140         return;
141     }
142     const char *paramValue = CachedParameterGetChanged(g_cachedHandle, &changed);
143     if (UNEXPECTANTLY(changed == 1) && paramValue != nullptr) {
144         uint64_t tags = 0;
145         if (!OHOS::HiviewDFX::Hitrace::StringToUint64(paramValue, tags)) {
146             return;
147         }
148         g_tagsProperty = (tags | HITRACE_TAG_ALWAYS) & HITRACE_TAG_VALID_MASK;
149     }
150     int appPidChanged = 0;
151     const char *paramPid = CachedParameterGetChanged(g_appPidCachedHandle, &appPidChanged);
152     if (UNEXPECTANTLY(appPidChanged == 1) && paramPid != nullptr) {
153         int64_t appTagMatchPid = -1;
154         if (!OHOS::HiviewDFX::Hitrace::StringToInt64(paramPid, appTagMatchPid)) {
155             return;
156         }
157         g_appTagMatchPid = appTagMatchPid;
158     }
159 }
160 
IsAppspawnProcess()161 bool IsAppspawnProcess()
162 {
163     std::string procName;
164     std::ifstream cmdline("/proc/self/cmdline");
165     if (cmdline.is_open()) {
166         getline(cmdline, procName, '\0');
167         cmdline.close();
168     }
169     return procName == "appspawn" || procName == "nwebspawn" || procName == "cjappspawn" || procName == "nativespawn";
170 }
171 
InitPid()172 void InitPid()
173 {
174     std::string pidStr = std::to_string(getprocpid());
175     int ret = strcpy_s(g_pid, PID_BUF_SIZE, pidStr.c_str());
176     if (ret != 0) {
177         HILOG_ERROR(LOG_CORE, "pid[%{public}s] strcpy_s fail ret: %{public}d.", pidStr.c_str(), ret);
178         return;
179     }
180 
181     if (!g_needReloadPid && IsAppspawnProcess()) {
182         // appspawn restarted, all app need init pid again.
183         g_needReloadPid = true;
184     }
185 
186     HILOG_INFO(LOG_CORE, "pid[%{public}s] first get g_tagsProperty: %{public}s", pidStr.c_str(),
187         std::to_string(g_tagsProperty.load()).c_str());
188 }
189 
ReloadPid()190 void ReloadPid()
191 {
192     std::string pidStr = std::to_string(getprocpid());
193     int ret = strcpy_s(g_pid, PID_BUF_SIZE, pidStr.c_str());
194     if (ret != 0) {
195         HILOG_ERROR(LOG_CORE, "pid[%{public}s] strcpy_s fail ret: %{public}d.", pidStr.c_str(), ret);
196         return;
197     }
198     if (!IsAppspawnProcess()) {
199         // appspawn restarted, all app need reload pid again.
200         g_pidHasReload = true;
201     }
202 }
203 
204 // open file "trace_marker".
OpenTraceMarkerFile()205 void OpenTraceMarkerFile()
206 {
207     const std::string debugFile = DEBUGFS_TRACING_DIR + TRACE_MARKER_NODE;
208     const std::string traceFile = TRACEFS_DIR + TRACE_MARKER_NODE;
209     g_markerFd = open(debugFile.c_str(), O_WRONLY | O_CLOEXEC);
210 #ifdef HITRACE_UNITTEST
211     SetMarkerFd(g_markerFd);
212 #endif
213     if (g_markerFd == -1) {
214         HILOG_ERROR(LOG_CORE, "open trace file %{public}s failed: %{public}d", debugFile.c_str(), errno);
215         g_markerFd = open(traceFile.c_str(), O_WRONLY | O_CLOEXEC);
216         if (g_markerFd == -1) {
217             HILOG_ERROR(LOG_CORE, "open trace file %{public}s failed: %{public}d", traceFile.c_str(), errno);
218             g_tagsProperty = 0;
219             return;
220         }
221     }
222     // get tags and pid
223     g_tagsProperty = OHOS::system::GetUintParameter<uint64_t>(TRACE_TAG_ENABLE_FLAGS, 0);
224     CreateCacheHandle();
225     InitPid();
226 
227     g_isHitraceMeterInit = true;
228 }
229 
WriteFailedLog()230 void WriteFailedLog()
231 {
232     HILOG_ERROR(LOG_CORE, "write trace_marker failed, %{public}d", errno);
233 }
234 
WriteToTraceMarker(const char * buf,const int count)235 void WriteToTraceMarker(const char* buf, const int count)
236 {
237     if (UNEXPECTANTLY(count <= 0 || count >= BUFFER_LEN)) {
238         HILOG_INFO(LOG_CORE, "Write trace canceled, buf size is greater than the BUFFER_LEN");
239         return;
240     }
241     if (write(g_markerFd, buf, count) < 0) {
242         std::call_once(g_onceWriteMarkerFailedFlag, WriteFailedLog);
243     }
244 }
245 
AddTraceMarkerLarge(const std::string & name,MarkerType type,const int64_t value)246 void AddTraceMarkerLarge(const std::string& name, MarkerType type, const int64_t value)
247 {
248     std::string record;
249     record += g_markTypes[type];
250     record += "|";
251     record += g_pid;
252     record += "|H:";
253     HiTraceId hiTraceId = HiTraceChain::GetId();
254     if (hiTraceId.IsValid()) {
255         char buf[HITRACEID_LEN] = {0};
256         int bytes = snprintf_s(buf, sizeof(buf), sizeof(buf) - 1, "[%llx,%llx,%llx]#",
257             hiTraceId.GetChainId(), hiTraceId.GetSpanId(), hiTraceId.GetParentSpanId());
258         if (EXPECTANTLY(bytes > 0)) {
259             record += buf;
260         }
261     }
262     record += name;
263     record += " ";
264     if (value != 0) {
265         record += std::to_string(value);
266     }
267     WriteToTraceMarker(record.c_str(), record.size());
268 }
269 
WriteOnceLog(LogLevel loglevel,const std::string & logStr,bool & isWrite)270 void WriteOnceLog(LogLevel loglevel, const std::string& logStr, bool& isWrite)
271 {
272     if (!isWrite) {
273         switch (loglevel) {
274             case LOG_ERROR: {
275                 HILOG_ERROR(LOG_CORE, "%{public}s: %{public}d(%{public}s)", logStr.c_str(), errno, strerror(errno));
276                 break;
277             }
278             case LOG_INFO: {
279                 HILOG_INFO(LOG_CORE, "%{public}s", logStr.c_str());
280                 break;
281             }
282             default: {
283                 break;
284             }
285         }
286         isWrite = true;
287     }
288 }
289 
GetProcData(const char * file,char * buffer,const size_t bufferSize)290 bool GetProcData(const char* file, char* buffer, const size_t bufferSize)
291 {
292     FILE* fp = fopen(file, "r");
293     if (fp == nullptr) {
294         static bool isWriteLog = false;
295         std::string errLogStr = std::string(__func__) + ": open " + std::string(file) + " failed";
296         WriteOnceLog(LOG_ERROR, errLogStr, isWriteLog);
297         return false;
298     }
299 
300     if (fgets(buffer, bufferSize, fp) == nullptr) {
301         (void)fclose(fp);
302         static bool isWriteLog = false;
303         std::string errLogStr = std::string(__func__) + ": fgets " + std::string(file) + " failed";
304         WriteOnceLog(LOG_ERROR, errLogStr, isWriteLog);
305         return false;
306     }
307 
308     if (fclose(fp) != 0) {
309         static bool isWriteLog = false;
310         std::string errLogStr = std::string(__func__) + ": fclose " + std::string(file) + " failed";
311         WriteOnceLog(LOG_ERROR, errLogStr, isWriteLog);
312         return false;
313     }
314 
315     return true;
316 }
317 
CheckAppTraceArgs(TraceFlag flag,uint64_t tags,uint64_t limitSize)318 int CheckAppTraceArgs(TraceFlag flag, uint64_t tags, uint64_t limitSize)
319 {
320     if (flag != FLAG_MAIN_THREAD && flag != FLAG_ALL_THREAD) {
321         HILOG_ERROR(LOG_CORE, "flag(%{public}" PRId32 ") is invalid", flag);
322         return RET_FAIL_INVALID_ARGS;
323     }
324 
325     if (static_cast<int64_t>(tags) < 0 || !UNEXPECTANTLY(tags & VALID_TAGS)) {
326         HILOG_ERROR(LOG_CORE, "tags(%{public}" PRId64 ") is invalid", tags);
327         return RET_FAIL_INVALID_ARGS;
328     }
329 
330     if (static_cast<int64_t>(limitSize) <= 0) {
331         HILOG_ERROR(LOG_CORE, "limitSize(%{public}" PRId64 ") is invalid", limitSize);
332         return RET_FAIL_INVALID_ARGS;
333     }
334 
335     return RET_SUCC;
336 }
337 
SetAppFileName(std::string & destFileName,std::string & fileName)338 int SetAppFileName(std::string& destFileName, std::string& fileName)
339 {
340     destFileName = SANDBOX_PATH + "trace/";
341     mode_t permissions = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; // 0755
342 #ifdef HITRACE_UNITTEST
343     destFileName = "/data/local/tmp/";
344 #endif
345     if (access(destFileName.c_str(), F_OK) != 0 && mkdir(destFileName.c_str(), permissions) == -1) {
346         HILOG_ERROR(LOG_CORE, "failed to create dir(%{public}s):%{public}d(%{public}s)", destFileName.c_str(),
347             errno, strerror(errno));
348         return RET_FAIL_MKDIR;
349     }
350 
351     if (!GetProcData("/proc/self/cmdline", g_appName, NAME_NORMAL_LEN)) {
352         HILOG_ERROR(LOG_CORE, "get app name failed, %{public}d", errno);
353         return RET_FAILD;
354     }
355 
356     time_t now = time(nullptr);
357     if (now == static_cast<time_t>(-1)) {
358         HILOG_ERROR(LOG_CORE, "get time failed, %{public}d", errno);
359         return RET_FAILD;
360     }
361 
362     struct tm tmTime;
363     if (localtime_r(&now, &tmTime) == nullptr) {
364         HILOG_ERROR(LOG_CORE, "localtime_r failed, %{public}d", errno);
365         return RET_FAILD;
366     }
367 
368     const int yearCount = 1900;
369     const int size = sizeof(g_appName) + 32;
370     char file[size] = {0};
371     auto ret = snprintf_s(file, sizeof(file), sizeof(file) - 1, "%s_%04d%02d%02d_%02d%02d%02d.trace", g_appName,
372         tmTime.tm_year + yearCount, tmTime.tm_mon + 1, tmTime.tm_mday, tmTime.tm_hour, tmTime.tm_min, tmTime.tm_sec);
373     if (ret <= 0) {
374         HILOG_ERROR(LOG_CORE, "Format file failed, %{public}d", errno);
375         return RET_FAILD;
376     }
377 
378     destFileName += std::string(file);
379     fileName = PHYSICAL_PATH + std::string(g_appName) + "/trace/" + std::string(file);
380     return RET_SUCC;
381 }
382 
InitTraceHead()383 int InitTraceHead()
384 {
385     // write reserved trace header
386     std::vector<char> buffer(TRACE_TXT_HEADER_MAX, '\0');
387     int used = snprintf_s(buffer.data(), buffer.size(), buffer.size() - 1, TRACE_TXT_HEADER_FORMAT.c_str(), "", "");
388     if (used <= 0) {
389         HILOG_ERROR(LOG_CORE, "format reserved trace header failed: %{public}d(%{public}s)", errno, strerror(errno));
390         return RET_FAILD;
391     }
392     if (write(g_appFd, buffer.data(), used) != used) {
393         HILOG_ERROR(LOG_CORE, "write reserved trace header failed: %{public}d(%{public}s)", errno, strerror(errno));
394         return RET_FAILD;
395     }
396 
397     g_writeOffset = 0;
398     g_fileSize = used;
399     g_traceEventNum = 0;
400 
401     lseek(g_appFd, used, SEEK_SET); // Reserve space to write the file header.
402     return RET_SUCC;
403 }
404 
WriteTraceToFile(char * buf,const int len)405 bool WriteTraceToFile(char* buf, const int len)
406 {
407     if (write(g_appFd, buf, len) != len) {
408         static bool isWriteLog = false;
409         WriteOnceLog(LOG_ERROR, "write app trace data failed", isWriteLog);
410         return false;
411     }
412 
413     g_fileSize += len;
414     g_writeOffset = 0;
415     return true;
416 }
417 
GetTraceBuffer(int size)418 char* GetTraceBuffer(int size)
419 {
420     if ((g_writeOffset + size) > DEFAULT_CACHE_SIZE && (g_writeOffset + size) < MAX_FILE_SIZE) {
421         // The remaining space is insufficient to cache the data. Write the data to the file.
422         if (!WriteTraceToFile(g_traceBuffer.get(), g_writeOffset)) {
423             return nullptr;
424         }
425     }
426 
427     return g_traceBuffer.get() + g_writeOffset;
428 }
429 
SetCommStr()430 void SetCommStr()
431 {
432     int size = g_appTracePrefix.size();
433     if (size >= COMM_STR_MAX) {
434         g_appTracePrefix = g_appTracePrefix.substr(size - COMM_STR_MAX, size);
435     } else {
436         g_appTracePrefix = std::string(COMM_STR_MAX - size, ' ') + g_appTracePrefix;
437     }
438 }
439 
SetMainThreadInfo()440 void SetMainThreadInfo()
441 {
442     if (strlen(g_appName) == 0) {
443         if (!GetProcData("/proc/self/cmdline", g_appName, NAME_NORMAL_LEN)) {
444             HILOG_ERROR(LOG_CORE, "get app name failed, %{public}d", errno);
445         }
446     }
447 
448     g_appTracePrefix = std::string(g_appName);
449     SetCommStr();
450     std::string pidStr = std::string(g_pid);
451     std::string pidFixStr = std::string(PID_STR_MAX - pidStr.length(), ' ');
452     g_appTracePrefix +=  "-" + pidStr + pidFixStr + " (" + pidFixStr + pidStr + ")";
453 }
454 
SetAllThreadInfo(const int & tid)455 bool SetAllThreadInfo(const int& tid)
456 {
457     std::string tidStr = std::to_string(tid);
458     std::string file = "/proc/self/task/" + tidStr + "/comm";
459     char comm[NAME_NORMAL_LEN + 1] = {0};
460     if (!GetProcData(file.c_str(), comm, NAME_NORMAL_LEN)) {
461         static bool isWriteLog = false;
462         WriteOnceLog(LOG_ERROR, "get comm failed", isWriteLog);
463         return false;
464     }
465     if (comm[strlen(comm) - 1] == '\n') {
466         comm[strlen(comm) - 1] = '\0';
467     }
468     g_appTracePrefix = std::string(comm);
469     SetCommStr();
470 
471     std::string pidStr = std::string(g_pid);
472     std::string tidFixStr = std::string(PID_STR_MAX - tidStr.length(), ' ');
473     std::string pidFixStr = std::string(PID_STR_MAX - pidStr.length(), ' ');
474     g_appTracePrefix += "-" + tidStr + tidFixStr + " (" + pidFixStr + pidStr + ")";
475 
476     return true;
477 }
478 
SetAppTraceBuffer(char * buf,const int len,MarkerType type,const std::string & name,const int64_t value)479 int SetAppTraceBuffer(char* buf, const int len, MarkerType type, const std::string& name, const int64_t value)
480 {
481     struct timespec ts = { 0, 0 };
482     clock_gettime(CLOCK_BOOTTIME, &ts);
483     int cpu = sched_getcpu();
484     if (cpu == -1) {
485         static bool isWriteLog = false;
486         WriteOnceLog(LOG_ERROR, "get cpu failed", isWriteLog);
487         return -1;
488     }
489 
490     int bytes = 0;
491     if (type == MARKER_BEGIN) {
492         bytes = snprintf_s(buf, len, len - 1, "  %s [%03d] .... %lu.%06lu: tracing_mark_write: B|%s|H:%s \n",
493             g_appTracePrefix.c_str(), cpu, static_cast<long>(ts.tv_sec),
494             static_cast<long>(ts.tv_nsec / NS_TO_MS), g_pid, name.c_str());
495     } else if (type == MARKER_END) {
496         bytes = snprintf_s(buf, len, len - 1, "  %s [%03d] .... %lu.%06lu: tracing_mark_write: E|%s|\n",
497             g_appTracePrefix.c_str(), cpu, static_cast<long>(ts.tv_sec),
498             static_cast<long>(ts.tv_nsec / NS_TO_MS), g_pid);
499     } else {
500         char marktypestr = g_markTypes[type];
501         bytes = snprintf_s(buf, len, len - 1, "  %s [%03d] .... %lu.%06lu: tracing_mark_write: %c|%s|H:%s|%lld\n",
502             g_appTracePrefix.c_str(), cpu, static_cast<long>(ts.tv_sec),
503             static_cast<long>(ts.tv_nsec / NS_TO_MS), marktypestr, g_pid, name.c_str(), value);
504     }
505 
506     return bytes;
507 }
508 
SetAppTrace(const int len,MarkerType type,const std::string & name,const int64_t value)509 void SetAppTrace(const int len, MarkerType type, const std::string& name, const int64_t value)
510 {
511     // get buffer
512     char* buf = GetTraceBuffer(len);
513     if (buf == nullptr) {
514         return;
515     }
516 
517     int bytes = SetAppTraceBuffer(buf, len, type, name, value);
518     if (bytes > 0) {
519         g_traceEventNum += 1;
520         g_writeOffset += bytes;
521     }
522 }
523 
WriteAppTraceLong(const int len,MarkerType type,const std::string & name,const int64_t value)524 void WriteAppTraceLong(const int len, MarkerType type, const std::string& name, const int64_t value)
525 {
526     // 1 write cache data.
527     if (!WriteTraceToFile(g_traceBuffer.get(), g_writeOffset)) {
528         return;
529     }
530 
531     // 2 apply new memory and directly write file.
532     auto buffer = std::make_unique<char[]>(len);
533     if (buffer == nullptr) {
534         static bool isWriteLog = false;
535         WriteOnceLog(LOG_ERROR, "memory allocation failed", isWriteLog);
536         return;
537     }
538 
539     int bytes = SetAppTraceBuffer(buffer.get(), len, type, name, value);
540     if (bytes > 0) {
541         if (!WriteTraceToFile(buffer.get(), bytes)) {
542             return;
543         }
544         g_traceEventNum += 1;
545     }
546 }
547 
CheckFileSize(int len)548 bool CheckFileSize(int len)
549 {
550     if (static_cast<uint64_t>(g_fileSize + g_writeOffset + len) > g_fileLimitSize.load()) {
551         static bool isWriteLog = false;
552         WriteOnceLog(LOG_INFO, "File size limit exceeded, stop capture trace.", isWriteLog);
553         StopCaptureAppTrace();
554         return false;
555     }
556 
557     return true;
558 }
559 
WriteAppTrace(MarkerType type,const std::string & name,const int64_t value)560 void WriteAppTrace(MarkerType type, const std::string& name, const int64_t value)
561 {
562     int tid = getproctid();
563     int len = PREFIX_MAX_SIZE + name.length();
564     if (g_appFlag == FLAG_MAIN_THREAD && g_tgid == tid) {
565         if (!CheckFileSize(len)) {
566             return;
567         }
568 
569         if (g_appTracePrefix.empty()) {
570             SetMainThreadInfo();
571         }
572 
573         if (len <= DEFAULT_CACHE_SIZE) {
574             SetAppTrace(len, type, name, value);
575         } else {
576             WriteAppTraceLong(len, type, name, value);
577         }
578     } else if (g_appFlag == FLAG_ALL_THREAD) {
579         std::unique_lock<std::recursive_mutex> lock(g_appTraceMutex);
580         if (!CheckFileSize(len)) {
581             return;
582         }
583 
584         SetAllThreadInfo(tid);
585 
586         if (len <= DEFAULT_CACHE_SIZE) {
587             SetAppTrace(len, type, name, value);
588         } else {
589             WriteAppTraceLong(len, type, name, value);
590         }
591     }
592 }
593 
AddHitraceMeterMarker(MarkerType type,uint64_t tag,const std::string & name,const int64_t value,const HiTraceIdStruct * hiTraceIdStruct=nullptr)594 void AddHitraceMeterMarker(MarkerType type, uint64_t tag, const std::string& name, const int64_t value,
595     const HiTraceIdStruct* hiTraceIdStruct = nullptr)
596 {
597     if (UNEXPECTANTLY(g_isHitraceMeterDisabled)) {
598         return;
599     }
600     // attention: if appspawn encounters a crash exception, we should reload pid.
601     if (UNEXPECTANTLY(g_needReloadPid && !g_pidHasReload)) {
602         ReloadPid();
603     }
604     if (UNEXPECTANTLY(!g_isHitraceMeterInit)) {
605         struct timespec ts = { 0, 0 };
606         if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1 || ts.tv_sec < 25) { // 25 : register after boot 25s
607             return;
608         }
609         std::call_once(g_onceFlag, OpenTraceMarkerFile);
610     }
611     UpdateSysParamTags();
612     if (UNEXPECTANTLY(g_tagsProperty & tag) && g_markerFd != -1) {
613         int pid = 0;
614         if (!OHOS::HiviewDFX::Hitrace::StringToInt(g_pid, pid)) {
615             return;
616         }
617         if (tag == HITRACE_TAG_APP && g_appTagMatchPid > 0 && g_appTagMatchPid != pid) {
618             return;
619         }
620         // record fomart: "type|pid|name value".
621         char buf[BUFFER_LEN] = {0};
622         int len = name.length();
623         if (EXPECTANTLY(len <= NAME_NORMAL_LEN)) {
624             HiTraceId hiTraceId = (hiTraceIdStruct == nullptr) ? HiTraceChain::GetId() : HiTraceId(*hiTraceIdStruct);
625             bool isHiTraceIdValid = hiTraceId.IsValid();
626             int bytes = 0;
627             if (type == MARKER_BEGIN) {
628                 bytes = isHiTraceIdValid ? snprintf_s(buf, sizeof(buf), sizeof(buf) - 1,
629                     "B|%s|H:[%llx,%llx,%llx]#%s ", g_pid, hiTraceId.GetChainId(),
630                     hiTraceId.GetSpanId(), hiTraceId.GetParentSpanId(), name.c_str())
631                     : snprintf_s(buf, sizeof(buf), sizeof(buf) - 1, "B|%s|H:%s ", g_pid, name.c_str());
632             } else if (type == MARKER_END) {
633                 bytes = snprintf_s(buf, sizeof(buf), sizeof(buf) - 1, "E|%s|", g_pid);
634             } else {
635                 char marktypestr = g_markTypes[type];
636                 bytes = isHiTraceIdValid ? snprintf_s(buf, sizeof(buf), sizeof(buf) - 1,
637                     "%c|%s|H:[%llx,%llx,%llx]#%s|%lld", marktypestr, g_pid,
638                     hiTraceId.GetChainId(), hiTraceId.GetSpanId(), hiTraceId.GetParentSpanId(), name.c_str(), value)
639                     : snprintf_s(buf, sizeof(buf), sizeof(buf) - 1,
640                     "%c|%s|H:%s|%lld", marktypestr, g_pid, name.c_str(), value);
641             }
642             WriteToTraceMarker(buf, bytes);
643         } else if (EXPECTANTLY(len < BUFFER_LEN)) {
644             AddTraceMarkerLarge(name, type, value);
645         }
646     }
647     auto appTagload = g_appTag.load();
648 #ifdef HITRACE_UNITTEST
649     appTagload = HITRACE_TAG_APP;
650 #endif
651     if (UNEXPECTANTLY(appTagload != HITRACE_TAG_NOT_READY) && g_appFd != -1) {
652         WriteAppTrace(type, name, value);
653     }
654 }
655 }; // namespace
656 
657 #ifdef HITRACE_UNITTEST
SetReloadPid(bool isReloadPid)658 void SetReloadPid(bool isReloadPid)
659 {
660     g_needReloadPid = isReloadPid;
661 }
662 
SetpidHasReload(bool ispidHasReload)663 void SetpidHasReload(bool ispidHasReload)
664 {
665     g_pidHasReload = ispidHasReload;
666 }
667 
SetAppFd(int appFd)668 void SetAppFd(int appFd)
669 {
670     g_appFd = appFd;
671 }
672 
GetSetMainThreadInfo()673 void GetSetMainThreadInfo()
674 {
675     SetMainThreadInfo();
676 }
677 
GetSetCommStr()678 void GetSetCommStr()
679 {
680     SetCommStr();
681 }
682 
SetTraceBuffer(int size)683 void SetTraceBuffer(int size)
684 {
685     GetTraceBuffer(size);
686 }
687 
SetAddTraceMarkerLarge(const std::string & name,const int64_t value)688 void SetAddTraceMarkerLarge(const std::string& name, const int64_t value)
689 {
690     AddTraceMarkerLarge(name, MARKER_BEGIN, value);
691 }
692 
SetAddHitraceMeterMarker(uint64_t label,const std::string & value)693 void SetAddHitraceMeterMarker(uint64_t label, const std::string& value)
694 {
695     AddHitraceMeterMarker(MARKER_BEGIN, label, value, 0);
696 }
697 
SetWriteToTraceMarker(const char * buf,const int count)698 void SetWriteToTraceMarker(const char* buf, const int count)
699 {
700     WriteToTraceMarker(buf, count);
701 }
702 
SetGetProcData(const char * file)703 void SetGetProcData(const char* file)
704 {
705     GetProcData(file, g_appName, NAME_NORMAL_LEN);
706 }
707 
SetHitracePerfScoped(int fd1st,int fd2nd)708 void HitracePerfScoped::SetHitracePerfScoped(int fd1st, int fd2nd)
709 {
710     if (fd1st == -1 && fd2nd == -1) {
711         fd1st_ = fd1st;
712         fd2nd_ = fd2nd;
713     }
714     GetInsCount();
715     GetCycleCount();
716 }
717 
SetCachedHandleAndAppPidCachedHandle(CachedHandle cachedHandle,CachedHandle appPidCachedHandle)718 void SetCachedHandleAndAppPidCachedHandle(CachedHandle cachedHandle, CachedHandle appPidCachedHandle)
719 {
720     g_cachedHandle = cachedHandle;
721     g_appPidCachedHandle = appPidCachedHandle;
722     UpdateSysParamTags();
723 }
724 
SetMarkerFd(int markerFd)725 void SetMarkerFd(int markerFd)
726 {
727     if (markerFd != -1) {
728         g_markerFd = -1;
729     }
730 }
731 
SetWriteAppTrace(TraceFlag appFlag,const std::string & name,const int64_t value,bool tid)732 void SetWriteAppTrace(TraceFlag appFlag, const std::string& name, const int64_t value, bool tid)
733 {
734     if (tid) {
735         g_tgid = getproctid();
736     }
737     g_appFlag = appFlag;
738     WriteAppTrace(MARKER_BEGIN, name, value);
739 }
740 
SetWriteOnceLog(LogLevel loglevel,const std::string & logStr,bool & isWrite)741 void SetWriteOnceLog(LogLevel loglevel, const std::string& logStr, bool& isWrite)
742 {
743     WriteOnceLog(loglevel, logStr, isWrite);
744 }
745 
SetappTracePrefix(const std::string & appTracePrefix)746 void SetappTracePrefix(const std::string& appTracePrefix)
747 {
748     g_appTracePrefix = appTracePrefix;
749 }
750 
SetMarkerType(TraceFlag appFlag,const std::string & name,const int64_t value,bool tid)751 void SetMarkerType(TraceFlag appFlag, const std::string& name, const int64_t value, bool tid)
752 {
753     if (tid) {
754         g_tgid = getproctid();
755     }
756     g_appFlag = appFlag;
757     WriteAppTrace(MARKER_ASYNC_BEGIN, name, value);
758 }
759 
SetWriteAppTraceLong(const int len,const std::string & name,const int64_t value)760 void SetWriteAppTraceLong(const int len, const std::string& name, const int64_t value)
761 {
762     WriteAppTraceLong(len, MARKER_BEGIN, name, value);
763 }
764 #endif
UpdateTraceLabel(void)765 void UpdateTraceLabel(void)
766 {
767     if (!g_isHitraceMeterInit) {
768         return;
769     }
770     UpdateSysParamTags();
771 }
772 
SetTraceDisabled(bool disable)773 void SetTraceDisabled(bool disable)
774 {
775     g_isHitraceMeterDisabled = disable;
776 }
777 
StartTraceWrapper(uint64_t label,const char * value)778 void StartTraceWrapper(uint64_t label, const char *value)
779 {
780     std::string traceValue = value;
781     StartTrace(label, traceValue);
782 }
783 
StartTrace(uint64_t label,const std::string & value,float limit UNUSED_PARAM)784 void StartTrace(uint64_t label, const std::string& value, float limit UNUSED_PARAM)
785 {
786     AddHitraceMeterMarker(MARKER_BEGIN, label, value, 0);
787 }
788 
StartTraceDebug(bool isDebug,uint64_t label,const std::string & value,float limit UNUSED_PARAM)789 void StartTraceDebug(bool isDebug, uint64_t label, const std::string& value, float limit UNUSED_PARAM)
790 {
791     if (!isDebug) {
792         return;
793     }
794     AddHitraceMeterMarker(MARKER_BEGIN, label, value, 0);
795 }
796 
StartTraceArgs(uint64_t label,const char * fmt,...)797 void StartTraceArgs(uint64_t label, const char *fmt, ...)
798 {
799     UpdateSysParamTags();
800     if (!(label & g_tagsProperty) || UNEXPECTANTLY(g_isHitraceMeterDisabled)) {
801         return;
802     }
803     char name[VAR_NAME_MAX_SIZE] = { 0 };
804     va_list args;
805     va_start(args, fmt);
806     int res = vsnprintf_s(name, sizeof(name), sizeof(name) - 1, fmt, args);
807     va_end(args);
808     if (res < 0) {
809         HILOG_ERROR(LOG_CORE, "vsnprintf_s failed: %{public}d, name: %{public}s", errno, fmt);
810         return;
811     }
812     AddHitraceMeterMarker(MARKER_BEGIN, label, name, 0);
813 }
814 
StartTraceArgsDebug(bool isDebug,uint64_t label,const char * fmt,...)815 void StartTraceArgsDebug(bool isDebug, uint64_t label, const char *fmt, ...)
816 {
817     UpdateSysParamTags();
818     if (!isDebug || !(label & g_tagsProperty) || UNEXPECTANTLY(g_isHitraceMeterDisabled)) {
819         return;
820     }
821     char name[VAR_NAME_MAX_SIZE] = { 0 };
822     va_list args;
823 
824     va_start(args, fmt);
825     int res = vsnprintf_s(name, sizeof(name), sizeof(name) - 1, fmt, args);
826     va_end(args);
827     if (res < 0) {
828         HILOG_ERROR(LOG_CORE, "vsnprintf_s failed: %{public}d, name: %{public}s", errno, fmt);
829         return;
830     }
831     AddHitraceMeterMarker(MARKER_BEGIN, label, name, 0);
832 }
833 
FinishTrace(uint64_t label)834 void FinishTrace(uint64_t label)
835 {
836     AddHitraceMeterMarker(MARKER_END, label, EMPTY_TRACE_NAME, 0);
837 }
838 
FinishTraceDebug(bool isDebug,uint64_t label)839 void FinishTraceDebug(bool isDebug, uint64_t label)
840 {
841     if (!isDebug) {
842         return;
843     }
844     AddHitraceMeterMarker(MARKER_END, label, EMPTY_TRACE_NAME, 0);
845 }
846 
StartAsyncTrace(uint64_t label,const std::string & value,int32_t taskId,float limit UNUSED_PARAM)847 void StartAsyncTrace(uint64_t label, const std::string& value, int32_t taskId, float limit UNUSED_PARAM)
848 {
849     AddHitraceMeterMarker(MARKER_ASYNC_BEGIN, label, value, taskId);
850 }
851 
StartAsyncTraceWrapper(uint64_t label,const char * value,int32_t taskId)852 void StartAsyncTraceWrapper(uint64_t label, const char *value, int32_t taskId)
853 {
854     std::string traceValue = value;
855     StartAsyncTrace(label, traceValue, taskId);
856 }
857 
StartTraceChain(uint64_t label,const struct HiTraceIdStruct * hiTraceId,const char * value)858 void StartTraceChain(uint64_t label, const struct HiTraceIdStruct* hiTraceId, const char *value)
859 {
860     AddHitraceMeterMarker(MARKER_BEGIN, label, value, 0, hiTraceId);
861 }
862 
StartAsyncTraceDebug(bool isDebug,uint64_t label,const std::string & value,int32_t taskId,float limit UNUSED_PARAM)863 void StartAsyncTraceDebug(bool isDebug, uint64_t label, const std::string& value, int32_t taskId,
864     float limit UNUSED_PARAM)
865 {
866     if (!isDebug) {
867         return;
868     }
869     AddHitraceMeterMarker(MARKER_ASYNC_BEGIN, label, value, taskId);
870 }
871 
StartAsyncTraceArgs(uint64_t label,int32_t taskId,const char * fmt,...)872 void StartAsyncTraceArgs(uint64_t label, int32_t taskId, const char *fmt, ...)
873 {
874     UpdateSysParamTags();
875     if (!(label & g_tagsProperty) || UNEXPECTANTLY(g_isHitraceMeterDisabled)) {
876         return;
877     }
878     char name[VAR_NAME_MAX_SIZE] = { 0 };
879     va_list args;
880 
881     va_start(args, fmt);
882     int res = vsnprintf_s(name, sizeof(name), sizeof(name) - 1, fmt, args);
883     va_end(args);
884     if (res < 0) {
885         HILOG_ERROR(LOG_CORE, "vsnprintf_s failed: %{public}d, name: %{public}s", errno, fmt);
886         return;
887     }
888     AddHitraceMeterMarker(MARKER_ASYNC_BEGIN, label, name, taskId);
889 }
890 
StartAsyncTraceArgsDebug(bool isDebug,uint64_t label,int32_t taskId,const char * fmt,...)891 void StartAsyncTraceArgsDebug(bool isDebug, uint64_t label, int32_t taskId, const char *fmt, ...)
892 {
893     UpdateSysParamTags();
894     if (!isDebug || !(label & g_tagsProperty) || UNEXPECTANTLY(g_isHitraceMeterDisabled)) {
895         return;
896     }
897     char name[VAR_NAME_MAX_SIZE] = { 0 };
898     va_list args;
899 
900     va_start(args, fmt);
901     int res = vsnprintf_s(name, sizeof(name), sizeof(name) - 1, fmt, args);
902     va_end(args);
903     if (res < 0) {
904         HILOG_ERROR(LOG_CORE, "vsnprintf_s failed: %{public}d, name: %{public}s", errno, fmt);
905         return;
906     }
907     AddHitraceMeterMarker(MARKER_ASYNC_BEGIN, label, name, taskId);
908 }
909 
FinishAsyncTrace(uint64_t label,const std::string & value,int32_t taskId)910 void FinishAsyncTrace(uint64_t label, const std::string& value, int32_t taskId)
911 {
912     AddHitraceMeterMarker(MARKER_ASYNC_END, label, value, taskId);
913 }
914 
FinishAsyncTraceWrapper(uint64_t label,const char * value,int32_t taskId)915 void FinishAsyncTraceWrapper(uint64_t label, const char *value, int32_t taskId)
916 {
917     std::string traceValue = value;
918     FinishAsyncTrace(label, traceValue, taskId);
919 }
920 
FinishAsyncTraceDebug(bool isDebug,uint64_t label,const std::string & value,int32_t taskId)921 void FinishAsyncTraceDebug(bool isDebug, uint64_t label, const std::string& value, int32_t taskId)
922 {
923     if (!isDebug) {
924         return;
925     }
926     AddHitraceMeterMarker(MARKER_ASYNC_END, label, value, taskId);
927 }
928 
FinishAsyncTraceArgs(uint64_t label,int32_t taskId,const char * fmt,...)929 void FinishAsyncTraceArgs(uint64_t label, int32_t taskId, const char *fmt, ...)
930 {
931     UpdateSysParamTags();
932     if (!(label & g_tagsProperty) || UNEXPECTANTLY(g_isHitraceMeterDisabled)) {
933         return;
934     }
935     char name[VAR_NAME_MAX_SIZE] = { 0 };
936     va_list args;
937 
938     va_start(args, fmt);
939     int res = vsnprintf_s(name, sizeof(name), sizeof(name) - 1, fmt, args);
940     va_end(args);
941     if (res < 0) {
942         HILOG_ERROR(LOG_CORE, "vsnprintf_s failed: %{public}d, name: %{public}s", errno, fmt);
943         return;
944     }
945     AddHitraceMeterMarker(MARKER_ASYNC_END, label, name, taskId);
946 }
947 
FinishAsyncTraceArgsDebug(bool isDebug,uint64_t label,int32_t taskId,const char * fmt,...)948 void FinishAsyncTraceArgsDebug(bool isDebug, uint64_t label, int32_t taskId, const char *fmt, ...)
949 {
950     UpdateSysParamTags();
951     if (!isDebug || !(label & g_tagsProperty) || UNEXPECTANTLY(g_isHitraceMeterDisabled)) {
952         return;
953     }
954     char name[VAR_NAME_MAX_SIZE] = { 0 };
955     va_list args;
956 
957     va_start(args, fmt);
958     int res = vsnprintf_s(name, sizeof(name), sizeof(name) - 1, fmt, args);
959     va_end(args);
960     if (res < 0) {
961         HILOG_ERROR(LOG_CORE, "vsnprintf_s failed: %{public}d, name: %{public}s", errno, fmt);
962         return;
963     }
964     AddHitraceMeterMarker(MARKER_ASYNC_END, label, name, taskId);
965 }
966 
MiddleTrace(uint64_t label,const std::string & beforeValue UNUSED_PARAM,const std::string & afterValue)967 void MiddleTrace(uint64_t label, const std::string& beforeValue UNUSED_PARAM, const std::string& afterValue)
968 {
969     AddHitraceMeterMarker(MARKER_END, label, EMPTY_TRACE_NAME, 0);
970     AddHitraceMeterMarker(MARKER_BEGIN, label, afterValue, 0);
971 }
972 
MiddleTraceDebug(bool isDebug,uint64_t label,const std::string & beforeValue UNUSED_PARAM,const std::string & afterValue)973 void MiddleTraceDebug(bool isDebug, uint64_t label, const std::string& beforeValue UNUSED_PARAM,
974     const std::string& afterValue)
975 {
976     if (!isDebug) {
977         return;
978     }
979     AddHitraceMeterMarker(MARKER_END, label, EMPTY_TRACE_NAME, 0);
980     AddHitraceMeterMarker(MARKER_BEGIN, label, afterValue, 0);
981 }
982 
CountTrace(uint64_t label,const std::string & name,int64_t count)983 void CountTrace(uint64_t label, const std::string& name, int64_t count)
984 {
985     AddHitraceMeterMarker(MARKER_INT, label, name, count);
986 }
987 
CountTraceDebug(bool isDebug,uint64_t label,const std::string & name,int64_t count)988 void CountTraceDebug(bool isDebug, uint64_t label, const std::string& name, int64_t count)
989 {
990     if (!isDebug) {
991         return;
992     }
993     AddHitraceMeterMarker(MARKER_INT, label, name, count);
994 }
995 
CountTraceWrapper(uint64_t label,const char * name,int64_t count)996 void CountTraceWrapper(uint64_t label, const char *name, int64_t count)
997 {
998     std::string traceName = name;
999     CountTrace(label, traceName, count);
1000 }
1001 
HitraceMeterFmtScoped(uint64_t label,const char * fmt,...)1002 HitraceMeterFmtScoped::HitraceMeterFmtScoped(uint64_t label, const char *fmt, ...) : mTag(label)
1003 {
1004     UpdateSysParamTags();
1005     if (!(label & g_tagsProperty) || UNEXPECTANTLY(g_isHitraceMeterDisabled)) {
1006         return;
1007     }
1008     char name[VAR_NAME_MAX_SIZE] = { 0 };
1009     va_list args;
1010 
1011     va_start(args, fmt);
1012     int res = vsnprintf_s(name, sizeof(name), sizeof(name) - 1, fmt, args);
1013     va_end(args);
1014     if (res < 0) {
1015         HILOG_ERROR(LOG_CORE, "vsnprintf_s failed: %{public}d, name: %{public}s", errno, fmt);
1016         return;
1017     }
1018     AddHitraceMeterMarker(MARKER_BEGIN, label, name, 0);
1019 }
1020 
IsTagEnabled(uint64_t tag)1021 bool IsTagEnabled(uint64_t tag)
1022 {
1023     UpdateSysParamTags();
1024     return ((tag & g_tagsProperty) == tag);
1025 }
1026 
1027 // For native process, the caller is responsible passing the full path of the fileName.
1028 // For hap application, StartCaputreAppTrace() fill fileName
1029 // as /data/app/el2/100/log/$(processname)/trace/$(processname)_$(date)_&(time).trace and return to caller.
StartCaptureAppTrace(TraceFlag flag,uint64_t tags,uint64_t limitSize,std::string & fileName)1030 int StartCaptureAppTrace(TraceFlag flag, uint64_t tags, uint64_t limitSize, std::string& fileName)
1031 {
1032     auto ret = CheckAppTraceArgs(flag, tags, limitSize);
1033     if (ret != RET_SUCC) {
1034         return ret;
1035     }
1036 
1037     std::unique_lock<std::recursive_mutex> lock(g_appTraceMutex);
1038     if (g_appFd != -1) {
1039         HILOG_INFO(LOG_CORE, "CaptureAppTrace started, return");
1040         return RET_STARTED;
1041     }
1042 
1043     g_traceBuffer = std::make_unique<char[]>(DEFAULT_CACHE_SIZE);
1044     if (g_traceBuffer == nullptr) {
1045         HILOG_ERROR(LOG_CORE, "memory allocation failed: %{public}d(%{public}s)", errno, strerror(errno));
1046         return RET_FAILD;
1047     }
1048 
1049     g_appFlag = flag;
1050     g_appTag = tags;
1051     g_fileLimitSize = (limitSize > MAX_FILE_SIZE) ? MAX_FILE_SIZE : limitSize;
1052     g_tgid = getprocpid();
1053     g_appTracePrefix = "";
1054 
1055     std::string destFileName = fileName;
1056     if (destFileName.empty()) {
1057         auto retval = SetAppFileName(destFileName, fileName);
1058         if (retval != RET_SUCC) {
1059             HILOG_ERROR(LOG_CORE, "set appFileName failed: %{public}d(%{public}s)", errno, strerror(errno));
1060             return retval;
1061         }
1062     }
1063 
1064     mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; // 0644
1065     g_appFd = open(destFileName.c_str(), O_WRONLY | O_CLOEXEC | O_CREAT | O_TRUNC, mode);
1066     if (g_appFd == -1) {
1067         HILOG_ERROR(LOG_CORE, "open destFileName failed: %{public}d(%{public}s)", errno, strerror(errno));
1068         if (errno == ENOENT) {
1069             return RET_FAIL_ENOENT;
1070         } else if (errno == EACCES) {
1071             return RET_FAIL_EACCES;
1072         } else {
1073             return RET_FAILD;
1074         }
1075     }
1076 
1077     return InitTraceHead();
1078 }
1079 
StopCaptureAppTrace()1080 int StopCaptureAppTrace()
1081 {
1082     std::unique_lock<std::recursive_mutex> lock(g_appTraceMutex);
1083     if (g_appFd == -1) {
1084         HILOG_INFO(LOG_CORE, "CaptureAppTrace stopped, return");
1085         return RET_STOPPED;
1086     }
1087 
1088     // Write cache data
1089     WriteTraceToFile(g_traceBuffer.get(), g_writeOffset);
1090 
1091     std::string eventNumStr = std::to_string(g_traceEventNum) + "/" + std::to_string(g_traceEventNum);
1092     std::vector<char> buffer(TRACE_TXT_HEADER_MAX, '\0');
1093     int used = snprintf_s(buffer.data(), buffer.size(), buffer.size() - 1, TRACE_TXT_HEADER_FORMAT.c_str(),
1094         eventNumStr.c_str(), std::to_string(CPU_CORE_NUM).c_str());
1095     if (used <= 0) {
1096         HILOG_ERROR(LOG_CORE, "format trace header failed: %{public}d(%{public}s)", errno, strerror(errno));
1097         return RET_FAILD;
1098     }
1099 
1100     lseek(g_appFd, 0, SEEK_SET); // Move the write pointer to populate the file header.
1101     if (write(g_appFd, buffer.data(), used) != used) {
1102         HILOG_ERROR(LOG_CORE, "write trace header failed: %{public}d(%{public}s)", errno, strerror(errno));
1103         return RET_FAILD;
1104     }
1105 
1106     g_fileSize = 0;
1107     g_writeOffset = 0;
1108     g_traceEventNum = 0;
1109     g_appTracePrefix = "";
1110     g_appTag = HITRACE_TAG_NOT_READY;
1111 
1112     close(g_appFd);
1113     g_appFd = -1;
1114     g_traceBuffer.reset();
1115     g_traceBuffer = nullptr;
1116 
1117     return RET_SUCC;
1118 }
1119 
HitracePerfScoped(bool isDebug,uint64_t tag,const std::string & name)1120 HitracePerfScoped::HitracePerfScoped(bool isDebug, uint64_t tag, const std::string &name) : mTag_(tag), mName_(name)
1121 {
1122     if (!isDebug) {
1123         return;
1124     }
1125     struct perf_event_attr peIns;
1126     (void)memset_s(&peIns, sizeof(struct perf_event_attr), 0, sizeof(struct perf_event_attr));
1127     peIns.type = PERF_TYPE_HARDWARE;
1128     peIns.size = sizeof(struct perf_event_attr);
1129     peIns.config = PERF_COUNT_HW_INSTRUCTIONS;
1130     peIns.disabled = 1;
1131     peIns.exclude_kernel = 0;
1132     peIns.exclude_hv = 0;
1133     fd1st_ = syscall(__NR_perf_event_open, &peIns, 0, -1, -1, 0);
1134     if (fd1st_ == -1) {
1135         err_ = errno;
1136         return;
1137     }
1138     struct perf_event_attr peCycles;
1139     (void)memset_s(&peCycles, sizeof(struct perf_event_attr), 0, sizeof(struct perf_event_attr));
1140     peCycles.type = PERF_TYPE_HARDWARE;
1141     peCycles.size = sizeof(struct perf_event_attr);
1142     peCycles.config = PERF_COUNT_HW_CPU_CYCLES;
1143     peCycles.disabled = 1;
1144     peCycles.exclude_kernel = 0;
1145     peCycles.exclude_hv = 0;
1146     fd2nd_ = syscall(__NR_perf_event_open, &peCycles, 0, -1, -1, 0);
1147     if (fd2nd_ == -1) {
1148         err_ = errno;
1149         return;
1150     }
1151     ioctl(fd1st_, PERF_EVENT_IOC_RESET, 0);
1152     ioctl(fd1st_, PERF_EVENT_IOC_ENABLE, 0);
1153     ioctl(fd2nd_, PERF_EVENT_IOC_RESET, 0);
1154     ioctl(fd2nd_, PERF_EVENT_IOC_ENABLE, 0);
1155 }
1156 
~HitracePerfScoped()1157 HitracePerfScoped::~HitracePerfScoped()
1158 {
1159     if (fd1st_ != -1) {
1160         ioctl(fd1st_, PERF_EVENT_IOC_DISABLE, 0);
1161         read(fd1st_, &countIns_, sizeof(long long));
1162         close(fd1st_);
1163         CountTrace(mTag_, mName_ + "-Ins", countIns_);
1164     }
1165     if (fd2nd_ != -1) {
1166         ioctl(fd2nd_, PERF_EVENT_IOC_DISABLE, 0);
1167         read(fd2nd_, &countCycles_, sizeof(long long));
1168         close(fd2nd_);
1169         CountTrace(mTag_, mName_ + "-Cycle", countCycles_);
1170     }
1171 }
1172 
GetInsCount()1173 inline long long HitracePerfScoped::GetInsCount()
1174 {
1175     if (fd1st_ == -1) {
1176         return err_;
1177     }
1178     read(fd1st_, &countIns_, sizeof(long long));
1179     return countIns_;
1180 }
1181 
GetCycleCount()1182 inline long long HitracePerfScoped::GetCycleCount()
1183 {
1184     if (fd2nd_ == -1) {
1185         return err_;
1186     }
1187     read(fd2nd_, &countCycles_, sizeof(long long));
1188     return countCycles_;
1189 }
1190