1 /*
2 * Copyright (c) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved.
3 *
4 * UniProton is licensed under Mulan PSL v2.
5 * You can use this software according to the terms and conditions of the Mulan PSL v2.
6 * You may obtain a copy of Mulan PSL v2 at:
7 * http://license.coscl.org.cn/MulanPSL2
8 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
9 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
10 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
11 * See the Mulan PSL v2 for more details.
12 * Create: 2022-11-15
13 * Description: time功能实现
14 */
15 #include "time.h"
16 #include "prt_posix_internal.h"
17 #include "prt_sys_external.h"
18 #include "prt_timer.h"
19 #include "prt_swtmr_external.h"
20
21 #define OS_SYS_NS_PER_MS (OS_SYS_NS_PER_SECOND / OS_SYS_MS_PER_SECOND)
22
23 static struct timespec g_accDeltaFromSet;
24
25 /* 封装超时处理函数 */
OsTimerWrapper(TimerHandle tmrHandle,U32 arg1,U32 arg2,U32 arg3,U32 arg4)26 static void OsTimerWrapper(TimerHandle tmrHandle, U32 arg1, U32 arg2, U32 arg3, U32 arg4)
27 {
28 (void)tmrHandle;
29 (void)arg3;
30 (void)arg4;
31 void *(*sigev_notify_function)(union sigval) = (void *)arg1;
32
33 union sigval val = {
34 .sival_int = arg2
35 };
36
37 sigev_notify_function(val);
38 }
39
timer_create(clockid_t clockId,struct sigevent * restrict evp,timer_t * restrict timerId)40 int timer_create(clockid_t clockId, struct sigevent * restrict evp, timer_t * restrict timerId)
41 {
42 U32 ret;
43 TimerHandle swtmrId;
44 struct TimerCreatePara timer = {0};
45
46 if ((timerId == NULL) || (evp == NULL) || (clockId != CLOCK_REALTIME)) {
47 errno = EINVAL;
48 return PTHREAD_OP_FAIL;
49 }
50
51 if (evp->sigev_notify != SIGEV_THREAD) { // 必须有超时处理函数
52 errno = EINVAL;
53 return PTHREAD_OP_FAIL;
54 }
55
56 timer.type = OS_TIMER_SOFTWARE;
57 timer.mode = OS_TIMER_LOOP;
58 timer.interval = 1;
59 timer.timerGroupId = 0;
60 timer.callBackFunc = OsTimerWrapper;
61 timer.arg1 = (U32)evp->sigev_notify_function;
62 timer.arg2 = (U32)evp->sigev_value.sival_int;
63 ret = PRT_TimerCreate(&timer, &swtmrId);
64 if (ret != OS_OK) {
65 errno = EINVAL;
66 return PTHREAD_OP_FAIL;
67 }
68
69 *timerId = (timer_t)swtmrId;
70 return OS_OK;
71 }
72
timer_delete(timer_t timerId)73 int timer_delete(timer_t timerId)
74 {
75 U32 swtmrId = (U32)timerId;
76
77 if (PRT_TimerDelete(0, swtmrId) != OS_OK) {
78 errno = EINVAL;
79 return PTHREAD_OP_FAIL;
80 }
81
82 return OS_OK;
83 }
84
OsTimeGetHwTime(struct timespec * hwTime)85 void OsTimeGetHwTime(struct timespec *hwTime)
86 {
87 U64 cycle = OsCurCycleGet64();
88 U64 nowNsec = (cycle / g_systemClock) * OS_SYS_NS_PER_SECOND +
89 (cycle % g_systemClock) * OS_SYS_NS_PER_SECOND / g_systemClock;
90
91 hwTime->tv_sec = nowNsec / OS_SYS_NS_PER_SECOND;
92 hwTime->tv_nsec = nowNsec % OS_SYS_NS_PER_SECOND;
93 }
94
OsTimeSetRealTime(const struct timespec * realTime)95 void OsTimeSetRealTime(const struct timespec *realTime)
96 {
97 U32 intSave;
98 struct timespec hwTime = {0};
99
100 OsTimeGetHwTime(&hwTime);
101 intSave = PRT_HwiLock();
102 g_accDeltaFromSet.tv_nsec = realTime->tv_nsec - hwTime.tv_nsec;
103 g_accDeltaFromSet.tv_sec = (realTime->tv_sec - hwTime.tv_sec) - (time_t)(g_accDeltaFromSet.tv_nsec < 0);
104 g_accDeltaFromSet.tv_nsec = (g_accDeltaFromSet.tv_nsec + OS_SYS_NS_PER_SECOND) % OS_SYS_NS_PER_SECOND;
105 PRT_HwiRestore(intSave);
106 }
107
OsTimeGetRealTime(struct timespec * realTime)108 void OsTimeGetRealTime(struct timespec *realTime)
109 {
110 U32 intSave;
111 struct timespec hwTime = {0};
112
113 OsTimeGetHwTime(&hwTime);
114
115 intSave = PRT_HwiLock();
116 realTime->tv_nsec = hwTime.tv_nsec + g_accDeltaFromSet.tv_nsec;
117 realTime->tv_sec = hwTime.tv_sec + g_accDeltaFromSet.tv_sec + (time_t)(realTime->tv_nsec >= OS_SYS_NS_PER_SECOND);
118 realTime->tv_nsec %= OS_SYS_NS_PER_SECOND;
119 PRT_HwiRestore(intSave);
120 }
121
OsTimeCheckSpec(const struct timespec * tp)122 bool OsTimeCheckSpec(const struct timespec *tp)
123 {
124 if (tp == NULL) {
125 return FALSE;
126 }
127
128 if ((tp->tv_sec < 0) || (tp->tv_nsec < 0) || (tp->tv_nsec >= OS_SYS_NS_PER_SECOND)) {
129 return FALSE;
130 }
131
132 return TRUE;
133 }
134
OsTimeMs2Spec(U32 expireTime,struct timespec * tp)135 void OsTimeMs2Spec(U32 expireTime, struct timespec *tp)
136 {
137 U32 remainder;
138
139 tp->tv_sec = expireTime / OS_SYS_MS_PER_SECOND;
140 remainder = expireTime - (U32)tp->tv_sec * OS_SYS_MS_PER_SECOND;
141 tp->tv_nsec = (long)remainder * OS_SYS_NS_PER_MS;
142 }
143
OsTimeSpec2Ms(const struct timespec * tp,U32 * expireTime)144 void OsTimeSpec2Ms(const struct timespec *tp, U32 *expireTime)
145 {
146 U32 tickCnt;
147
148 tickCnt = OsTimeSpec2Tick(tp);
149
150 *expireTime = (tickCnt / g_tickModInfo.tickPerSecond) * OS_SYS_MS_PER_SECOND;
151 }
152
OsTimeSpec2Tick(const struct timespec * tp)153 U32 OsTimeSpec2Tick(const struct timespec *tp)
154 {
155 U64 ns;
156 U64 tmp;
157 U64 tickCnt;
158 U32 nsPerTick;
159
160 nsPerTick = OS_SYS_NS_PER_SECOND / OsSysGetTickPerSecond(); // 每个tick多少纳秒
161 ns = (U64)tp->tv_sec * OS_SYS_NS_PER_SECOND + (U64)tp->tv_nsec;
162 tickCnt = ns / nsPerTick;
163 tmp = ns - tickCnt * nsPerTick;
164 if (tmp > 0) {
165 tickCnt++;
166 }
167
168 if (tickCnt > U32_MAX) {
169 tickCnt = U32_MAX;
170 }
171
172 return (U32)tickCnt;
173 }
174
OsTimeOut2Ticks(const struct timespec * time,U32 * ticks)175 U32 OsTimeOut2Ticks(const struct timespec *time, U32 *ticks)
176 {
177 struct timespec curTime;
178 S64 timeOutNs;
179 U64 timeOut;
180
181 if ((time->tv_nsec < 0) || (time->tv_nsec >= OS_SYS_NS_PER_SECOND) ||
182 (time->tv_sec < 0) || (time->tv_sec > S32_MAX)) {
183 return EINVAL;
184 }
185
186 OsTimeGetRealTime(&curTime);
187
188 timeOutNs = (time->tv_sec - curTime.tv_sec) * OS_SYS_NS_PER_SECOND + (time->tv_nsec - curTime.tv_nsec);
189 if (timeOutNs <= 0) {
190 return ETIMEDOUT;
191 }
192
193 timeOut = (U64)(time->tv_sec - curTime.tv_sec) * OsSysGetTickPerSecond();
194 if (time->tv_nsec > curTime.tv_nsec) {
195 timeOut += ((U64)(time->tv_nsec - curTime.tv_nsec) * OsSysGetTickPerSecond() - 1) / OS_SYS_NS_PER_SECOND + 1;
196 } else {
197 timeOut -= ((U64)(curTime.tv_nsec - time->tv_nsec) * OsSysGetTickPerSecond()) / OS_SYS_NS_PER_SECOND;
198 }
199 // 因为tick误差在ms级,为了确保延时时间满足要求,向上加一
200 timeOut = timeOut + 1;
201 *ticks = timeOut >= OS_WAIT_FOREVER ? OS_WAIT_FOREVER : (U32)timeOut;
202
203 return OS_OK;
204 }
205
timer_gettime(timer_t timerId,struct itimerspec * value)206 int timer_gettime(timer_t timerId, struct itimerspec *value)
207 {
208 U32 ret;
209 U32 expireTime; // 剩余超时时间,单位ms
210 struct SwTmrInfo info;
211
212 if (value == NULL) {
213 errno = EINVAL;
214 return PTHREAD_OP_FAIL;
215 }
216
217 ret = PRT_TimerQuery(0, (TimerHandle)timerId, &expireTime);
218 if (ret != OS_OK) {
219 errno = EINVAL;
220 return PTHREAD_OP_FAIL;
221 }
222
223 ret = PRT_SwTmrInfoGet((TimerHandle)timerId, &info);
224 if (ret != OS_OK) {
225 errno = EINVAL;
226 return PTHREAD_OP_FAIL;
227 }
228
229 OsTimeMs2Spec(expireTime, &value->it_value);
230 OsTimeMs2Spec((info.mode == OS_TIMER_ONCE) ? 0 : info.interval, &value->it_interval);
231
232 return OS_OK;
233 }
234
timer_settime(timer_t timerId,int flags,const struct itimerspec * value,struct itimerspec * ovalue)235 int timer_settime(timer_t timerId, int flags, const struct itimerspec *value, struct itimerspec *ovalue)
236 {
237 U32 intSave;
238 U32 interval, expiry, ret;
239 struct TagSwTmrCtrl *swtmr;
240 (void)flags;
241
242 if (value == NULL) {
243 errno = EINVAL;
244 return PTHREAD_OP_FAIL;
245 }
246
247 if (!OsTimeCheckSpec(&value->it_value) || !OsTimeCheckSpec(&value->it_interval)) {
248 errno = EINVAL;
249 return PTHREAD_OP_FAIL;
250 }
251
252 expiry = OsTimeSpec2Tick(&value->it_value);
253 interval = OsTimeSpec2Tick(&value->it_interval);
254
255 if (interval != 0 && interval != expiry) {
256 errno = ENOTSUP;
257 return PTHREAD_OP_FAIL;
258 }
259
260 if (ovalue) {
261 if (timer_gettime(timerId, ovalue) != OS_OK) {
262 errno = EINVAL;
263 return PTHREAD_OP_FAIL;
264 }
265 }
266
267 ret = PRT_TimerStop(0, timerId);
268 if (ret != OS_OK && ret != OS_ERRNO_SWTMR_UNSTART) {
269 errno = EINVAL;
270 return PTHREAD_OP_FAIL;
271 }
272
273 // 当 it_value = 0, 表示要停止定时器.
274 if ((value->it_value.tv_sec == 0) && (value->it_value.tv_nsec == 0)) {
275 return OS_OK;
276 }
277
278 intSave = PRT_HwiLock();
279 swtmr = g_swtmrCbArray + OS_SWTMR_ID_2_INDEX(timerId);
280 swtmr->mode = (interval ? OS_TIMER_LOOP : OS_TIMER_ONCE);
281 swtmr->interval = (interval ? interval : expiry);
282 swtmr->idxRollNum = swtmr->interval;
283 PRT_HwiRestore(intSave);
284
285 if (PRT_TimerStart(0, timerId) != OS_OK) {
286 errno = EINVAL;
287 return PTHREAD_OP_FAIL;
288 }
289
290 return OS_OK;
291 }
292
nanosleep(const struct timespec * rqtp,struct timespec * rmtp)293 int nanosleep(const struct timespec *rqtp, struct timespec *rmtp)
294 {
295 U64 nanosec;
296 U64 tick;
297 const U32 nsPerTick = OS_SYS_NS_PER_SECOND / g_tickModInfo.tickPerSecond;
298
299 if (!OsTimeCheckSpec(rqtp)) {
300 errno = EINVAL;
301 return PTHREAD_OP_FAIL;
302 }
303
304 nanosec = (U64)rqtp->tv_sec * OS_SYS_NS_PER_SECOND + (U64)rqtp->tv_nsec;
305 tick = (nanosec + nsPerTick - 1) / nsPerTick; // 睡眠时间不得小于rqtp规定的时间
306
307 if (tick >= U32_MAX) {
308 errno = EINVAL;
309 return PTHREAD_OP_FAIL;
310 }
311
312 if (PRT_TaskDelay((U32)tick) == OS_OK) {
313 if (rmtp != NULL) {
314 rmtp->tv_sec = rmtp->tv_nsec = 0;
315 }
316 return OS_OK;
317 }
318
319 return PTHREAD_OP_FAIL;
320 }
321
sleep(U32 seconds)322 U32 sleep(U32 seconds)
323 {
324 U32 ret;
325 U32 ticks;
326
327 ticks = seconds * g_tickModInfo.tickPerSecond;
328 ret = PRT_TaskDelay(ticks ? (ticks + 1) : 0);
329 if (ret != OS_OK) {
330 return EINTR;
331 }
332
333 return OS_OK;
334 }
335
clock_getres(clockid_t clockId,struct timespec * tp)336 int clock_getres(clockid_t clockId, struct timespec *tp)
337 {
338 if (tp == NULL) {
339 errno = EINVAL;
340 return PTHREAD_OP_FAIL;
341 }
342
343 switch (clockId) {
344 case CLOCK_MONOTONIC_RAW:
345 case CLOCK_MONOTONIC:
346 case CLOCK_REALTIME:
347 case CLOCK_MONOTONIC_COARSE:
348 case CLOCK_REALTIME_COARSE:
349 tp->tv_nsec = (long)((OS_SYS_NS_PER_SECOND - 1) / g_systemClock + 1); // 每个cycle多少ns
350 tp->tv_sec = 0;
351 return OS_OK;
352 case CLOCK_PROCESS_CPUTIME_ID:
353 case CLOCK_BOOTTIME:
354 case CLOCK_REALTIME_ALARM:
355 case CLOCK_BOOTTIME_ALARM:
356 errno = ENOTSUP;
357 return PTHREAD_OP_FAIL;
358 default:
359 errno = EINVAL;
360 return PTHREAD_OP_FAIL;
361 }
362 }
363
clock_settime(clockid_t clockId,const struct timespec * tp)364 int clock_settime(clockid_t clockId, const struct timespec *tp)
365 {
366 if (!OsTimeCheckSpec(tp)) {
367 errno = EINVAL;
368 return PTHREAD_OP_FAIL;
369 }
370
371 switch (clockId) {
372 case CLOCK_REALTIME:
373 OsTimeSetRealTime(tp);
374 return OS_OK;
375 case CLOCK_MONOTONIC_COARSE:
376 case CLOCK_REALTIME_COARSE:
377 case CLOCK_MONOTONIC_RAW:
378 case CLOCK_BOOTTIME:
379 case CLOCK_REALTIME_ALARM:
380 case CLOCK_BOOTTIME_ALARM:
381 errno = ENOTSUP;
382 return PTHREAD_OP_FAIL;
383 case CLOCK_MONOTONIC:
384 default:
385 errno = EINVAL;
386 return PTHREAD_OP_FAIL;
387 }
388 }
389
clock_gettime(clockid_t clockId,struct timespec * tp)390 int clock_gettime(clockid_t clockId, struct timespec *tp)
391 {
392 if (tp == NULL) {
393 errno = EINVAL;
394 return PTHREAD_OP_FAIL;
395 }
396
397 switch (clockId) {
398 case CLOCK_MONOTONIC_RAW:
399 case CLOCK_MONOTONIC:
400 case CLOCK_MONOTONIC_COARSE:
401 OsTimeGetHwTime(tp);
402 return OS_OK;
403 case CLOCK_REALTIME:
404 case CLOCK_REALTIME_COARSE:
405 OsTimeGetRealTime(tp);
406 return OS_OK;
407 case CLOCK_BOOTTIME:
408 case CLOCK_REALTIME_ALARM:
409 case CLOCK_BOOTTIME_ALARM:
410 errno = ENOTSUP;
411 return PTHREAD_OP_FAIL;
412 default:
413 errno = EINVAL;
414 return PTHREAD_OP_FAIL;
415 }
416 }
417