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