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