1570af302Sopenharmony_ci 2570af302Sopenharmony_ci/* 3570af302Sopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd. 4570af302Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 5570af302Sopenharmony_ci * you may not use this file except in compliance with the License. 6570af302Sopenharmony_ci * You may obtain a copy of the License at 7570af302Sopenharmony_ci * 8570af302Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 9570af302Sopenharmony_ci * 10570af302Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 11570af302Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 12570af302Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13570af302Sopenharmony_ci * See the License for the specific language governing permissions and 14570af302Sopenharmony_ci * limitations under the License. 15570af302Sopenharmony_ci */ 16570af302Sopenharmony_ci 17570af302Sopenharmony_ci#include <trace/trace_marker.h> 18570af302Sopenharmony_ci 19570af302Sopenharmony_ci#include <errno.h> 20570af302Sopenharmony_ci#include <fcntl.h> 21570af302Sopenharmony_ci#include <stdbool.h> 22570af302Sopenharmony_ci#include <stdio.h> 23570af302Sopenharmony_ci#include <stdlib.h> 24570af302Sopenharmony_ci#include <string.h> 25570af302Sopenharmony_ci#include <sys/types.h> 26570af302Sopenharmony_ci#include <unistd.h> 27570af302Sopenharmony_ci#include "musl_log.h" 28570af302Sopenharmony_ci#ifdef OHOS_ENABLE_PARAMETER 29570af302Sopenharmony_ci#include "sys_param.h" 30570af302Sopenharmony_ci#endif 31570af302Sopenharmony_ci 32570af302Sopenharmony_ci#ifndef MUSL_TEMP_FAILURE_RETRY 33570af302Sopenharmony_ci#define MUSL_TEMP_FAILURE_RETRY(exp) \ 34570af302Sopenharmony_ci ({ \ 35570af302Sopenharmony_ci long int _rc; \ 36570af302Sopenharmony_ci do { \ 37570af302Sopenharmony_ci _rc = (long int)(exp); \ 38570af302Sopenharmony_ci } while ((_rc == -1) && (errno == EINTR)); \ 39570af302Sopenharmony_ci _rc; \ 40570af302Sopenharmony_ci }) 41570af302Sopenharmony_ci#endif 42570af302Sopenharmony_ci 43570af302Sopenharmony_ci#define LIKELY(exp) (__builtin_expect(!!(exp), 1)) 44570af302Sopenharmony_ci 45570af302Sopenharmony_ci#ifdef OHOS_ENABLE_PARAMETER 46570af302Sopenharmony_ci#define TRACE_PROPERTY_FLAG "debug.hitrace.tags.enableflags" 47570af302Sopenharmony_cistatic uint64_t g_trace_switch_status = 0; 48570af302Sopenharmony_ci 49570af302Sopenharmony_ciuint64_t get_uint64_sysparam(CachedHandle cachedhandle) 50570af302Sopenharmony_ci{ 51570af302Sopenharmony_ci char *param_value = CachedParameterGet(cachedhandle); 52570af302Sopenharmony_ci if (param_value != NULL) { 53570af302Sopenharmony_ci return strtoull(param_value, NULL, 0); 54570af302Sopenharmony_ci } 55570af302Sopenharmony_ci return 0; 56570af302Sopenharmony_ci} 57570af302Sopenharmony_ci#endif 58570af302Sopenharmony_ci 59570af302Sopenharmony_civoid trace_marker_reset(void) 60570af302Sopenharmony_ci{ 61570af302Sopenharmony_ci#ifdef OHOS_ENABLE_PARAMETER 62570af302Sopenharmony_ci static CachedHandle trace_switch_handle = NULL; 63570af302Sopenharmony_ci if (trace_switch_handle == NULL) { 64570af302Sopenharmony_ci trace_switch_handle = CachedParameterCreate(TRACE_PROPERTY_FLAG, "0"); 65570af302Sopenharmony_ci } 66570af302Sopenharmony_ci g_trace_switch_status = get_uint64_sysparam(trace_switch_handle); 67570af302Sopenharmony_ci#else 68570af302Sopenharmony_ci return; 69570af302Sopenharmony_ci#endif 70570af302Sopenharmony_ci} 71570af302Sopenharmony_ci 72570af302Sopenharmony_ci// Check whether the user space trace function is enabled 73570af302Sopenharmony_cistatic inline bool is_enable_trace(uint64_t label) 74570af302Sopenharmony_ci{ 75570af302Sopenharmony_ci#ifdef OHOS_ENABLE_PARAMETER 76570af302Sopenharmony_ci return (((g_trace_switch_status & label) != 0) || ((g_trace_switch_status & HITRACE_TAG_ALWAYS) != 0)); 77570af302Sopenharmony_ci#else 78570af302Sopenharmony_ci return false; 79570af302Sopenharmony_ci#endif 80570af302Sopenharmony_ci} 81570af302Sopenharmony_ci 82570af302Sopenharmony_ci// Get the fd of trace_marker 83570af302Sopenharmony_cistatic inline int get_trace_marker_fd(void) 84570af302Sopenharmony_ci{ 85570af302Sopenharmony_ci int trace_marker_fd = MUSL_TEMP_FAILURE_RETRY(open("/sys/kernel/tracing/trace_marker", O_CLOEXEC | O_WRONLY | O_APPEND)); 86570af302Sopenharmony_ci if (trace_marker_fd == -1) { 87570af302Sopenharmony_ci trace_marker_fd = MUSL_TEMP_FAILURE_RETRY(open("/sys/kernel/debug/tracing/trace_marker", O_CLOEXEC | O_WRONLY | O_APPEND)); 88570af302Sopenharmony_ci } 89570af302Sopenharmony_ci return trace_marker_fd; 90570af302Sopenharmony_ci} 91570af302Sopenharmony_ci 92570af302Sopenharmony_ci/* Write the function call information to the trace_marker node in kernel space, 93570af302Sopenharmony_ciused on the same thread as trace_marker_end(),with the symbol "B". */ 94570af302Sopenharmony_civoid trace_marker_begin(uint64_t label, const char *message, const char *value) 95570af302Sopenharmony_ci{ 96570af302Sopenharmony_ci if (LIKELY((!is_enable_trace(label) || message == NULL))) { 97570af302Sopenharmony_ci return; 98570af302Sopenharmony_ci } 99570af302Sopenharmony_ci 100570af302Sopenharmony_ci int trace_marker_fd = get_trace_marker_fd(); 101570af302Sopenharmony_ci if (trace_marker_fd == -1) { 102570af302Sopenharmony_ci return; 103570af302Sopenharmony_ci } 104570af302Sopenharmony_ci 105570af302Sopenharmony_ci char buf[TRACE_MARKER_MESSAGE_LEN] = {0}; 106570af302Sopenharmony_ci int len = 0; 107570af302Sopenharmony_ci if (value == NULL) { 108570af302Sopenharmony_ci len = snprintf(buf, TRACE_MARKER_MESSAGE_LEN, "B|%d|%s", getpid(), message); 109570af302Sopenharmony_ci } else { 110570af302Sopenharmony_ci len = snprintf(buf, TRACE_MARKER_MESSAGE_LEN, "B|%d|%s %s", getpid(), message, value); 111570af302Sopenharmony_ci } 112570af302Sopenharmony_ci if (len > 0 && len < sizeof(buf)) { 113570af302Sopenharmony_ci int ret = MUSL_TEMP_FAILURE_RETRY(write(trace_marker_fd, buf, len)); 114570af302Sopenharmony_ci if (ret == -1) { 115570af302Sopenharmony_ci MUSL_LOGE("fail to write B. %d", ret); 116570af302Sopenharmony_ci } 117570af302Sopenharmony_ci } else { 118570af302Sopenharmony_ci MUSL_LOGE("B length error. %d", len); 119570af302Sopenharmony_ci } 120570af302Sopenharmony_ci 121570af302Sopenharmony_ci // close file descriptor of trace_marker 122570af302Sopenharmony_ci close(trace_marker_fd); 123570af302Sopenharmony_ci} 124570af302Sopenharmony_ci 125570af302Sopenharmony_ci/* Write the terminator to the trace_marker node of the kernel space, 126570af302Sopenharmony_ciused on the same thread as trace_marker_begin(),with the symbol "E". */ 127570af302Sopenharmony_civoid trace_marker_end(uint64_t label) 128570af302Sopenharmony_ci{ 129570af302Sopenharmony_ci if (LIKELY(!is_enable_trace(label))) { 130570af302Sopenharmony_ci return; 131570af302Sopenharmony_ci } 132570af302Sopenharmony_ci 133570af302Sopenharmony_ci int trace_marker_fd = get_trace_marker_fd(); 134570af302Sopenharmony_ci if (trace_marker_fd == -1) { 135570af302Sopenharmony_ci return; 136570af302Sopenharmony_ci } 137570af302Sopenharmony_ci 138570af302Sopenharmony_ci char buf[TRACE_MARKER_MESSAGE_LEN] = {0}; 139570af302Sopenharmony_ci int len = snprintf(buf, TRACE_MARKER_MESSAGE_LEN, "E|%d", getpid()); 140570af302Sopenharmony_ci if (len > 0 && len < sizeof(buf)) { 141570af302Sopenharmony_ci int ret = MUSL_TEMP_FAILURE_RETRY(write(trace_marker_fd, buf, len)); 142570af302Sopenharmony_ci if (ret == -1) { 143570af302Sopenharmony_ci MUSL_LOGE("fail to write E. %d", ret); 144570af302Sopenharmony_ci } 145570af302Sopenharmony_ci } else { 146570af302Sopenharmony_ci MUSL_LOGE("E length error. %d", len); 147570af302Sopenharmony_ci } 148570af302Sopenharmony_ci 149570af302Sopenharmony_ci // close file descriptor of trace_marker 150570af302Sopenharmony_ci close(trace_marker_fd); 151570af302Sopenharmony_ci} 152570af302Sopenharmony_ci 153570af302Sopenharmony_ci/* Write the function call information to the trace_marker node in kernel space, 154570af302Sopenharmony_ciused in a different thread than trace_marker_async_end(),with the symbol "S". */ 155570af302Sopenharmony_civoid trace_marker_async_begin(uint64_t label, const char *message, const char *value, int taskId) 156570af302Sopenharmony_ci{ 157570af302Sopenharmony_ci if (LIKELY((!is_enable_trace(label) || message == NULL))) { 158570af302Sopenharmony_ci return; 159570af302Sopenharmony_ci } 160570af302Sopenharmony_ci 161570af302Sopenharmony_ci int trace_marker_fd = get_trace_marker_fd(); 162570af302Sopenharmony_ci if (trace_marker_fd == -1) { 163570af302Sopenharmony_ci return; 164570af302Sopenharmony_ci } 165570af302Sopenharmony_ci 166570af302Sopenharmony_ci char buf[TRACE_MARKER_MESSAGE_LEN] = {0}; 167570af302Sopenharmony_ci int len = 0; 168570af302Sopenharmony_ci if (value == NULL) { 169570af302Sopenharmony_ci len = snprintf(buf, TRACE_MARKER_MESSAGE_LEN, "S|%d|%s %d", getpid(), message, taskId); 170570af302Sopenharmony_ci } else { 171570af302Sopenharmony_ci len = snprintf(buf, TRACE_MARKER_MESSAGE_LEN, "S|%d|%s|%s %d", getpid(), message, value, taskId); 172570af302Sopenharmony_ci } 173570af302Sopenharmony_ci if (len > 0 && len < sizeof(buf)) { 174570af302Sopenharmony_ci int ret = MUSL_TEMP_FAILURE_RETRY(write(trace_marker_fd, buf, len)); 175570af302Sopenharmony_ci if (ret == -1) { 176570af302Sopenharmony_ci MUSL_LOGE("fail to write S. %d", ret); 177570af302Sopenharmony_ci } 178570af302Sopenharmony_ci } else { 179570af302Sopenharmony_ci MUSL_LOGE("S length error. %d", len); 180570af302Sopenharmony_ci } 181570af302Sopenharmony_ci 182570af302Sopenharmony_ci // close file descriptor of trace_marker 183570af302Sopenharmony_ci close(trace_marker_fd); 184570af302Sopenharmony_ci} 185570af302Sopenharmony_ci 186570af302Sopenharmony_ci/* Write the terminator to the trace_marker node in kernel space, 187570af302Sopenharmony_ciused in a different thread than trace_marker_async_begin(),with the symbol "F". */ 188570af302Sopenharmony_civoid trace_marker_async_end(uint64_t label, const char *message, const char *value, int taskId) 189570af302Sopenharmony_ci{ 190570af302Sopenharmony_ci if (LIKELY((!is_enable_trace(label) || message == NULL))) { 191570af302Sopenharmony_ci return; 192570af302Sopenharmony_ci } 193570af302Sopenharmony_ci 194570af302Sopenharmony_ci int trace_marker_fd = get_trace_marker_fd(); 195570af302Sopenharmony_ci if (trace_marker_fd == -1) { 196570af302Sopenharmony_ci return; 197570af302Sopenharmony_ci } 198570af302Sopenharmony_ci 199570af302Sopenharmony_ci char buf[TRACE_MARKER_MESSAGE_LEN] = {0}; 200570af302Sopenharmony_ci int len = 0; 201570af302Sopenharmony_ci if (value == NULL) { 202570af302Sopenharmony_ci len = snprintf(buf, TRACE_MARKER_MESSAGE_LEN, "F|%d|%s %d", getpid(), message, taskId); 203570af302Sopenharmony_ci } else { 204570af302Sopenharmony_ci len = snprintf(buf, TRACE_MARKER_MESSAGE_LEN, "F|%d|%s|%s %d", getpid(), message, value, taskId); 205570af302Sopenharmony_ci } 206570af302Sopenharmony_ci if (len > 0 && len < sizeof(buf)) { 207570af302Sopenharmony_ci int ret = MUSL_TEMP_FAILURE_RETRY(write(trace_marker_fd, buf, len)); 208570af302Sopenharmony_ci if (ret == -1) { 209570af302Sopenharmony_ci MUSL_LOGE("fail to write F. %d", ret); 210570af302Sopenharmony_ci } 211570af302Sopenharmony_ci } else { 212570af302Sopenharmony_ci MUSL_LOGE("F length error. %d", len); 213570af302Sopenharmony_ci } 214570af302Sopenharmony_ci 215570af302Sopenharmony_ci // close file descriptor of trace_marker 216570af302Sopenharmony_ci close(trace_marker_fd); 217570af302Sopenharmony_ci} 218570af302Sopenharmony_ci 219570af302Sopenharmony_ci// A numeric variable used to mark a pre trace, with the symbol "C". 220570af302Sopenharmony_civoid trace_marker_count(uint64_t label, const char *message, int value) 221570af302Sopenharmony_ci{ 222570af302Sopenharmony_ci if (LIKELY((!is_enable_trace(label) || message == NULL))) { 223570af302Sopenharmony_ci return; 224570af302Sopenharmony_ci } 225570af302Sopenharmony_ci 226570af302Sopenharmony_ci int trace_marker_fd = get_trace_marker_fd(); 227570af302Sopenharmony_ci if (trace_marker_fd == -1) { 228570af302Sopenharmony_ci return; 229570af302Sopenharmony_ci } 230570af302Sopenharmony_ci 231570af302Sopenharmony_ci char buf[TRACE_MARKER_MESSAGE_LEN] = {0}; 232570af302Sopenharmony_ci int len = snprintf(buf, TRACE_MARKER_MESSAGE_LEN, "C|%d|%s %d", getpid(), message, value); 233570af302Sopenharmony_ci if (len > 0 && len < sizeof(buf)) { 234570af302Sopenharmony_ci int ret = MUSL_TEMP_FAILURE_RETRY(write(trace_marker_fd, buf, len)); 235570af302Sopenharmony_ci if (ret == -1) { 236570af302Sopenharmony_ci MUSL_LOGE("fail to write C. %d", ret); 237570af302Sopenharmony_ci } 238570af302Sopenharmony_ci } else { 239570af302Sopenharmony_ci MUSL_LOGE("C length error. %d", len); 240570af302Sopenharmony_ci } 241570af302Sopenharmony_ci 242570af302Sopenharmony_ci // close file descriptor of trace_marker 243570af302Sopenharmony_ci close(trace_marker_fd); 244570af302Sopenharmony_ci} 245570af302Sopenharmony_ci 246