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