1b0e7dd80Sopenharmony_ci/* 2b0e7dd80Sopenharmony_ci * Copyright (c) 2023-2024 Huawei Device Co., Ltd. 3b0e7dd80Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4b0e7dd80Sopenharmony_ci * you may not use this file except in compliance with the License. 5b0e7dd80Sopenharmony_ci * You may obtain a copy of the License at 6b0e7dd80Sopenharmony_ci * 7b0e7dd80Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8b0e7dd80Sopenharmony_ci * 9b0e7dd80Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10b0e7dd80Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11b0e7dd80Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12b0e7dd80Sopenharmony_ci * See the License for the specific language governing permissions and 13b0e7dd80Sopenharmony_ci * limitations under the License. 14b0e7dd80Sopenharmony_ci */ 15b0e7dd80Sopenharmony_ci 16b0e7dd80Sopenharmony_ci#include "common_utils.h" 17b0e7dd80Sopenharmony_ci 18b0e7dd80Sopenharmony_ci#include <cinttypes> 19b0e7dd80Sopenharmony_ci#include <unistd.h> 20b0e7dd80Sopenharmony_ci#include <cstdio> 21b0e7dd80Sopenharmony_ci#include <fstream> 22b0e7dd80Sopenharmony_ci#include <fcntl.h> 23b0e7dd80Sopenharmony_ci#include <sstream> 24b0e7dd80Sopenharmony_ci#include "cJSON.h" 25b0e7dd80Sopenharmony_ci#include "securec.h" 26b0e7dd80Sopenharmony_ci 27b0e7dd80Sopenharmony_cinamespace OHOS { 28b0e7dd80Sopenharmony_cinamespace HiviewDFX { 29b0e7dd80Sopenharmony_cinamespace Hitrace { 30b0e7dd80Sopenharmony_cinamespace { 31b0e7dd80Sopenharmony_ciconst std::string CPUFREQ_PREFIX = "/sys/devices/system/cpu/cpu"; 32b0e7dd80Sopenharmony_ciconst std::string CPUFREQ_AFTERFIX = "/cpufreq/scaling_cur_freq"; 33b0e7dd80Sopenharmony_ci} 34b0e7dd80Sopenharmony_ci 35b0e7dd80Sopenharmony_cistd::string CanonicalizeSpecPath(const char* src) 36b0e7dd80Sopenharmony_ci{ 37b0e7dd80Sopenharmony_ci if (src == nullptr || strlen(src) >= PATH_MAX) { 38b0e7dd80Sopenharmony_ci HILOG_ERROR(LOG_CORE, "CanonicalizeSpecPath: %{pubilc}s failed.", src); 39b0e7dd80Sopenharmony_ci return ""; 40b0e7dd80Sopenharmony_ci } 41b0e7dd80Sopenharmony_ci char resolvedPath[PATH_MAX] = { 0 }; 42b0e7dd80Sopenharmony_ci 43b0e7dd80Sopenharmony_ci if (access(src, F_OK) == 0) { 44b0e7dd80Sopenharmony_ci if (realpath(src, resolvedPath) == nullptr) { 45b0e7dd80Sopenharmony_ci HILOG_ERROR(LOG_CORE, "CanonicalizeSpecPath: realpath %{pubilc}s failed.", src); 46b0e7dd80Sopenharmony_ci return ""; 47b0e7dd80Sopenharmony_ci } 48b0e7dd80Sopenharmony_ci } else { 49b0e7dd80Sopenharmony_ci std::string fileName(src); 50b0e7dd80Sopenharmony_ci if (fileName.find("..") == std::string::npos) { 51b0e7dd80Sopenharmony_ci if (sprintf_s(resolvedPath, PATH_MAX, "%s", src) == -1) { 52b0e7dd80Sopenharmony_ci HILOG_ERROR(LOG_CORE, "CanonicalizeSpecPath: sprintf_s %{pubilc}s failed.", src); 53b0e7dd80Sopenharmony_ci return ""; 54b0e7dd80Sopenharmony_ci } 55b0e7dd80Sopenharmony_ci } else { 56b0e7dd80Sopenharmony_ci HILOG_ERROR(LOG_CORE, "CanonicalizeSpecPath: find .. src failed."); 57b0e7dd80Sopenharmony_ci return ""; 58b0e7dd80Sopenharmony_ci } 59b0e7dd80Sopenharmony_ci } 60b0e7dd80Sopenharmony_ci 61b0e7dd80Sopenharmony_ci std::string res(resolvedPath); 62b0e7dd80Sopenharmony_ci return res; 63b0e7dd80Sopenharmony_ci} 64b0e7dd80Sopenharmony_ci 65b0e7dd80Sopenharmony_cibool MarkClockSync(const std::string& traceRootPath) 66b0e7dd80Sopenharmony_ci{ 67b0e7dd80Sopenharmony_ci constexpr unsigned int bufferSize = 128; 68b0e7dd80Sopenharmony_ci char buffer[bufferSize] = { 0 }; 69b0e7dd80Sopenharmony_ci std::string traceMarker = "trace_marker"; 70b0e7dd80Sopenharmony_ci std::string resolvedPath = CanonicalizeSpecPath((traceRootPath + traceMarker).c_str()); 71b0e7dd80Sopenharmony_ci int fd = open(resolvedPath.c_str(), O_WRONLY); 72b0e7dd80Sopenharmony_ci if (fd == -1) { 73b0e7dd80Sopenharmony_ci HILOG_ERROR(LOG_CORE, "MarkClockSync: oepn %{public}s fail, errno(%{public}d)", resolvedPath.c_str(), errno); 74b0e7dd80Sopenharmony_ci return false; 75b0e7dd80Sopenharmony_ci } 76b0e7dd80Sopenharmony_ci 77b0e7dd80Sopenharmony_ci // write realtime_ts 78b0e7dd80Sopenharmony_ci struct timespec rts = {0, 0}; 79b0e7dd80Sopenharmony_ci if (clock_gettime(CLOCK_REALTIME, &rts) == -1) { 80b0e7dd80Sopenharmony_ci HILOG_ERROR(LOG_CORE, "MarkClockSync: get realtime error, errno(%{public}d)", errno); 81b0e7dd80Sopenharmony_ci close(fd); 82b0e7dd80Sopenharmony_ci return false; 83b0e7dd80Sopenharmony_ci } 84b0e7dd80Sopenharmony_ci constexpr unsigned int nanoSeconds = 1000000000; // seconds converted to nanoseconds 85b0e7dd80Sopenharmony_ci constexpr unsigned int nanoToMill = 1000000; // millisecond converted to nanoseconds 86b0e7dd80Sopenharmony_ci int len = snprintf_s(buffer, sizeof(buffer), sizeof(buffer) - 1, 87b0e7dd80Sopenharmony_ci "trace_event_clock_sync: realtime_ts=%" PRId64 "\n", 88b0e7dd80Sopenharmony_ci static_cast<int64_t>((rts.tv_sec * nanoSeconds + rts.tv_nsec) / nanoToMill)); 89b0e7dd80Sopenharmony_ci if (len < 0) { 90b0e7dd80Sopenharmony_ci HILOG_ERROR(LOG_CORE, "MarkClockSync: entering realtime_ts into buffer error, errno(%{public}d)", errno); 91b0e7dd80Sopenharmony_ci close(fd); 92b0e7dd80Sopenharmony_ci return false; 93b0e7dd80Sopenharmony_ci } 94b0e7dd80Sopenharmony_ci 95b0e7dd80Sopenharmony_ci if (write(fd, buffer, len) < 0) { 96b0e7dd80Sopenharmony_ci HILOG_ERROR(LOG_CORE, "MarkClockSync: writing realtime error, errno(%{public}d)", errno); 97b0e7dd80Sopenharmony_ci } 98b0e7dd80Sopenharmony_ci 99b0e7dd80Sopenharmony_ci // write parent_ts 100b0e7dd80Sopenharmony_ci struct timespec mts = {0, 0}; 101b0e7dd80Sopenharmony_ci if (clock_gettime(CLOCK_MONOTONIC, &mts) == -1) { 102b0e7dd80Sopenharmony_ci HILOG_ERROR(LOG_CORE, "MarkClockSync: get parent_ts error, errno(%{public}d)", errno); 103b0e7dd80Sopenharmony_ci close(fd); 104b0e7dd80Sopenharmony_ci return false; 105b0e7dd80Sopenharmony_ci } 106b0e7dd80Sopenharmony_ci constexpr float nanoToSecond = 1000000000.0f; // consistent with the ftrace timestamp format 107b0e7dd80Sopenharmony_ci len = snprintf_s(buffer, sizeof(buffer), sizeof(buffer) - 1, "trace_event_clock_sync: parent_ts=%f\n", 108b0e7dd80Sopenharmony_ci static_cast<float>(((static_cast<float>(mts.tv_sec)) * nanoSeconds + mts.tv_nsec) / nanoToSecond)); 109b0e7dd80Sopenharmony_ci if (len < 0) { 110b0e7dd80Sopenharmony_ci HILOG_ERROR(LOG_CORE, "MarkClockSync: entering parent_ts into buffer error, errno(%{public}d)", errno); 111b0e7dd80Sopenharmony_ci close(fd); 112b0e7dd80Sopenharmony_ci return false; 113b0e7dd80Sopenharmony_ci } 114b0e7dd80Sopenharmony_ci if (write(fd, buffer, len) < 0) { 115b0e7dd80Sopenharmony_ci HILOG_ERROR(LOG_CORE, "MarkClockSync: writing parent_ts error, errno(%{public}d)", errno); 116b0e7dd80Sopenharmony_ci } 117b0e7dd80Sopenharmony_ci close(fd); 118b0e7dd80Sopenharmony_ci return true; 119b0e7dd80Sopenharmony_ci} 120b0e7dd80Sopenharmony_ci 121b0e7dd80Sopenharmony_cistatic cJSON* ParseJsonFromFile(const std::string& filePath) 122b0e7dd80Sopenharmony_ci{ 123b0e7dd80Sopenharmony_ci std::ifstream inFile(filePath, std::ios::in); 124b0e7dd80Sopenharmony_ci if (!inFile.is_open()) { 125b0e7dd80Sopenharmony_ci HILOG_ERROR(LOG_CORE, "ParseJsonFromFile: %{public}s is not existed.", filePath.c_str()); 126b0e7dd80Sopenharmony_ci return nullptr; 127b0e7dd80Sopenharmony_ci } 128b0e7dd80Sopenharmony_ci std::string fileContent((std::istreambuf_iterator<char>(inFile)), std::istreambuf_iterator<char>()); 129b0e7dd80Sopenharmony_ci cJSON* root = cJSON_Parse(fileContent.c_str()); 130b0e7dd80Sopenharmony_ci if (root == nullptr) { 131b0e7dd80Sopenharmony_ci HILOG_ERROR(LOG_CORE, "ParseJsonFromFile: %{public}s is not in JSON format.", filePath.c_str()); 132b0e7dd80Sopenharmony_ci } 133b0e7dd80Sopenharmony_ci inFile.close(); 134b0e7dd80Sopenharmony_ci return root; 135b0e7dd80Sopenharmony_ci} 136b0e7dd80Sopenharmony_ci 137b0e7dd80Sopenharmony_cistatic void ParseSysFiles(cJSON *tags, TagCategory& tagCategory) 138b0e7dd80Sopenharmony_ci{ 139b0e7dd80Sopenharmony_ci cJSON *sysFiles = cJSON_GetObjectItem(tags, "sysFiles"); 140b0e7dd80Sopenharmony_ci if (sysFiles != nullptr && cJSON_IsArray(sysFiles)) { 141b0e7dd80Sopenharmony_ci cJSON *sysFile = nullptr; 142b0e7dd80Sopenharmony_ci cJSON_ArrayForEach(sysFile, sysFiles) { 143b0e7dd80Sopenharmony_ci if (cJSON_IsString(sysFile)) { 144b0e7dd80Sopenharmony_ci tagCategory.sysFiles.push_back(sysFile->valuestring); 145b0e7dd80Sopenharmony_ci } 146b0e7dd80Sopenharmony_ci } 147b0e7dd80Sopenharmony_ci } 148b0e7dd80Sopenharmony_ci} 149b0e7dd80Sopenharmony_ci 150b0e7dd80Sopenharmony_cistatic bool ParseTagCategory(cJSON* tagCategoryNode, std::map<std::string, TagCategory>& allTags) 151b0e7dd80Sopenharmony_ci{ 152b0e7dd80Sopenharmony_ci cJSON* tags = nullptr; 153b0e7dd80Sopenharmony_ci cJSON_ArrayForEach(tags, tagCategoryNode) { 154b0e7dd80Sopenharmony_ci if (tags == nullptr || tags->string == nullptr) { 155b0e7dd80Sopenharmony_ci continue; 156b0e7dd80Sopenharmony_ci } 157b0e7dd80Sopenharmony_ci TagCategory tagCategory; 158b0e7dd80Sopenharmony_ci cJSON* description = cJSON_GetObjectItem(tags, "description"); 159b0e7dd80Sopenharmony_ci if (description != nullptr && cJSON_IsString(description)) { 160b0e7dd80Sopenharmony_ci tagCategory.description = description->valuestring; 161b0e7dd80Sopenharmony_ci } 162b0e7dd80Sopenharmony_ci cJSON* tagOffset = cJSON_GetObjectItem(tags, "tag_offset"); 163b0e7dd80Sopenharmony_ci if (tagOffset != nullptr && cJSON_IsNumber(tagOffset)) { 164b0e7dd80Sopenharmony_ci tagCategory.tag = 1ULL << tagOffset->valueint; 165b0e7dd80Sopenharmony_ci } 166b0e7dd80Sopenharmony_ci cJSON* type = cJSON_GetObjectItem(tags, "type"); 167b0e7dd80Sopenharmony_ci if (type != nullptr && cJSON_IsNumber(type)) { 168b0e7dd80Sopenharmony_ci tagCategory.type = type->valueint; 169b0e7dd80Sopenharmony_ci } 170b0e7dd80Sopenharmony_ci ParseSysFiles(tags, tagCategory); 171b0e7dd80Sopenharmony_ci allTags.insert(std::pair<std::string, TagCategory>(tags->string, tagCategory)); 172b0e7dd80Sopenharmony_ci } 173b0e7dd80Sopenharmony_ci return true; 174b0e7dd80Sopenharmony_ci} 175b0e7dd80Sopenharmony_ci 176b0e7dd80Sopenharmony_cistatic bool ParseTagGroups(cJSON* tagGroupsNode, std::map<std::string, std::vector<std::string>> &tagGroupTable) 177b0e7dd80Sopenharmony_ci{ 178b0e7dd80Sopenharmony_ci cJSON* tagGroup = nullptr; 179b0e7dd80Sopenharmony_ci cJSON_ArrayForEach(tagGroup, tagGroupsNode) { 180b0e7dd80Sopenharmony_ci if (tagGroup == nullptr || tagGroup->string == nullptr) { 181b0e7dd80Sopenharmony_ci continue; 182b0e7dd80Sopenharmony_ci } 183b0e7dd80Sopenharmony_ci std::string tagGroupName = tagGroup->string; 184b0e7dd80Sopenharmony_ci std::vector<std::string> tagList; 185b0e7dd80Sopenharmony_ci cJSON* tag = nullptr; 186b0e7dd80Sopenharmony_ci cJSON_ArrayForEach(tag, tagGroup) { 187b0e7dd80Sopenharmony_ci if (cJSON_IsString(tag)) { 188b0e7dd80Sopenharmony_ci tagList.push_back(tag->valuestring); 189b0e7dd80Sopenharmony_ci } 190b0e7dd80Sopenharmony_ci } 191b0e7dd80Sopenharmony_ci tagGroupTable.insert(std::pair<std::string, std::vector<std::string>>(tagGroupName, tagList)); 192b0e7dd80Sopenharmony_ci } 193b0e7dd80Sopenharmony_ci return true; 194b0e7dd80Sopenharmony_ci} 195b0e7dd80Sopenharmony_ci 196b0e7dd80Sopenharmony_cibool ParseTagInfo(std::map<std::string, TagCategory> &allTags, 197b0e7dd80Sopenharmony_ci std::map<std::string, std::vector<std::string>> &tagGroupTable) 198b0e7dd80Sopenharmony_ci{ 199b0e7dd80Sopenharmony_ci std::string traceUtilsPath = "/system/etc/hiview/hitrace_utils.json"; 200b0e7dd80Sopenharmony_ci cJSON* root = ParseJsonFromFile(traceUtilsPath); 201b0e7dd80Sopenharmony_ci if (root == nullptr) { 202b0e7dd80Sopenharmony_ci return false; 203b0e7dd80Sopenharmony_ci } 204b0e7dd80Sopenharmony_ci cJSON* tagCategory = cJSON_GetObjectItem(root, "tag_category"); 205b0e7dd80Sopenharmony_ci if (tagCategory == nullptr) { 206b0e7dd80Sopenharmony_ci HILOG_ERROR(LOG_CORE, "ParseTagInfo: %{public}s is not contain tag_category node.", traceUtilsPath.c_str()); 207b0e7dd80Sopenharmony_ci cJSON_Delete(root); 208b0e7dd80Sopenharmony_ci return false; 209b0e7dd80Sopenharmony_ci } 210b0e7dd80Sopenharmony_ci if (!ParseTagCategory(tagCategory, allTags)) { 211b0e7dd80Sopenharmony_ci cJSON_Delete(root); 212b0e7dd80Sopenharmony_ci return false; 213b0e7dd80Sopenharmony_ci } 214b0e7dd80Sopenharmony_ci cJSON* tagGroups = cJSON_GetObjectItem(root, "tag_groups"); 215b0e7dd80Sopenharmony_ci if (tagGroups == nullptr) { 216b0e7dd80Sopenharmony_ci HILOG_ERROR(LOG_CORE, "ParseTagInfo: %{public}s is not contain tag_groups node.", traceUtilsPath.c_str()); 217b0e7dd80Sopenharmony_ci cJSON_Delete(root); 218b0e7dd80Sopenharmony_ci return false; 219b0e7dd80Sopenharmony_ci } 220b0e7dd80Sopenharmony_ci if (!ParseTagGroups(tagGroups, tagGroupTable)) { 221b0e7dd80Sopenharmony_ci cJSON_Delete(root); 222b0e7dd80Sopenharmony_ci return false; 223b0e7dd80Sopenharmony_ci } 224b0e7dd80Sopenharmony_ci cJSON_Delete(root); 225b0e7dd80Sopenharmony_ci HILOG_INFO(LOG_CORE, "ParseTagInfo: parse done."); 226b0e7dd80Sopenharmony_ci return true; 227b0e7dd80Sopenharmony_ci} 228b0e7dd80Sopenharmony_ci 229b0e7dd80Sopenharmony_cibool IsNumber(const std::string &str) 230b0e7dd80Sopenharmony_ci{ 231b0e7dd80Sopenharmony_ci if (str.empty()) { 232b0e7dd80Sopenharmony_ci return false; 233b0e7dd80Sopenharmony_ci } 234b0e7dd80Sopenharmony_ci for (auto c : str) { 235b0e7dd80Sopenharmony_ci if (!isdigit(c)) { 236b0e7dd80Sopenharmony_ci return false; 237b0e7dd80Sopenharmony_ci } 238b0e7dd80Sopenharmony_ci } 239b0e7dd80Sopenharmony_ci return true; 240b0e7dd80Sopenharmony_ci} 241b0e7dd80Sopenharmony_ci 242b0e7dd80Sopenharmony_ciint GetCpuProcessors() 243b0e7dd80Sopenharmony_ci{ 244b0e7dd80Sopenharmony_ci int processors = 0; 245b0e7dd80Sopenharmony_ci processors = sysconf(_SC_NPROCESSORS_CONF); 246b0e7dd80Sopenharmony_ci return (processors == 0) ? 1 : processors; 247b0e7dd80Sopenharmony_ci} 248b0e7dd80Sopenharmony_ci 249b0e7dd80Sopenharmony_civoid ReadCurrentCpuFrequencies(std::string& freqs) 250b0e7dd80Sopenharmony_ci{ 251b0e7dd80Sopenharmony_ci int cpuNum = GetCpuProcessors(); 252b0e7dd80Sopenharmony_ci std::ifstream file; 253b0e7dd80Sopenharmony_ci std::string line; 254b0e7dd80Sopenharmony_ci for (int i = 0; i < cpuNum; ++i) { 255b0e7dd80Sopenharmony_ci std::string freq = "0"; 256b0e7dd80Sopenharmony_ci std::string cpuFreqPath = CPUFREQ_PREFIX + std::to_string(i) + CPUFREQ_AFTERFIX; 257b0e7dd80Sopenharmony_ci file.open(cpuFreqPath); 258b0e7dd80Sopenharmony_ci if (file.is_open()) { 259b0e7dd80Sopenharmony_ci if (std::getline(file, line)) { 260b0e7dd80Sopenharmony_ci std::istringstream iss(line); 261b0e7dd80Sopenharmony_ci iss >> freq; 262b0e7dd80Sopenharmony_ci } 263b0e7dd80Sopenharmony_ci file.close(); 264b0e7dd80Sopenharmony_ci } 265b0e7dd80Sopenharmony_ci freqs += "cpu_id=" + std::to_string(i) + " state=" + freq; 266b0e7dd80Sopenharmony_ci if (i != cpuNum - 1) { 267b0e7dd80Sopenharmony_ci freqs += ","; 268b0e7dd80Sopenharmony_ci } 269b0e7dd80Sopenharmony_ci } 270b0e7dd80Sopenharmony_ci} 271b0e7dd80Sopenharmony_ci} // namespace Hitrace 272b0e7dd80Sopenharmony_ci} // namespace HiviewDFX 273b0e7dd80Sopenharmony_ci} // namespace OHOS 274