• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #ifdef SOFTBUS_STANDARD_OS
26 #include "ffrt.h"
27 #endif
28 
29 #include "comm_log.h"
30 #include "securec.h"
31 #include "softbus_def.h"
32 #include "softbus_error_code.h"
33 
34 #define MS_PER_SECOND 1000
35 #define US_PER_MSECOND 1000
36 #define NS_PER_USECOND 1000
37 #define DATE_TIME_BUFF_LEN 24 // yyyy-MM-dd HH:mm:ss.SSS
38 
39 static unsigned int g_timerType;
40 __attribute__((no_sanitize("hwaddress"))) static TimerFunc g_timerFunc = NULL;
41 static _Thread_local char g_dateTimeBuff[DATE_TIME_BUFF_LEN] = {0};
42 
HandleTimeoutAdapterFun(union sigval para)43 __attribute__((no_sanitize("hwaddress"))) static void HandleTimeoutAdapterFun(union sigval para)
44 {
45     (void)para;
46     if (g_timerFunc != NULL) {
47         g_timerFunc();
48     }
49 }
50 
SetTimerFunc(TimerFunc func)51 __attribute__((no_sanitize("hwaddress"))) void SetTimerFunc(TimerFunc func)
52 {
53     g_timerFunc = func;
54 }
55 
56 #ifdef SOFTBUS_STANDARD_OS
HandleTimeoutFunWithFfrt(void * data)57 static void HandleTimeoutFunWithFfrt(void *data)
58 {
59     (void)data;
60     if (g_timerFunc != NULL) {
61         g_timerFunc();
62     }
63 }
64 
SoftBusStartTimerWithFfrt(int32_t * timerHandle,uint64_t timeout,bool repeat)65 int32_t SoftBusStartTimerWithFfrt(int32_t *timerHandle, uint64_t timeout, bool repeat)
66 {
67     if (timerHandle == NULL) {
68         COMM_LOGE(COMM_ADAPTER, "timerHandle is null");
69         return SOFTBUS_INVALID_PARAM;
70     }
71     int32_t ret = ffrt_timer_start(ffrt_qos_default, timeout, NULL, HandleTimeoutFunWithFfrt, repeat);
72     if (ret == ffrt_error) {
73         COMM_LOGE(COMM_ADAPTER, "timer start with ffrt fail, ret=%{public}d", ret);
74         return SOFTBUS_TIMER_ERR;
75     }
76     *timerHandle = ret;
77     COMM_LOGI(COMM_ADAPTER, "timer start with ffrt succ, timerHandle=%{public}d", *timerHandle);
78     return SOFTBUS_OK;
79 }
80 
SoftBusStopTimerWithFfrt(int32_t timerHandle)81 void SoftBusStopTimerWithFfrt(int32_t timerHandle)
82 {
83     if (timerHandle < 0) {
84         COMM_LOGE(COMM_ADAPTER, "invalid timerHandle=%{public}d", timerHandle);
85         return;
86     }
87     int32_t ret = ffrt_timer_stop(ffrt_qos_default, timerHandle);
88     if (ret != ffrt_success) {
89         COMM_LOGE(COMM_ADAPTER, "timer stop with ffrt fail, timerHandle=%{public}d, ret=%{public}d", timerHandle, ret);
90         return;
91     }
92     COMM_LOGI(COMM_ADAPTER, "timer stop with ffrt succ, timerHandle=%{public}d", timerHandle);
93 }
94 #endif
95 
SoftBusCreateTimer(void ** timerId,unsigned int type)96 void *SoftBusCreateTimer(void **timerId, unsigned int type)
97 {
98     if (timerId == NULL) {
99         COMM_LOGE(COMM_ADAPTER, "timerId is null");
100         return NULL;
101     }
102     struct sigevent envent;
103     (void)memset_s(&envent, sizeof(envent), 0, sizeof(envent));
104     envent.sigev_notify = SIGEV_THREAD;
105     envent.sigev_notify_function = HandleTimeoutAdapterFun;
106     envent.sigev_notify_attributes = NULL;
107 
108     g_timerType = type;
109     if (timer_create(CLOCK_REALTIME, &envent, timerId) != 0) {
110         COMM_LOGE(COMM_ADAPTER, "timer create error, errnoCode=%{public}d", errno);
111         return NULL;
112     }
113 
114     return *timerId;
115 }
116 
SoftBusStartTimer(void * timerId,unsigned int tickets)117 int SoftBusStartTimer(void *timerId, unsigned int tickets)
118 {
119     if (timerId == NULL) {
120         COMM_LOGE(COMM_ADAPTER, "timerId is null");
121         return SOFTBUS_ERR;
122     }
123     struct itimerspec value;
124     (void)memset_s(&value, sizeof(value), 0, sizeof(value));
125     value.it_value.tv_sec = tickets / MS_PER_SECOND;
126     value.it_value.tv_nsec = 0;
127     if (g_timerType == TIMER_TYPE_ONCE) {
128         value.it_interval.tv_sec = 0;
129         value.it_interval.tv_nsec = 0;
130     } else {
131         value.it_interval.tv_sec = tickets / MS_PER_SECOND;
132         value.it_interval.tv_nsec = 0;
133     }
134 
135     if (timer_settime(timerId, 0, &value, NULL) != 0) {
136         COMM_LOGE(COMM_ADAPTER, "timer start error, errnoCode=%{public}d", errno);
137         return SOFTBUS_ERR;
138     }
139 
140     return SOFTBUS_OK;
141 }
142 
SoftBusDeleteTimer(void * timerId)143 int SoftBusDeleteTimer(void *timerId)
144 {
145     if (timerId == NULL) {
146         COMM_LOGE(COMM_ADAPTER, "timerId is null");
147         return SOFTBUS_ERR;
148     }
149 
150     if (timer_delete(timerId) != 0) {
151         COMM_LOGE(COMM_ADAPTER, "timer delete err, errnoCode=%{public}d", errno);
152         return SOFTBUS_ERR;
153     }
154 
155     return SOFTBUS_OK;
156 }
157 
SoftBusSleepMs(unsigned int ms)158 int SoftBusSleepMs(unsigned int ms)
159 {
160     int ret;
161     struct timeval tm;
162     tm.tv_sec = ms / MS_PER_SECOND;
163     tm.tv_usec = (ms % MS_PER_SECOND) * US_PER_MSECOND;
164 
165     do {
166         ret = select(0, NULL, NULL, NULL, &tm);
167     } while ((ret == -1) && (errno == EINTR));
168 
169     return SOFTBUS_ERR;
170 }
171 
SoftBusGetTime(SoftBusSysTime * sysTime)172 int32_t SoftBusGetTime(SoftBusSysTime *sysTime)
173 {
174     if (sysTime == NULL) {
175         COMM_LOGI(COMM_ADAPTER, "sysTime is null");
176         return SOFTBUS_INVALID_PARAM;
177     }
178     struct timespec time = {0};
179     (void)clock_gettime(CLOCK_MONOTONIC, &time);
180 
181     sysTime->sec = time.tv_sec;
182     sysTime->usec = time.tv_nsec / NS_PER_USECOND;
183     return SOFTBUS_OK;
184 }
185 
SoftBusGetRealTime(SoftBusSysTime * sysTime)186 int32_t SoftBusGetRealTime(SoftBusSysTime *sysTime)
187 {
188     if (sysTime == NULL) {
189         COMM_LOGW(COMM_ADAPTER, "sysTime is null");
190         return SOFTBUS_INVALID_PARAM;
191     }
192     struct timespec time = {0};
193     (void)clock_gettime(CLOCK_BOOTTIME, &time);
194     sysTime->sec = time.tv_sec;
195     sysTime->usec = time.tv_nsec / NS_PER_USECOND;
196     return SOFTBUS_OK;
197 }
198 
SoftBusGetSysTimeMs(void)199 uint64_t SoftBusGetSysTimeMs(void)
200 {
201     struct timeval time;
202     time.tv_sec = 0;
203     time.tv_usec = 0;
204     if (gettimeofday(&time, NULL) != 0) {
205         COMM_LOGI(COMM_ADAPTER, "get sys time fail");
206         return 0;
207     }
208     return (uint64_t)time.tv_sec * MS_PER_SECOND + (uint64_t)time.tv_usec / US_PER_MSECOND;
209 }
210 
SoftBusFormatTimestamp(uint64_t timestamp)211 const char *SoftBusFormatTimestamp(uint64_t timestamp)
212 {
213     uint32_t milliseconds = timestamp % MS_PER_SECOND;
214     time_t seconds = (time_t)(timestamp / MS_PER_SECOND);
215     struct tm formatedDateTime;
216 
217 #if (defined( __WINDOWS__ ))
218     if (localtime_s(&formatedDateTime, &seconds) != 0) {
219 #else
220     if (localtime_r(&seconds, &formatedDateTime) == NULL) {
221 #endif // __WINDOWS__
222         COMM_LOGE(COMM_ADAPTER, "get localtime failed");
223         return NULL;
224     }
225 
226     const int32_t BASE_YEAR = 1900;
227     const int32_t BASE_MONTH = 1;
228     int32_t ret = sprintf_s(g_dateTimeBuff, DATE_TIME_BUFF_LEN, "%04d-%02d-%02d %02d:%02d:%02d.%03u",
229         formatedDateTime.tm_year + BASE_YEAR, formatedDateTime.tm_mon + BASE_MONTH, formatedDateTime.tm_mday,
230         formatedDateTime.tm_hour, formatedDateTime.tm_min, formatedDateTime.tm_sec, milliseconds);
231     if (ret < 0) {
232         COMM_LOGE(COMM_ADAPTER, "sprintf failed, ret=%{public}d", ret);
233         return NULL;
234     }
235 
236     g_dateTimeBuff[DATE_TIME_BUFF_LEN - 1] = '\0';
237     return g_dateTimeBuff;
238 }
239