1 /*
2 * Copyright (c) 2021-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
16 #include "softbus_adapter_timer.h"
17
18 #include <errno.h>
19 #include <signal.h>
20 #include <sys/stat.h>
21 #include <sys/time.h>
22 #include <time.h>
23 #include <unistd.h>
24
25 #include "comm_log.h"
26 #include "securec.h"
27 #include "softbus_def.h"
28 #include "softbus_errcode.h"
29
30 #define MS_PER_SECOND 1000
31 #define US_PER_MSECOND 1000
32 #define NS_PER_USECOND 1000
33 #define DATE_TIME_BUFF_LEN 24 // yyyy-MM-dd HH:mm:ss.SSS
34
35 static unsigned int g_timerType;
36 __attribute__((no_sanitize("hwaddress"))) static TimerFunc g_timerFunc = NULL;
37 static _Thread_local char g_dateTimeBuff[DATE_TIME_BUFF_LEN] = {0};
38
HandleTimeoutAdapterFun(union sigval para)39 __attribute__((no_sanitize("hwaddress"))) static void HandleTimeoutAdapterFun(union sigval para)
40 {
41 (void)para;
42 if (g_timerFunc != NULL) {
43 g_timerFunc();
44 }
45 }
46
SetTimerFunc(TimerFunc func)47 __attribute__((no_sanitize("hwaddress"))) void SetTimerFunc(TimerFunc func)
48 {
49 g_timerFunc = func;
50 }
51
SoftBusCreateTimer(void ** timerId,unsigned int type)52 void *SoftBusCreateTimer(void **timerId, unsigned int type)
53 {
54 if (timerId == NULL) {
55 COMM_LOGE(COMM_ADAPTER, "timerId is null");
56 return NULL;
57 }
58 struct sigevent envent;
59 (void)memset_s(&envent, sizeof(envent), 0, sizeof(envent));
60 envent.sigev_notify = SIGEV_THREAD;
61 envent.sigev_notify_function = HandleTimeoutAdapterFun;
62 envent.sigev_notify_attributes = NULL;
63
64 g_timerType = type;
65 if (timer_create(CLOCK_REALTIME, &envent, timerId) != 0) {
66 COMM_LOGE(COMM_ADAPTER, "timer create error, errnoCode=%{public}d", errno);
67 return NULL;
68 }
69
70 return *timerId;
71 }
72
SoftBusStartTimer(void * timerId,unsigned int tickets)73 int SoftBusStartTimer(void *timerId, unsigned int tickets)
74 {
75 if (timerId == NULL) {
76 COMM_LOGE(COMM_ADAPTER, "timerId is null");
77 return SOFTBUS_ERR;
78 }
79 struct itimerspec value;
80 (void)memset_s(&value, sizeof(value), 0, sizeof(value));
81 value.it_value.tv_sec = tickets / MS_PER_SECOND;
82 value.it_value.tv_nsec = 0;
83 if (g_timerType == TIMER_TYPE_ONCE) {
84 value.it_interval.tv_sec = 0;
85 value.it_interval.tv_nsec = 0;
86 } else {
87 value.it_interval.tv_sec = tickets / MS_PER_SECOND;
88 value.it_interval.tv_nsec = 0;
89 }
90
91 if (timer_settime(timerId, 0, &value, NULL) != 0) {
92 COMM_LOGE(COMM_ADAPTER, "timer start error, errnoCode=%{public}d", errno);
93 return SOFTBUS_ERR;
94 }
95
96 return SOFTBUS_OK;
97 }
98
SoftBusDeleteTimer(void * timerId)99 int SoftBusDeleteTimer(void *timerId)
100 {
101 if (timerId == NULL) {
102 COMM_LOGE(COMM_ADAPTER, "timerId is null");
103 return SOFTBUS_ERR;
104 }
105
106 if (timer_delete(timerId) != 0) {
107 COMM_LOGE(COMM_ADAPTER, "timer delete err, errnoCode=%{public}d", errno);
108 return SOFTBUS_ERR;
109 }
110
111 return SOFTBUS_OK;
112 }
113
SoftBusSleepMs(unsigned int ms)114 int SoftBusSleepMs(unsigned int ms)
115 {
116 int ret;
117 struct timeval tm;
118 tm.tv_sec = ms / MS_PER_SECOND;
119 tm.tv_usec = (ms % MS_PER_SECOND) * US_PER_MSECOND;
120
121 do {
122 ret = select(0, NULL, NULL, NULL, &tm);
123 } while ((ret == -1) && (errno == EINTR));
124
125 return SOFTBUS_ERR;
126 }
127
SoftBusGetTime(SoftBusSysTime * sysTime)128 int32_t SoftBusGetTime(SoftBusSysTime *sysTime)
129 {
130 if (sysTime == NULL) {
131 COMM_LOGI(COMM_ADAPTER, "sysTime is null");
132 return SOFTBUS_INVALID_PARAM;
133 }
134 struct timespec time = {0};
135 (void)clock_gettime(CLOCK_MONOTONIC, &time);
136
137 sysTime->sec = time.tv_sec;
138 sysTime->usec = time.tv_nsec / NS_PER_USECOND;
139 return SOFTBUS_OK;
140 }
141
SoftBusGetRealTime(SoftBusSysTime * sysTime)142 int32_t SoftBusGetRealTime(SoftBusSysTime *sysTime)
143 {
144 if (sysTime == NULL) {
145 COMM_LOGW(COMM_ADAPTER, "sysTime is null");
146 return SOFTBUS_INVALID_PARAM;
147 }
148 struct timespec time = {0};
149 (void)clock_gettime(CLOCK_BOOTTIME, &time);
150 sysTime->sec = time.tv_sec;
151 sysTime->usec = time.tv_nsec / NS_PER_USECOND;
152 return SOFTBUS_OK;
153 }
154
SoftBusGetSysTimeMs(void)155 uint64_t SoftBusGetSysTimeMs(void)
156 {
157 struct timeval time;
158 time.tv_sec = 0;
159 time.tv_usec = 0;
160 if (gettimeofday(&time, NULL) != 0) {
161 COMM_LOGI(COMM_ADAPTER, "get sys time fail");
162 return 0;
163 }
164 return (uint64_t)time.tv_sec * MS_PER_SECOND + (uint64_t)time.tv_usec / US_PER_MSECOND;
165 }
166
SoftBusFormatTimestamp(uint64_t timestamp)167 const char *SoftBusFormatTimestamp(uint64_t timestamp)
168 {
169 uint32_t milliseconds = timestamp % MS_PER_SECOND;
170 time_t seconds = (time_t)(timestamp / MS_PER_SECOND);
171 struct tm formatedDateTime;
172
173 #if (defined( __WINDOWS__ ))
174 if (localtime_s(&formatedDateTime, &seconds) != 0) {
175 #else
176 if (localtime_r(&seconds, &formatedDateTime) == NULL) {
177 #endif // __WINDOWS__
178 COMM_LOGE(COMM_ADAPTER, "get localtime failed");
179 return NULL;
180 }
181
182 const int32_t BASE_YEAR = 1900;
183 const int32_t BASE_MONTH = 1;
184 int32_t ret = sprintf_s(g_dateTimeBuff, DATE_TIME_BUFF_LEN, "%04d-%02d-%02d %02d:%02d:%02d.%03u",
185 formatedDateTime.tm_year + BASE_YEAR, formatedDateTime.tm_mon + BASE_MONTH, formatedDateTime.tm_mday,
186 formatedDateTime.tm_hour, formatedDateTime.tm_min, formatedDateTime.tm_sec, milliseconds);
187 if (ret < 0) {
188 COMM_LOGE(COMM_ADAPTER, "sprintf failed");
189 return NULL;
190 }
191
192 g_dateTimeBuff[DATE_TIME_BUFF_LEN - 1] = '\0';
193 return g_dateTimeBuff;
194 }
195