148f512ceSopenharmony_ci/* 248f512ceSopenharmony_ci * Copyright (c) 2021-2022 Huawei Device Co., Ltd. 348f512ceSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 448f512ceSopenharmony_ci * you may not use this file except in compliance with the License. 548f512ceSopenharmony_ci * You may obtain a copy of the License at 648f512ceSopenharmony_ci * 748f512ceSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 848f512ceSopenharmony_ci * 948f512ceSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 1048f512ceSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 1148f512ceSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1248f512ceSopenharmony_ci * See the License for the specific language governing permissions and 1348f512ceSopenharmony_ci * limitations under the License. 1448f512ceSopenharmony_ci */ 1548f512ceSopenharmony_ci#ifndef HIPERF_UTILITIES_H_ 1648f512ceSopenharmony_ci#define HIPERF_UTILITIES_H_ 1748f512ceSopenharmony_ci 1848f512ceSopenharmony_ci// for security function 1948f512ceSopenharmony_ci#include <securec.h> 2048f512ceSopenharmony_ci#include <algorithm> 2148f512ceSopenharmony_ci#include <cctype> 2248f512ceSopenharmony_ci#include <cinttypes> 2348f512ceSopenharmony_ci#include <cstdio> 2448f512ceSopenharmony_ci#include <fstream> 2548f512ceSopenharmony_ci#include <iomanip> 2648f512ceSopenharmony_ci#include <iostream> 2748f512ceSopenharmony_ci#include <sstream> 2848f512ceSopenharmony_ci#include <string> 2948f512ceSopenharmony_ci#include <vector> 3048f512ceSopenharmony_ci#include <set> 3148f512ceSopenharmony_ci 3248f512ceSopenharmony_ci#include <dirent.h> 3348f512ceSopenharmony_ci#include <fcntl.h> 3448f512ceSopenharmony_ci#include <file_ex.h> 3548f512ceSopenharmony_ci#include <stddef.h> 3648f512ceSopenharmony_ci#include <sys/stat.h> 3748f512ceSopenharmony_ci#include <unique_fd.h> 3848f512ceSopenharmony_ci#include <unistd.h> 3948f512ceSopenharmony_ci#if !is_mingw 4048f512ceSopenharmony_ci#include <gtest/gtest_prod.h> 4148f512ceSopenharmony_ci#include <sys/syscall.h> 4248f512ceSopenharmony_ci#endif 4348f512ceSopenharmony_ci#include <linux/types.h> 4448f512ceSopenharmony_ci#include "debug_logger.h" 4548f512ceSopenharmony_ci#include "noncopyable.h" 4648f512ceSopenharmony_ci 4748f512ceSopenharmony_ci// data and value 4848f512ceSopenharmony_ci/* 4948f512ceSopenharmony_cilong long always 64 only in ILP64, int is 64 otherwise int is always 32 5048f512ceSopenharmony_ci*/ 5148f512ceSopenharmony_ciusing s8 = __s8; 5248f512ceSopenharmony_ciusing u8 = __u8; 5348f512ceSopenharmony_ciusing s16 = __s16; 5448f512ceSopenharmony_ciusing u16 = __u16; 5548f512ceSopenharmony_ciusing s32 = __s32; 5648f512ceSopenharmony_ciusing u32 = __u32; 5748f512ceSopenharmony_ciusing s64 = __s64; 5848f512ceSopenharmony_ciusing u64 = __u64; 5948f512ceSopenharmony_ci 6048f512ceSopenharmony_ciconstexpr const int NUMBER_FORMAT_HEX_BASE = 16; 6148f512ceSopenharmony_ciconstexpr const int BYTE_PRINT_WIDTH = 2; 6248f512ceSopenharmony_ciconstexpr const int UINT64_PRINT_WIDTH = BYTE_PRINT_WIDTH * 8; 6348f512ceSopenharmony_ciconstexpr const int BITS_OF_BYTE = 8; 6448f512ceSopenharmony_ciconstexpr const int BITS_OF_TWO_BYTE = 2 * BITS_OF_BYTE; 6548f512ceSopenharmony_ciconstexpr const int BITS_OF_FOUR_BYTE = 4 * BITS_OF_BYTE; 6648f512ceSopenharmony_ciconstexpr const int FULL_PERCENTAGE = 100; 6748f512ceSopenharmony_ciconstexpr const int FULL_PERCENTAGE_NUM_LEN = 5; // 100.00 6848f512ceSopenharmony_ciconstexpr const int FULL_PERCENTAGE_DIFF_NUM_LEN = 6; // +100.00 6948f512ceSopenharmony_ciconstexpr const int FULL_PERCENTAGE_LEN = 6; // 100.00% 7048f512ceSopenharmony_ciconstexpr const int FULL_PERCENTAGE_DIFF_LEN = 7; // +100.00% 7148f512ceSopenharmony_ciconstexpr const int THOUSANDS = 1000; 7248f512ceSopenharmony_ciconstexpr const int HUNDREDS = 100; 7348f512ceSopenharmony_ciconstexpr const int DEFAULT_STRING_BUF_SIZE = 4096; 7448f512ceSopenharmony_ciconstexpr const int FIVE_THOUSANDS = 5000; 7548f512ceSopenharmony_ciconstexpr const int DATA_MAX_SIZE = 1001; 7648f512ceSopenharmony_ciconstexpr const int LITTLE_MEMORY_SIZE = 1; 7748f512ceSopenharmony_ciconstexpr const int MULTIPLE_SIZE = 1024; 7848f512ceSopenharmony_ciconstexpr const uint16_t CHECK_FREQUENCY = 100; // 7948f512ceSopenharmony_ciconstexpr const uint8_t CHECK_TIMEOUT = 30; 8048f512ceSopenharmony_ciconstexpr const int INDENT_TWO = 2; 8148f512ceSopenharmony_ciconstexpr const float ALMOST_ZERO = 0.001; 8248f512ceSopenharmony_ci#if !is_mingw 8348f512ceSopenharmony_ci#ifndef O_BINARY 8448f512ceSopenharmony_ci#define O_BINARY 0 8548f512ceSopenharmony_ci#endif 8648f512ceSopenharmony_ci#endif 8748f512ceSopenharmony_ci 8848f512ceSopenharmony_ciconstexpr const double MS_DURATION = 8948f512ceSopenharmony_ci static_cast<double>(std::chrono::milliseconds::duration::period::den); 9048f512ceSopenharmony_ci 9148f512ceSopenharmony_ciconstexpr uint64_t KILO = 1024; 9248f512ceSopenharmony_ci 9348f512ceSopenharmony_cinamespace OHOS { 9448f512ceSopenharmony_cinamespace Developtools { 9548f512ceSopenharmony_cinamespace HiPerf { 9648f512ceSopenharmony_cistd::string CanonicalizeSpecPath(const char* src); 9748f512ceSopenharmony_ciconst std::string EMPTY_STRING = ""; 9848f512ceSopenharmony_ciconst ssize_t ERRINFOLEN = 512; 9948f512ceSopenharmony_ciconst std::set<int> ALLOW_UIDS = {1201}; 10048f512ceSopenharmony_ci 10148f512ceSopenharmony_ciconst std::string SAVED_CMDLINES = "/sys/kernel/tracing/saved_cmdlines"; 10248f512ceSopenharmony_cistatic FILE *g_outputDump = nullptr; 10348f512ceSopenharmony_ciconst uint64_t waitAppRunCheckTimeOut = 20; 10448f512ceSopenharmony_ci 10548f512ceSopenharmony_cistruct ThreadInfos { 10648f512ceSopenharmony_ci pid_t tid; 10748f512ceSopenharmony_ci pid_t pid; 10848f512ceSopenharmony_ci}; 10948f512ceSopenharmony_ci// string function 11048f512ceSopenharmony_ciclass MemoryHold { 11148f512ceSopenharmony_cipublic: 11248f512ceSopenharmony_ci ~MemoryHold() 11348f512ceSopenharmony_ci { 11448f512ceSopenharmony_ci Clean(); 11548f512ceSopenharmony_ci } 11648f512ceSopenharmony_ci // only use in UT 11748f512ceSopenharmony_ci void Clean() 11848f512ceSopenharmony_ci { 11948f512ceSopenharmony_ci for (auto &p : holder_) { 12048f512ceSopenharmony_ci delete[] p; 12148f512ceSopenharmony_ci } 12248f512ceSopenharmony_ci holder_.clear(); 12348f512ceSopenharmony_ci } 12448f512ceSopenharmony_ci static MemoryHold &Get() 12548f512ceSopenharmony_ci { 12648f512ceSopenharmony_ci static MemoryHold instance; 12748f512ceSopenharmony_ci return instance; 12848f512ceSopenharmony_ci } 12948f512ceSopenharmony_ci 13048f512ceSopenharmony_ciprivate: 13148f512ceSopenharmony_ci std::vector<char *> holder_; 13248f512ceSopenharmony_ci}; 13348f512ceSopenharmony_ci 13448f512ceSopenharmony_cistd::string StringReplace(std::string source, const std::string &from, const std::string &to); 13548f512ceSopenharmony_ci 13648f512ceSopenharmony_citemplate<class T> 13748f512ceSopenharmony_cistd::string VectorToString(const std::vector<T> &items) 13848f512ceSopenharmony_ci{ 13948f512ceSopenharmony_ci if constexpr (std::is_same<T, std::vector<std::string>>::value) { 14048f512ceSopenharmony_ci std::vector<std::string> stringItems; 14148f512ceSopenharmony_ci for (auto item : items) { 14248f512ceSopenharmony_ci stringItems.push_back("[" + VectorToString(item) + "]"); 14348f512ceSopenharmony_ci } 14448f512ceSopenharmony_ci return VectorToString(stringItems); 14548f512ceSopenharmony_ci } else { 14648f512ceSopenharmony_ci std::string itemsString; 14748f512ceSopenharmony_ci const std::string split = ","; 14848f512ceSopenharmony_ci for (auto item : items) { 14948f512ceSopenharmony_ci if (!itemsString.empty()) 15048f512ceSopenharmony_ci itemsString.append(split); 15148f512ceSopenharmony_ci if constexpr (std::is_same<T, std::string>::value) { 15248f512ceSopenharmony_ci itemsString.append(item); 15348f512ceSopenharmony_ci } else { 15448f512ceSopenharmony_ci itemsString.append(std::to_string(item)); 15548f512ceSopenharmony_ci } 15648f512ceSopenharmony_ci } 15748f512ceSopenharmony_ci if (itemsString.empty()) 15848f512ceSopenharmony_ci itemsString.append("<empty>"); 15948f512ceSopenharmony_ci return itemsString; 16048f512ceSopenharmony_ci } 16148f512ceSopenharmony_ci} 16248f512ceSopenharmony_ci 16348f512ceSopenharmony_cistd::string BufferToHexString(const std::vector<unsigned char> &vec); 16448f512ceSopenharmony_cistd::string BufferToHexString(const unsigned char buf[], size_t size); 16548f512ceSopenharmony_civoid HexDump(const void *buf, size_t size, size_t max_size = 0); 16648f512ceSopenharmony_ci 16748f512ceSopenharmony_cistd::string &StringTrim(std::string &s); 16848f512ceSopenharmony_ci 16948f512ceSopenharmony_cistd::vector<std::string> StringSplit(std::string source, const std::string &split = ","); 17048f512ceSopenharmony_ci 17148f512ceSopenharmony_cisize_t SubStringCount(const std::string &source, const std::string &sub); 17248f512ceSopenharmony_ci 17348f512ceSopenharmony_cibool StringStartsWith(const std::string &string, const std::string &with); 17448f512ceSopenharmony_ci 17548f512ceSopenharmony_cibool StringEndsWith(const std::string &string, const std::string &with); 17648f512ceSopenharmony_ci 17748f512ceSopenharmony_cibool IsSameCommand(const std::string &cmdLine, const std::string &cmdName); 17848f512ceSopenharmony_ci 17948f512ceSopenharmony_cistd::vector<pid_t> GetSubthreadIDs(const pid_t pid); 18048f512ceSopenharmony_ci 18148f512ceSopenharmony_cibool IsDigits(const std::string &str); 18248f512ceSopenharmony_ci 18348f512ceSopenharmony_cibool IsHexDigits(const std::string &str); 18448f512ceSopenharmony_ci 18548f512ceSopenharmony_ciconstexpr const int COMPRESS_READ_BUF_SIZE = 4096; 18648f512ceSopenharmony_ci// compress specified dataFile into gzip file 18748f512ceSopenharmony_cibool CompressFile(const std::string &dataFile, const std::string &destFile); 18848f512ceSopenharmony_ci// uncompress specified gzip file into dataFile 18948f512ceSopenharmony_cibool UncompressFile(const std::string &gzipFile, const std::string &dataFile); 19048f512ceSopenharmony_ci 19148f512ceSopenharmony_citemplate<typename... VA> 19248f512ceSopenharmony_cistd::string StringPrintf(const char *stringFormat, VA... args) 19348f512ceSopenharmony_ci{ 19448f512ceSopenharmony_ci // check howmany bytes we need 19548f512ceSopenharmony_ci char bytes[DEFAULT_STRING_BUF_SIZE]; 19648f512ceSopenharmony_ci bytes[DEFAULT_STRING_BUF_SIZE - 1] = '\0'; 19748f512ceSopenharmony_ci 19848f512ceSopenharmony_ci if (stringFormat == nullptr) { 19948f512ceSopenharmony_ci return EMPTY_STRING; 20048f512ceSopenharmony_ci } 20148f512ceSopenharmony_ci 20248f512ceSopenharmony_ci // print it to bytes 20348f512ceSopenharmony_ci if (snprintf_s(bytes, sizeof(bytes), sizeof(bytes) - 1, stringFormat, 20448f512ceSopenharmony_ci args...) < 0) { 20548f512ceSopenharmony_ci return EMPTY_STRING; 20648f512ceSopenharmony_ci } 20748f512ceSopenharmony_ci 20848f512ceSopenharmony_ci // make a string return 20948f512ceSopenharmony_ci return std::string(bytes); 21048f512ceSopenharmony_ci} 21148f512ceSopenharmony_ci 21248f512ceSopenharmony_ci// path check 21348f512ceSopenharmony_cistd::vector<std::string> GetEntriesInDir(const std::string &basePath); 21448f512ceSopenharmony_ci 21548f512ceSopenharmony_cistd::vector<std::string> GetSubDirs(const std::string &basePath); 21648f512ceSopenharmony_cistd::vector<pid_t> GetSubthreadIDs(const pid_t pid, std::map<pid_t, ThreadInfos> &thread_map); 21748f512ceSopenharmony_ci 21848f512ceSopenharmony_cibool IsDir(const std::string &path); 21948f512ceSopenharmony_ci 22048f512ceSopenharmony_cibool IsPath(const std::string &fileName); 22148f512ceSopenharmony_ci 22248f512ceSopenharmony_cibool LittleMemory(); 22348f512ceSopenharmony_ci 22448f512ceSopenharmony_ci#if defined(is_mingw) && is_mingw 22548f512ceSopenharmony_ciconst char PATH_SEPARATOR = '\\'; 22648f512ceSopenharmony_ci#else 22748f512ceSopenharmony_ciconst char PATH_SEPARATOR = '/'; 22848f512ceSopenharmony_ci#endif 22948f512ceSopenharmony_ciconst std::string PATH_SEPARATOR_STR = std::string(1, PATH_SEPARATOR); 23048f512ceSopenharmony_ci 23148f512ceSopenharmony_cistd::string PlatformPathConvert(const std::string &path); 23248f512ceSopenharmony_ci 23348f512ceSopenharmony_ci// attribute 23448f512ceSopenharmony_ci#define PACKED __attribute__((packed)) 23548f512ceSopenharmony_ci 23648f512ceSopenharmony_ci// data align 23748f512ceSopenharmony_ci 23848f512ceSopenharmony_ci// some time u will meet signal 7 (SIGBUS), code 1 (BUS_ADRALN) in 32 or 64 arch cpu 23948f512ceSopenharmony_ci#define HIPERF_BUF_ALIGN alignas(64) 24048f512ceSopenharmony_ci 24148f512ceSopenharmony_ci#define ALIGN(size, align) (((size) + (align) - 1) & (~((align) - 1))) 24248f512ceSopenharmony_ci 24348f512ceSopenharmony_ciuint32_t RoundUp(uint32_t x, const int align); 24448f512ceSopenharmony_ci 24548f512ceSopenharmony_ci// data convert function 24648f512ceSopenharmony_citemplate<class T> 24748f512ceSopenharmony_cistd::string ToHex(const T &source, int size = sizeof(T), bool prefix = false) 24848f512ceSopenharmony_ci{ 24948f512ceSopenharmony_ci std::stringstream ss; 25048f512ceSopenharmony_ci if (prefix) { 25148f512ceSopenharmony_ci ss << "0x"; 25248f512ceSopenharmony_ci } 25348f512ceSopenharmony_ci ss << std::hex << std::setw(BYTE_PRINT_WIDTH * size) << std::setfill('0') << (uint64_t)source; 25448f512ceSopenharmony_ci return ss.str(); 25548f512ceSopenharmony_ci} 25648f512ceSopenharmony_ci 25748f512ceSopenharmony_ci// data move and copy 25848f512ceSopenharmony_citemplate<class S, class T> 25948f512ceSopenharmony_cisize_t inline CopyFromBufferAndMove(S *&buffer, T *dest, size_t size = 0) 26048f512ceSopenharmony_ci{ 26148f512ceSopenharmony_ci if (size == 0) { 26248f512ceSopenharmony_ci size = sizeof(T); 26348f512ceSopenharmony_ci } 26448f512ceSopenharmony_ci if (memcpy_s(dest, size, buffer, size) != EOK) { 26548f512ceSopenharmony_ci return size; 26648f512ceSopenharmony_ci } 26748f512ceSopenharmony_ci buffer = buffer + size; 26848f512ceSopenharmony_ci return size; 26948f512ceSopenharmony_ci} 27048f512ceSopenharmony_ci 27148f512ceSopenharmony_ci// file read write 27248f512ceSopenharmony_cibool ReadIntFromProcFile(const std::string &path, int &value); 27348f512ceSopenharmony_cibool WriteIntToProcFile(const std::string &path, int value); 27448f512ceSopenharmony_cistd::string ReadFileToString(const std::string &fileName); 27548f512ceSopenharmony_cibool ReadFileToString(const std::string &fileName, std::string &content, size_t fileSize = 0); 27648f512ceSopenharmony_cibool WriteStringToFile(const std::string &fileName, const std::string &value); 27748f512ceSopenharmony_ci 27848f512ceSopenharmony_ci// stdout 27948f512ceSopenharmony_ciclass StdoutRecord { 28048f512ceSopenharmony_cipublic: 28148f512ceSopenharmony_ci ~StdoutRecord() 28248f512ceSopenharmony_ci { 28348f512ceSopenharmony_ci Stop(); // stdout need restore 28448f512ceSopenharmony_ci } 28548f512ceSopenharmony_ci StdoutRecord(const std::string &tempFile = EMPTY_STRING, 28648f512ceSopenharmony_ci const std::string &mode = EMPTY_STRING); 28748f512ceSopenharmony_ci 28848f512ceSopenharmony_ci bool Start(); 28948f512ceSopenharmony_ci std::string Stop(); 29048f512ceSopenharmony_ci 29148f512ceSopenharmony_ciprivate: 29248f512ceSopenharmony_ci OHOS::UniqueFd stdoutFile_; // back and restore stdout 29348f512ceSopenharmony_ci std::FILE *recordFile_ = nullptr; // save the output 29448f512ceSopenharmony_ci bool stop_ = true; 29548f512ceSopenharmony_ci std::string content_ = EMPTY_STRING; 29648f512ceSopenharmony_ci}; 29748f512ceSopenharmony_ci 29848f512ceSopenharmony_ci// misc 29948f512ceSopenharmony_citemplate<class T> 30048f512ceSopenharmony_cifloat Percentage(const T &a, const T &b) 30148f512ceSopenharmony_ci{ 30248f512ceSopenharmony_ci if (b == 0) { 30348f512ceSopenharmony_ci return 0; 30448f512ceSopenharmony_ci } 30548f512ceSopenharmony_ci return static_cast<float>(a) / static_cast<float>(b) * FULL_PERCENTAGE; 30648f512ceSopenharmony_ci} 30748f512ceSopenharmony_ci 30848f512ceSopenharmony_cibool IsRoot(); 30948f512ceSopenharmony_cibool IsBeta(); 31048f512ceSopenharmony_cibool IsAllowProfilingUid(); 31148f512ceSopenharmony_cibool IsHiviewCall(); 31248f512ceSopenharmony_cibool PowerOfTwo(uint64_t n); 31348f512ceSopenharmony_ci 31448f512ceSopenharmony_ciconst std::string HMKERNEL = "HongMeng"; 31548f512ceSopenharmony_ci 31648f512ceSopenharmony_ci#define PRINT_INDENT(indent, format, ...) \ 31748f512ceSopenharmony_ci if (indent >= 0) { \ 31848f512ceSopenharmony_ci if (g_outputDump == nullptr) { \ 31948f512ceSopenharmony_ci printf("%*s" format, (indent)*2, "", ##__VA_ARGS__); \ 32048f512ceSopenharmony_ci } else { \ 32148f512ceSopenharmony_ci fprintf(g_outputDump, "%*s" format, (indent)*2, "", ##__VA_ARGS__); \ 32248f512ceSopenharmony_ci } \ 32348f512ceSopenharmony_ci } else { \ 32448f512ceSopenharmony_ci HLOGV("%s" format, "", ##__VA_ARGS__); \ 32548f512ceSopenharmony_ci } 32648f512ceSopenharmony_ci 32748f512ceSopenharmony_ci#ifndef MMAP_FAILED 32848f512ceSopenharmony_ci#define MMAP_FAILED reinterpret_cast<void *>(-1) 32948f512ceSopenharmony_ci#endif 33048f512ceSopenharmony_ci#ifndef MAP_FAILED 33148f512ceSopenharmony_ci#define MAP_FAILED MMAP_FAILED 33248f512ceSopenharmony_ci#endif 33348f512ceSopenharmony_cipid_t GetAppPackagePid(const std::string &appPackage, const pid_t oldPid, const int checkAppMs, 33448f512ceSopenharmony_ci const uint64_t waitAppTimeOut); 33548f512ceSopenharmony_cibool IsRestarted(const std::string &appPackage); 33648f512ceSopenharmony_civoid CollectPidsByAppname(std::set<pid_t> &pids, const std::string &appPackage); 33748f512ceSopenharmony_cibool CheckAppIsRunning (std::vector<pid_t> &selectPids, const std::string &appPackage, int checkAppMs); 33848f512ceSopenharmony_cibool IsExistDebugByApp(const std::string& bundleName); 33948f512ceSopenharmony_cibool IsExistDebugByPid(const std::vector<pid_t> &pids); 34048f512ceSopenharmony_cibool IsDebugableApp(const std::string& bundleName); 34148f512ceSopenharmony_cibool IsSupportNonDebuggableApp(); 34248f512ceSopenharmony_ciconst std::string GetUserType(); 34348f512ceSopenharmony_cibool GetDeveloperMode(); 34448f512ceSopenharmony_cibool IsArkJsFile(const std::string& filepath); 34548f512ceSopenharmony_cistd::string GetProcessName(int pid); 34648f512ceSopenharmony_cibool NeedAdaptSandboxPath(char *filename, int pid, u16 &headerSize); 34748f512ceSopenharmony_cibool NeedAdaptHMBundlePath(std::string& filename, const std::string& threadname); 34848f512ceSopenharmony_cibool IsApplicationEncryped(const int pid); 34948f512ceSopenharmony_ci 35048f512ceSopenharmony_citemplate <typename Func> 35148f512ceSopenharmony_ciclass ScopeGuard { 35248f512ceSopenharmony_cipublic: 35348f512ceSopenharmony_ci explicit ScopeGuard(Func&& fn) 35448f512ceSopenharmony_ci : fn_(fn) {} 35548f512ceSopenharmony_ci ~ScopeGuard() 35648f512ceSopenharmony_ci { 35748f512ceSopenharmony_ci fn_(); 35848f512ceSopenharmony_ci } 35948f512ceSopenharmony_ciprivate: 36048f512ceSopenharmony_ci Func fn_; 36148f512ceSopenharmony_ci}; 36248f512ceSopenharmony_ci 36348f512ceSopenharmony_cistruct ScopeGuardOnExit {}; 36448f512ceSopenharmony_citemplate <typename Func> 36548f512ceSopenharmony_cistatic inline ScopeGuard<Func> operator+(ScopeGuardOnExit, Func&& fn) 36648f512ceSopenharmony_ci{ 36748f512ceSopenharmony_ci return ScopeGuard<Func>(std::forward<Func>(fn)); 36848f512ceSopenharmony_ci} 36948f512ceSopenharmony_ci 37048f512ceSopenharmony_ci#define ON_SCOPE_EXIT \ 37148f512ceSopenharmony_ci auto __onGuardExit__ = ScopeGuardOnExit{} + [&] 37248f512ceSopenharmony_ci} // namespace HiPerf 37348f512ceSopenharmony_ci} // namespace Developtools 37448f512ceSopenharmony_ci} // namespace OHOS 37548f512ceSopenharmony_ci#endif // HIPERF_UTILITIES_H_ 376