• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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 <trace/trace_marker.h>
17 
18 #include <errno.h>
19 #include <fcntl.h>
20 #include <stdbool.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <sys/types.h>
25 #include <unistd.h>
26 #include "musl_log.h"
27 
28 #ifndef MUSL_TEMP_FAILURE_RETRY
29 #define MUSL_TEMP_FAILURE_RETRY(exp)            \
30     ({                                     \
31     long int _rc;                          \
32     do {                                   \
33         _rc = (long int)(exp);             \
34     } while ((_rc == -1) && (errno == EINTR)); \
35     _rc;                                   \
36     })
37 #endif
38 
39 // Check whether the user space trace function is enabled
is_enable_trace(void)40 static inline bool is_enable_trace(void)
41 {
42     return true;
43 }
44 
45 // Get the fd of trace_marker
get_trace_marker_fd(void)46 static inline int get_trace_marker_fd(void)
47 {
48     int trace_marker_fd = MUSL_TEMP_FAILURE_RETRY(open("/sys/kernel/tracing/trace_marker", O_CLOEXEC | O_WRONLY | O_APPEND));
49     if (trace_marker_fd == -1) {
50         trace_marker_fd = MUSL_TEMP_FAILURE_RETRY(open("/sys/kernel/debug/tracing/trace_marker", O_CLOEXEC | O_WRONLY | O_APPEND));
51     }
52     return trace_marker_fd;
53 }
54 
55 /* Write the function call information to the trace_marker node in kernel space,
56 used on the same thread as trace_marker_end(),with the symbol "B". */
trace_marker_begin(const char * message,const char * value)57 void trace_marker_begin(const char *message, const char *value)
58 {
59     if (!is_enable_trace() || message == NULL) {
60         return;
61     }
62 
63     int trace_marker_fd = get_trace_marker_fd();
64     if (trace_marker_fd == -1) {
65         return;
66     }
67 
68     char buf[TRACE_MARKER_MESSAGE_LEN] = {0};
69     int len = 0;
70     if (value == NULL) {
71         len = snprintf(buf, TRACE_MARKER_MESSAGE_LEN, "B|%d %s", getpid(), message);
72     } else {
73         len = snprintf(buf, TRACE_MARKER_MESSAGE_LEN, "B|%d|%s %s", getpid(), message, value);
74     }
75     if (len > 0 && len < sizeof(buf)) {
76         int ret = MUSL_TEMP_FAILURE_RETRY(write(trace_marker_fd, buf, len));
77         if (ret == -1) {
78             MUSL_LOGE("fail to write B. %d", ret);
79         }
80     } else {
81         MUSL_LOGE("B length error. %d", len);
82     }
83 
84     // close file descriptor of trace_marker
85     close(trace_marker_fd);
86 }
87 
88 /* Write the terminator to the trace_marker node of the kernel space,
89 used on the same thread as trace_marker_begin(),with the symbol "E". */
trace_marker_end(void)90 void trace_marker_end(void)
91 {
92     if (!is_enable_trace()) {
93         return;
94     }
95 
96     int trace_marker_fd = get_trace_marker_fd();
97     if (trace_marker_fd == -1) {
98         return;
99     }
100 
101     char buf[TRACE_MARKER_MESSAGE_LEN] = {0};
102     int len = snprintf(buf, TRACE_MARKER_MESSAGE_LEN, "E|%d", getpid());
103     if (len > 0 && len < sizeof(buf)) {
104         int ret = MUSL_TEMP_FAILURE_RETRY(write(trace_marker_fd, buf, len));
105         if (ret == -1) {
106             MUSL_LOGE("fail to write E. %d", ret);
107         }
108     } else {
109         MUSL_LOGE("E length error. %d", len);
110     }
111 
112     // close file descriptor of trace_marker
113     close(trace_marker_fd);
114 }
115 
116 /* Write the function call information to the trace_marker node in kernel space,
117 used in a different thread than trace_marker_async_end(),with the symbol "S". */
trace_marker_async_begin(const char * message,const char * value,int taskId)118 void trace_marker_async_begin(const char *message, const char *value, int taskId)
119 {
120     if (!is_enable_trace() || message == NULL) {
121         return;
122     }
123 
124     int trace_marker_fd = get_trace_marker_fd();
125     if (trace_marker_fd == -1) {
126         return;
127     }
128 
129     char buf[TRACE_MARKER_MESSAGE_LEN] = {0};
130     int len = 0;
131     if (value == NULL) {
132         len = snprintf(buf, TRACE_MARKER_MESSAGE_LEN, "S|%d|%s %d", getpid(), message, taskId);
133     } else {
134         len = snprintf(buf, TRACE_MARKER_MESSAGE_LEN, "S|%d|%s|%s %d", getpid(), message, value, taskId);
135     }
136     if (len > 0 && len < sizeof(buf)) {
137         int ret = MUSL_TEMP_FAILURE_RETRY(write(trace_marker_fd, buf, len));
138         if (ret == -1) {
139             MUSL_LOGE("fail to write S. %d", ret);
140         }
141     } else {
142         MUSL_LOGE("S length error. %d", len);
143     }
144 
145     // close file descriptor of trace_marker
146     close(trace_marker_fd);
147 }
148 
149 /* Write the terminator to the trace_marker node in kernel space,
150 used in a different thread than trace_marker_async_begin(),with the symbol "F". */
trace_marker_async_end(const char * message,const char * value,int taskId)151 void trace_marker_async_end(const char *message, const char *value, int taskId)
152 {
153     if (!is_enable_trace() || message == NULL) {
154         return;
155     }
156 
157     int trace_marker_fd = get_trace_marker_fd();
158     if (trace_marker_fd == -1) {
159         return;
160     }
161 
162     char buf[TRACE_MARKER_MESSAGE_LEN] = {0};
163     int len = 0;
164     if (value == NULL) {
165         len = snprintf(buf, TRACE_MARKER_MESSAGE_LEN, "F|%d|%s %d", getpid(), message, taskId);
166     } else {
167         len = snprintf(buf, TRACE_MARKER_MESSAGE_LEN, "F|%d|%s|%s %d", getpid(), message, value, taskId);
168     }
169     if (len > 0 && len < sizeof(buf)) {
170         int ret = MUSL_TEMP_FAILURE_RETRY(write(trace_marker_fd, buf, len));
171         if (ret == -1) {
172             MUSL_LOGE("fail to write F. %d", ret);
173         }
174     } else {
175         MUSL_LOGE("F length error. %d", len);
176     }
177 
178     // close file descriptor of trace_marker
179     close(trace_marker_fd);
180 }
181 
182 // A numeric variable used to mark a pre trace, with the symbol "C".
trace_marker_count(const char * message,int value)183 void trace_marker_count(const char *message, int value)
184 {
185     if (!is_enable_trace() || message == NULL) {
186         return;
187     }
188 
189     int trace_marker_fd = get_trace_marker_fd();
190     if (trace_marker_fd == -1) {
191         return;
192     }
193 
194     char buf[TRACE_MARKER_MESSAGE_LEN] = {0};
195     int len = snprintf(buf, TRACE_MARKER_MESSAGE_LEN, "C|%d|%s %d", getpid(), message, value);
196     if (len > 0 && len < sizeof(buf)) {
197         int ret = MUSL_TEMP_FAILURE_RETRY(write(trace_marker_fd, buf, len));
198         if (ret == -1) {
199             MUSL_LOGE("fail to write C. %d", ret);
200         }
201     } else {
202         MUSL_LOGE("C length error. %d", len);
203     }
204 
205     // close file descriptor of trace_marker
206     close(trace_marker_fd);
207 }
208