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