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