• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 /*
3  * Copyright (c) 2023 Huawei Device Co., Ltd.
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <trace/trace_marker.h>
18 
19 #include <errno.h>
20 #include <fcntl.h>
21 #include <stdbool.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <sys/types.h>
26 #include <unistd.h>
27 #include "musl_log.h"
28 #ifdef OHOS_ENABLE_PARAMETER
29 #include "sys_param.h"
30 #endif
31 
32 #ifndef MUSL_TEMP_FAILURE_RETRY
33 #define MUSL_TEMP_FAILURE_RETRY(exp)           \
34     ({                                         \
35     long int _rc;                              \
36     do {                                       \
37         _rc = (long int)(exp);                 \
38     } while ((_rc == -1) && (errno == EINTR)); \
39     _rc;                                       \
40     })
41 #endif
42 
43 #define LIKELY(exp) (__builtin_expect(!!(exp), 1))
44 
45 #ifdef OHOS_ENABLE_PARAMETER
46 #define TRACE_PROPERTY_FLAG "debug.hitrace.tags.enableflags"
47 static uint64_t g_trace_switch_status = 0;
48 
get_uint64_sysparam(CachedHandle cachedhandle)49 uint64_t get_uint64_sysparam(CachedHandle cachedhandle)
50 {
51     const char *param_value = CachedParameterGet(cachedhandle);
52     if (param_value != NULL) {
53         return strtoull(param_value, NULL, 0);
54     }
55     return 0;
56 }
57 #endif
58 
trace_marker_reset(void)59 void trace_marker_reset(void)
60 {
61 #ifdef OHOS_ENABLE_PARAMETER
62     static CachedHandle trace_switch_handle = NULL;
63     if (trace_switch_handle == NULL) {
64         trace_switch_handle = CachedParameterCreate(TRACE_PROPERTY_FLAG, "0");
65     }
66     g_trace_switch_status = get_uint64_sysparam(trace_switch_handle);
67 #else
68     return;
69 #endif
70 }
71 
72 // Check whether the user space trace function is enabled
is_enable_trace(uint64_t label)73 static inline bool is_enable_trace(uint64_t label)
74 {
75 #ifdef OHOS_ENABLE_PARAMETER
76     return (((g_trace_switch_status & label) != 0) || ((g_trace_switch_status & HITRACE_TAG_ALWAYS) != 0));
77 #else
78     return false;
79 #endif
80 }
81 
82 // Get the fd of trace_marker
get_trace_marker_fd(void)83 static inline int get_trace_marker_fd(void)
84 {
85     int trace_marker_fd = MUSL_TEMP_FAILURE_RETRY(open("/sys/kernel/tracing/trace_marker", O_CLOEXEC | O_WRONLY | O_APPEND));
86     if (trace_marker_fd == -1) {
87         trace_marker_fd = MUSL_TEMP_FAILURE_RETRY(open("/sys/kernel/debug/tracing/trace_marker", O_CLOEXEC | O_WRONLY | O_APPEND));
88     }
89     return trace_marker_fd;
90 }
91 
92 /* Write the function call information to the trace_marker node in kernel space,
93 used on the same thread as trace_marker_end(),with the symbol "B". */
trace_marker_begin(uint64_t label,const char * message,const char * value)94 void trace_marker_begin(uint64_t label, const char *message, const char *value)
95 {
96     if (LIKELY((!is_enable_trace(label) || message == NULL))) {
97         return;
98     }
99 
100     int trace_marker_fd = get_trace_marker_fd();
101     if (trace_marker_fd == -1) {
102         return;
103     }
104 
105     char buf[TRACE_MARKER_MESSAGE_LEN] = {0};
106     int len = 0;
107     if (value == NULL) {
108         len = snprintf(buf, TRACE_MARKER_MESSAGE_LEN, "B|%d|%s", getpid(), message);
109     } else {
110         len = snprintf(buf, TRACE_MARKER_MESSAGE_LEN, "B|%d|%s %s", getpid(), message, value);
111     }
112     if (len > 0 && len < sizeof(buf)) {
113         int ret = MUSL_TEMP_FAILURE_RETRY(write(trace_marker_fd, buf, len));
114         if (ret == -1) {
115             MUSL_LOGW("fail to write B. %d", ret);
116         }
117     } else {
118         MUSL_LOGW("B length error. %d", len);
119     }
120 
121     // close file descriptor of trace_marker
122     close(trace_marker_fd);
123 }
124 
125 /* Write the terminator to the trace_marker node of the kernel space,
126 used on the same thread as trace_marker_begin(),with the symbol "E". */
trace_marker_end(uint64_t label)127 void trace_marker_end(uint64_t label)
128 {
129     if (LIKELY(!is_enable_trace(label))) {
130         return;
131     }
132 
133     int trace_marker_fd = get_trace_marker_fd();
134     if (trace_marker_fd == -1) {
135         return;
136     }
137 
138     char buf[TRACE_MARKER_MESSAGE_LEN] = {0};
139     int len = snprintf(buf, TRACE_MARKER_MESSAGE_LEN, "E|%d", getpid());
140     if (len > 0 && len < sizeof(buf)) {
141         int ret = MUSL_TEMP_FAILURE_RETRY(write(trace_marker_fd, buf, len));
142         if (ret == -1) {
143             MUSL_LOGW("fail to write E. %d", ret);
144         }
145     } else {
146         MUSL_LOGW("E length error. %d", len);
147     }
148 
149     // close file descriptor of trace_marker
150     close(trace_marker_fd);
151 }
152 
153 /* Write the function call information to the trace_marker node in kernel space,
154 used in a different thread than trace_marker_async_end(),with the symbol "S". */
trace_marker_async_begin(uint64_t label,const char * message,const char * value,int taskId)155 void trace_marker_async_begin(uint64_t label, const char *message, const char *value, int taskId)
156 {
157     if (LIKELY((!is_enable_trace(label) || message == NULL))) {
158         return;
159     }
160 
161     int trace_marker_fd = get_trace_marker_fd();
162     if (trace_marker_fd == -1) {
163         return;
164     }
165 
166     char buf[TRACE_MARKER_MESSAGE_LEN] = {0};
167     int len = 0;
168     if (value == NULL) {
169         len = snprintf(buf, TRACE_MARKER_MESSAGE_LEN, "S|%d|%s %d", getpid(), message, taskId);
170     } else {
171         len = snprintf(buf, TRACE_MARKER_MESSAGE_LEN, "S|%d|%s|%s %d", getpid(), message, value, taskId);
172     }
173     if (len > 0 && len < sizeof(buf)) {
174         int ret = MUSL_TEMP_FAILURE_RETRY(write(trace_marker_fd, buf, len));
175         if (ret == -1) {
176             MUSL_LOGW("fail to write S. %d", ret);
177         }
178     } else {
179         MUSL_LOGW("S length error. %d", len);
180     }
181 
182     // close file descriptor of trace_marker
183     close(trace_marker_fd);
184 }
185 
186 /* Write the terminator to the trace_marker node in kernel space,
187 used in a different thread than trace_marker_async_begin(),with the symbol "F". */
trace_marker_async_end(uint64_t label,const char * message,const char * value,int taskId)188 void trace_marker_async_end(uint64_t label, const char *message, const char *value, int taskId)
189 {
190     if (LIKELY((!is_enable_trace(label) || message == NULL))) {
191         return;
192     }
193 
194     int trace_marker_fd = get_trace_marker_fd();
195     if (trace_marker_fd == -1) {
196         return;
197     }
198 
199     char buf[TRACE_MARKER_MESSAGE_LEN] = {0};
200     int len = 0;
201     if (value == NULL) {
202         len = snprintf(buf, TRACE_MARKER_MESSAGE_LEN, "F|%d|%s %d", getpid(), message, taskId);
203     } else {
204         len = snprintf(buf, TRACE_MARKER_MESSAGE_LEN, "F|%d|%s|%s %d", getpid(), message, value, taskId);
205     }
206     if (len > 0 && len < sizeof(buf)) {
207         int ret = MUSL_TEMP_FAILURE_RETRY(write(trace_marker_fd, buf, len));
208         if (ret == -1) {
209             MUSL_LOGW("fail to write F. %d", ret);
210         }
211     } else {
212         MUSL_LOGW("F length error. %d", len);
213     }
214 
215     // close file descriptor of trace_marker
216     close(trace_marker_fd);
217 }
218 
219 // A numeric variable used to mark a pre trace, with the symbol "C".
trace_marker_count(uint64_t label,const char * message,int value)220 void trace_marker_count(uint64_t label, const char *message, int value)
221 {
222     if (LIKELY((!is_enable_trace(label) || message == NULL))) {
223         return;
224     }
225 
226     int trace_marker_fd = get_trace_marker_fd();
227     if (trace_marker_fd == -1) {
228         return;
229     }
230 
231     char buf[TRACE_MARKER_MESSAGE_LEN] = {0};
232     int len = snprintf(buf, TRACE_MARKER_MESSAGE_LEN, "C|%d|%s %d", getpid(), message, value);
233     if (len > 0 && len < sizeof(buf)) {
234         int ret = MUSL_TEMP_FAILURE_RETRY(write(trace_marker_fd, buf, len));
235         if (ret == -1) {
236             MUSL_LOGW("fail to write C. %d", ret);
237         }
238     } else {
239         MUSL_LOGW("C length error. %d", len);
240     }
241 
242     // close file descriptor of trace_marker
243     close(trace_marker_fd);
244 }
245 
246