1 /*
2 * Copyright (c) 2022-2023 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 #ifndef DFX_MUSL_CUTIL_H
16 #define DFX_MUSL_CUTIL_H
17
18 #include <stdbool.h>
19 #include <stddef.h>
20 #include <stdint.h>
21 #include <syscall.h>
22 #include <time.h>
23 #include <unistd.h>
24 #include "dfx_define.h"
25 #include "musl_log.h"
26
27 #ifdef __cplusplus
28 extern "C" {
29 #endif
30
31 #ifdef ENABLE_MUSL_CUTIL
32 static const char PID_STR_NAME[] = "Pid:";
33
ReadStringFromFile(const char * path,char * dst,size_t dstSz)34 static bool ReadStringFromFile(const char* path, char* dst, size_t dstSz)
35 {
36 char name[NAME_BUF_LEN];
37 char nameFilter[NAME_BUF_LEN];
38 memset(name, 0, sizeof(name));
39 memset(nameFilter, 0, sizeof(nameFilter));
40
41 int fd = -1;
42 fd = OHOS_TEMP_FAILURE_RETRY(open(path, O_RDONLY));
43 if (fd < 0) {
44 return false;
45 }
46
47 int nRead = OHOS_TEMP_FAILURE_RETRY(read(fd, name, NAME_BUF_LEN -1));
48 if (nRead == -1) {
49 close(fd);
50 return false;
51 }
52
53 char* p = name;
54 int i = 0;
55 while (*p != '\0') {
56 if ((*p == '\n') || (i == NAME_BUF_LEN)) {
57 break;
58 }
59 nameFilter[i] = *p;
60 p++, i++;
61 }
62 nameFilter[NAME_BUF_LEN - 1] = '\0';
63
64 size_t cpyLen = strlen(nameFilter) + 1;
65 if (cpyLen > dstSz) {
66 cpyLen = dstSz;
67 }
68 memcpy(dst, nameFilter, cpyLen);
69 close(fd);
70 return true;
71 }
72
GetThreadName(char * buffer,size_t bufferSz)73 bool GetThreadName(char* buffer, size_t bufferSz)
74 {
75 return ReadStringFromFile(PROC_SELF_COMM_PATH, buffer, bufferSz);
76 }
77
GetThreadNameByTid(int32_t tid,char * buffer,size_t bufferSz)78 bool GetThreadNameByTid(int32_t tid, char* buffer, size_t bufferSz)
79 {
80 char threadNamePath[NAME_BUF_LEN] = { 0 };
81 if (snprintf(threadNamePath, sizeof(threadNamePath), "/proc/%d/comm", tid) <= 0) {
82 return false;
83 }
84 return ReadStringFromFile(threadNamePath, buffer, bufferSz);
85 }
86
GetProcessName(char * buffer,size_t bufferSz)87 bool GetProcessName(char* buffer, size_t bufferSz)
88 {
89 return ReadStringFromFile(PROC_SELF_CMDLINE_PATH, buffer, bufferSz);
90 }
91
GetRealPid(void)92 pid_t GetRealPid(void)
93 {
94 pid_t pid = syscall(SYS_getpid);
95 int fd = OHOS_TEMP_FAILURE_RETRY(open(PROC_SELF_STATUS_PATH, O_RDONLY));
96 if (fd < 0) {
97 DFXLOG_ERROR("GetRealPid:: open failed! pid:(%ld), errno:(%d).", pid, errno);
98 return pid;
99 }
100
101 char buf[LINE_BUF_SIZE] = {0};
102 int i = 0;
103 char b;
104 ssize_t nRead = 0;
105 while (1) {
106 nRead = OHOS_TEMP_FAILURE_RETRY(read(fd, &b, sizeof(char)));
107 if (nRead <= 0 || b == '\0') {
108 DFXLOG_ERROR("GetRealPid:: read failed! pid:(%ld), errno:(%d), nRead(%zd), readchar(%02X).",
109 pid, errno, nRead, b);
110 break;
111 }
112
113 if (b == '\n' || i == LINE_BUF_SIZE) {
114 if (strncmp(buf, PID_STR_NAME, strlen(PID_STR_NAME)) != 0) {
115 i = 0;
116 (void)memset(buf, '\0', sizeof(buf));
117 continue;
118 }
119 if (sscanf(buf, "%*[^0-9]%d", &pid) < 0) {
120 DFXLOG_ERROR("GetRealPid:: sscanf failed! pid:(%ld), errno:(%d), buf(%s).", pid, errno, buf);
121 }
122 break;
123 }
124 buf[i] = b;
125 i++;
126 }
127 close(fd);
128 return pid;
129 }
130
GetTimeMilliseconds(void)131 uint64_t GetTimeMilliseconds(void)
132 {
133 struct timespec ts;
134 (void)clock_gettime(CLOCK_REALTIME, &ts);
135 return ((uint64_t)ts.tv_sec * NUMBER_ONE_THOUSAND) + // 1000 : second to millisecond convert ratio
136 (((uint64_t)ts.tv_nsec) / NUMBER_ONE_MILLION); // 1000000 : nanosecond to millisecond convert ratio
137 }
138
GetAbsTimeMilliSeconds(void)139 uint64_t GetAbsTimeMilliSeconds(void)
140 {
141 struct timespec ts;
142 (void)clock_gettime(CLOCK_MONOTONIC, &ts);
143 return ((uint64_t)(ts.tv_sec) * NUMBER_ONE_THOUSAND) +
144 ((uint64_t)(ts.tv_nsec) / NUMBER_ONE_MILLION);
145 }
146
ParseSiValue(siginfo_t * si,uint64_t * endTime,int * tid)147 void ParseSiValue(siginfo_t* si, uint64_t* endTime, int* tid)
148 {
149 const int flagOffset = 63;
150 if (((uint64_t)si->si_value.sival_ptr & (1ULL << flagOffset)) != 0) {
151 *endTime = (uint64_t)si->si_value.sival_ptr & (~(1ULL << flagOffset));
152 *tid = 0;
153 } else {
154 *endTime = 0;
155 *tid = si->si_value.sival_int;
156 }
157 }
158
159 #endif
160 #ifdef __cplusplus
161 }
162 #endif
163 #endif