1 /*
2 * Copyright (c) 2022-2022 Huawei Device Co., Ltd. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without modification,
5 * are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright notice, this list of
8 * conditions and the following disclaimer.
9 *
10 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
11 * of conditions and the following disclaimer in the documentation and/or other materials
12 * provided with the distribution.
13 *
14 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
15 * to endorse or promote products derived from this software without specific prior written
16 * permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
20 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
22 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #define _GNU_SOURCE
32 #include <time.h>
33 #include <sys/time.h>
34 #include <stdint.h>
35 #include <errno.h>
36 #include <signal.h>
37 #include <unistd.h>
38 #include "time_internal.h"
39 #include "los_debug.h"
40 #include "los_task.h"
41 #include "los_swtmr.h"
42 #include "los_tick.h"
43 #include "los_context.h"
44 #include "los_interrupt.h"
45 #include "sys/times.h"
46 #include "rtc_time_hook.h"
47
48 #define DELAYTIMER_MAX 0x7FFFFFFFF
49
50 /* accumulative time delta from discontinuous modify */
51 STATIC struct timespec g_accDeltaFromSet;
52
53 #ifndef __USE_NEWLIB__
54 STATIC const UINT16 g_daysInMonth[2][13] = {
55 /* Normal years. */
56 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
57 /* Leap years. */
58 { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
59 };
60
61 STATIC const UINT8 g_montbl[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
62 #endif
63
64 #ifndef __USE_NEWLIB__
65 #define g_timezone timezone
66 #else
67 #define g_Timezone _timezone
68 #endif
69
70 /*
71 * Time zone information, stored in seconds,
72 * negative values indicate the east of UTC,
73 * positive values indicate the west of UTC.
74 */
75 long g_timezone = -8 * 60 * 60; // set default to CST(UTC+8)
76
77 /*
78 * store register rtc func
79 */
80 STATIC struct RtcTimeHook g_rtcTimeFunc;
81
82 STATIC UINT64 g_rtcTimeBase = 0;
83 STATIC UINT64 g_systickBase = 0;
84
LOS_RtcHookRegister(struct RtcTimeHook * cfg)85 VOID LOS_RtcHookRegister(struct RtcTimeHook *cfg)
86 {
87 if (cfg == NULL) {
88 return;
89 }
90 g_rtcTimeFunc.RtcGetTickHook = cfg->RtcGetTickHook;
91 g_rtcTimeFunc.RtcGetTimeHook = cfg->RtcGetTimeHook;
92 g_rtcTimeFunc.RtcSetTimeHook = cfg->RtcSetTimeHook;
93 g_rtcTimeFunc.RtcGetTimezoneHook = cfg->RtcGetTimezoneHook;
94 g_rtcTimeFunc.RtcSetTimezoneHook = cfg->RtcSetTimezoneHook;
95 }
96
nanosleep(const struct timespec * rqtp,struct timespec * rmtp)97 int nanosleep(const struct timespec *rqtp, struct timespec *rmtp)
98 {
99 UINT64 nseconds;
100 UINT64 tick;
101 UINT32 ret;
102 const UINT32 nsPerTick = OS_SYS_NS_PER_SECOND / LOSCFG_BASE_CORE_TICK_PER_SECOND;
103
104 if (!ValidTimeSpec(rqtp)) {
105 errno = EINVAL;
106 return -1;
107 }
108
109 nseconds = (UINT64)rqtp->tv_sec * OS_SYS_NS_PER_SECOND + rqtp->tv_nsec;
110
111 tick = (nseconds + nsPerTick - 1) / nsPerTick; // Round up for ticks
112
113 if (tick >= UINT32_MAX) {
114 errno = EINVAL;
115 return -1;
116 }
117
118 /* PS: skip the first tick because it is NOT a full tick. */
119 ret = LOS_TaskDelay(tick ? (UINT32)(tick + 1) : 0);
120 if (ret == LOS_OK || ret == LOS_ERRNO_TSK_YIELD_NOT_ENOUGH_TASK) {
121 if (rmtp) {
122 rmtp->tv_sec = rmtp->tv_nsec = 0;
123 }
124 return 0;
125 }
126
127 /* sleep in interrupt context or in task sched lock state */
128 errno = EINTR;
129 return -1;
130 }
131
timer_create(clockid_t clockID,struct sigevent * restrict evp,timer_t * restrict timerID)132 int timer_create(clockid_t clockID, struct sigevent *restrict evp, timer_t *restrict timerID)
133 {
134 UINT32 ret;
135 UINT32 swtmrID;
136
137 if (!timerID || (clockID != CLOCK_REALTIME) || !evp) {
138 errno = EINVAL;
139 return -1;
140 }
141
142 if ((evp->sigev_notify != SIGEV_THREAD) || evp->sigev_notify_attributes) {
143 errno = ENOTSUP;
144 return -1;
145 }
146
147 ret = LOS_SwtmrCreate(1, LOS_SWTMR_MODE_ONCE, (SWTMR_PROC_FUNC)evp->sigev_notify_function,
148 &swtmrID, (UINT32)(UINTPTR)evp->sigev_value.sival_ptr
149 #if (LOSCFG_BASE_CORE_SWTMR_ALIGN == 1)
150 , OS_SWTMR_ROUSES_IGNORE, OS_SWTMR_ALIGN_INSENSITIVE
151 #endif
152 );
153 if (ret != LOS_OK) {
154 errno = (ret == LOS_ERRNO_SWTMR_MAXSIZE) ? EAGAIN : EINVAL;
155 return -1;
156 }
157
158 *timerID = (timer_t)(UINTPTR)swtmrID;
159 return 0;
160 }
161
timer_delete(timer_t timerID)162 int timer_delete(timer_t timerID)
163 {
164 UINT32 swtmrID = (UINT32)(UINTPTR)timerID;
165 if (LOS_SwtmrDelete(swtmrID) != LOS_OK) {
166 errno = EINVAL;
167 return -1;
168 }
169
170 return 0;
171 }
172
timer_settime(timer_t timerID,int flags,const struct itimerspec * restrict value,struct itimerspec * restrict oldValue)173 int timer_settime(timer_t timerID, int flags,
174 const struct itimerspec *restrict value,
175 struct itimerspec *restrict oldValue)
176 {
177 UINT32 intSave;
178 UINT32 swtmrID = (UINT32)(UINTPTR)timerID;
179 SWTMR_CTRL_S *swtmr = NULL;
180 UINT32 interval, expiry, ret;
181
182 if (flags != 0) {
183 /* flags not supported currently */
184 errno = ENOTSUP;
185 return -1;
186 }
187
188 if (value == NULL) {
189 errno = EINVAL;
190 return -1;
191 }
192
193 if (!ValidTimeSpec(&value->it_value) || !ValidTimeSpec(&value->it_interval)) {
194 errno = EINVAL;
195 return -1;
196 }
197
198 expiry = OsTimeSpec2Tick(&value->it_value);
199 interval = OsTimeSpec2Tick(&value->it_interval);
200
201 /* if specified interval, it must be same with expiry due to the limitation of liteos-m */
202 if (interval && interval != expiry) {
203 errno = ENOTSUP;
204 return -1;
205 }
206
207 if (oldValue) {
208 (VOID)timer_gettime(timerID, oldValue);
209 }
210
211 ret = LOS_SwtmrStop(swtmrID);
212 if ((ret != LOS_OK) && (ret != LOS_ERRNO_SWTMR_NOT_STARTED)) {
213 errno = EINVAL;
214 return -1;
215 }
216
217 intSave = LOS_IntLock();
218 swtmr = OS_SWT_FROM_SID(swtmrID);
219 swtmr->ucMode = (interval ? LOS_SWTMR_MODE_PERIOD : LOS_SWTMR_MODE_NO_SELFDELETE);
220 swtmr->uwInterval = (interval ? interval : expiry);
221
222 swtmr->ucOverrun = 0;
223 LOS_IntRestore(intSave);
224
225 if ((value->it_value.tv_sec == 0) && (value->it_value.tv_nsec == 0)) {
226 /*
227 * 1) when expiry is 0, means timer should be stopped.
228 * 2) If timer is ticking, stopping timer is already done before.
229 * 3) If timer is created but not ticking, return 0 as well.
230 */
231 return 0;
232 }
233
234 if (LOS_SwtmrStart(swtmr->usTimerID) != LOS_OK) {
235 errno = EINVAL;
236 return -1;
237 }
238
239 return 0;
240 }
241
timer_gettime(timer_t timerID,struct itimerspec * value)242 int timer_gettime(timer_t timerID, struct itimerspec *value)
243 {
244 UINT32 tick = 0;
245 SWTMR_CTRL_S *swtmr = NULL;
246 UINT32 swtmrID = (UINT32)(UINTPTR)timerID;
247 UINT32 ret;
248
249 if (value == NULL) {
250 errno = EINVAL;
251 return -1;
252 }
253
254 swtmr = OS_SWT_FROM_SID(swtmrID);
255
256 /* get expire time */
257 ret = LOS_SwtmrTimeGet(swtmr->usTimerID, &tick);
258 if ((ret != LOS_OK) && (ret != LOS_ERRNO_SWTMR_NOT_STARTED)) {
259 errno = EINVAL;
260 return -1;
261 }
262 if (ret == LOS_ERRNO_SWTMR_NOT_STARTED) {
263 tick = 0;
264 }
265 OsTick2TimeSpec(&value->it_value, tick);
266 OsTick2TimeSpec(&value->it_interval, (swtmr->ucMode == LOS_SWTMR_MODE_ONCE) ? 0 : swtmr->uwInterval);
267 return 0;
268 }
269
timer_getoverrun(timer_t timerID)270 int timer_getoverrun(timer_t timerID)
271 {
272 SWTMR_CTRL_S *swtmr = NULL;
273 swtmr = OS_SWT_FROM_SID((UINT32)(UINTPTR)timerID);
274
275 if ((swtmr->ucOverrun) >= (UINT8)DELAYTIMER_MAX) {
276 return (INT32)DELAYTIMER_MAX;
277 }
278 return (int)swtmr->ucOverrun;
279 }
280
OsGetHwTime(struct timespec * hwTime)281 STATIC VOID OsGetHwTime(struct timespec *hwTime)
282 {
283 UINT64 cycle = LOS_SysCycleGet();
284 UINT64 nowNsec = (cycle / g_sysClock) * OS_SYS_NS_PER_SECOND +
285 (cycle % g_sysClock) * OS_SYS_NS_PER_SECOND / g_sysClock;
286
287 hwTime->tv_sec = nowNsec / OS_SYS_NS_PER_SECOND;
288 hwTime->tv_nsec = nowNsec % OS_SYS_NS_PER_SECOND;
289 }
290
OsGetRealTime(struct timespec * realTime)291 STATIC VOID OsGetRealTime(struct timespec *realTime)
292 {
293 UINT32 intSave;
294 struct timespec hwTime = {0};
295 OsGetHwTime(&hwTime);
296 intSave = LOS_IntLock();
297 realTime->tv_nsec = hwTime.tv_nsec + g_accDeltaFromSet.tv_nsec;
298 realTime->tv_sec = hwTime.tv_sec + g_accDeltaFromSet.tv_sec + (realTime->tv_nsec >= OS_SYS_NS_PER_SECOND);
299 realTime->tv_nsec %= OS_SYS_NS_PER_SECOND;
300 LOS_IntRestore(intSave);
301 }
302
OsSetRealTime(const struct timespec * realTime)303 STATIC VOID OsSetRealTime(const struct timespec *realTime)
304 {
305 UINT32 intSave;
306 struct timespec hwTime = {0};
307 OsGetHwTime(&hwTime);
308 intSave = LOS_IntLock();
309 g_accDeltaFromSet.tv_nsec = realTime->tv_nsec - hwTime.tv_nsec;
310 g_accDeltaFromSet.tv_sec = realTime->tv_sec - hwTime.tv_sec - (g_accDeltaFromSet.tv_nsec < 0);
311 g_accDeltaFromSet.tv_nsec = (g_accDeltaFromSet.tv_nsec + OS_SYS_NS_PER_SECOND) % OS_SYS_NS_PER_SECOND;
312 LOS_IntRestore(intSave);
313 }
314
clock_settime(clockid_t clockID,const struct timespec * tp)315 int clock_settime(clockid_t clockID, const struct timespec *tp)
316 {
317 if (!ValidTimeSpec(tp)) {
318 errno = EINVAL;
319 return -1;
320 }
321
322 switch (clockID) {
323 case CLOCK_REALTIME:
324 /* we only support the realtime clock currently */
325 OsSetRealTime(tp);
326 return 0;
327 case CLOCK_MONOTONIC_COARSE:
328 case CLOCK_REALTIME_COARSE:
329 case CLOCK_MONOTONIC_RAW:
330 case CLOCK_PROCESS_CPUTIME_ID:
331 case CLOCK_BOOTTIME:
332 #ifdef CLOCK_REALTIME_ALARM
333 case CLOCK_REALTIME_ALARM:
334 #endif
335 #ifdef CLOCK_BOOTTIME_ALARM
336 case CLOCK_BOOTTIME_ALARM:
337 #endif
338 #ifdef CLOCK_SGI_CYCLE
339 case CLOCK_SGI_CYCLE:
340 #endif
341 #ifdef CLOCK_TAI
342 case CLOCK_TAI:
343 #endif
344 case CLOCK_THREAD_CPUTIME_ID:
345 errno = ENOTSUP;
346 return -1;
347 case CLOCK_MONOTONIC:
348 default:
349 errno = EINVAL;
350 return -1;
351 }
352 }
353
clock_gettime(clockid_t clockID,struct timespec * tp)354 int clock_gettime(clockid_t clockID, struct timespec *tp)
355 {
356 if (tp == NULL) {
357 errno = EINVAL;
358 return -1;
359 }
360
361 switch (clockID) {
362 case CLOCK_MONOTONIC_RAW:
363 case CLOCK_MONOTONIC:
364 case CLOCK_MONOTONIC_COARSE:
365 OsGetHwTime(tp);
366 return 0;
367 case CLOCK_REALTIME:
368 case CLOCK_REALTIME_COARSE:
369 OsGetRealTime(tp);
370 return 0;
371 case CLOCK_THREAD_CPUTIME_ID:
372 case CLOCK_PROCESS_CPUTIME_ID:
373 case CLOCK_BOOTTIME:
374 #ifdef CLOCK_REALTIME_ALARM
375 case CLOCK_REALTIME_ALARM:
376 #endif
377 #ifdef CLOCK_BOOTTIME_ALARM
378 case CLOCK_BOOTTIME_ALARM:
379 #endif
380 #ifdef CLOCK_SGI_CYCLE
381 case CLOCK_SGI_CYCLE:
382 #endif
383 #ifdef CLOCK_TAI
384 case CLOCK_TAI:
385 #endif
386 errno = ENOTSUP;
387 return -1;
388 default:
389 errno = EINVAL;
390 return -1;
391 }
392 }
393
clock_getres(clockid_t clockID,struct timespec * tp)394 int clock_getres(clockid_t clockID, struct timespec *tp)
395 {
396 if (tp == NULL) {
397 errno = EINVAL;
398 return -1;
399 }
400
401 switch (clockID) {
402 case CLOCK_MONOTONIC_RAW:
403 case CLOCK_MONOTONIC:
404 case CLOCK_REALTIME:
405 case CLOCK_MONOTONIC_COARSE:
406 case CLOCK_REALTIME_COARSE:
407 tp->tv_nsec = OS_SYS_NS_PER_SECOND / g_sysClock;
408 tp->tv_sec = 0;
409 return 0;
410 case CLOCK_THREAD_CPUTIME_ID:
411 case CLOCK_PROCESS_CPUTIME_ID:
412 case CLOCK_BOOTTIME:
413 #ifdef CLOCK_REALTIME_ALARM
414 case CLOCK_REALTIME_ALARM:
415 #endif
416 #ifdef CLOCK_BOOTTIME_ALARM
417 case CLOCK_BOOTTIME_ALARM:
418 #endif
419 #ifdef CLOCK_SGI_CYCLE
420 case CLOCK_SGI_CYCLE:
421 #endif
422 #ifdef CLOCK_TAI
423 case CLOCK_TAI:
424 #endif
425 errno = ENOTSUP;
426 return -1;
427 default:
428 errno = EINVAL;
429 return -1;
430 }
431 }
432
clock_nanosleep(clockid_t clk,int flags,const struct timespec * req,struct timespec * rem)433 int clock_nanosleep(clockid_t clk, int flags, const struct timespec *req, struct timespec *rem)
434 {
435 switch (clk) {
436 case CLOCK_REALTIME:
437 if (flags == 0) {
438 /* we only support the realtime clock currently */
439 return nanosleep(req, rem);
440 }
441 /* fallthrough */
442 case CLOCK_MONOTONIC_COARSE:
443 case CLOCK_REALTIME_COARSE:
444 case CLOCK_MONOTONIC_RAW:
445 case CLOCK_MONOTONIC:
446 case CLOCK_PROCESS_CPUTIME_ID:
447 case CLOCK_BOOTTIME:
448 #ifdef CLOCK_REALTIME_ALARM
449 case CLOCK_REALTIME_ALARM:
450 #endif
451 #ifdef CLOCK_BOOTTIME_ALARM
452 case CLOCK_BOOTTIME_ALARM:
453 #endif
454 #ifdef CLOCK_SGI_CYCLE
455 case CLOCK_SGI_CYCLE:
456 #endif
457 #ifdef CLOCK_TAI
458 case CLOCK_TAI:
459 #endif
460 if (flags == 0 || flags == TIMER_ABSTIME) {
461 return ENOTSUP;
462 }
463 /* fallthrough */
464 case CLOCK_THREAD_CPUTIME_ID:
465 default:
466 return EINVAL;
467 }
468 }
469
clock(void)470 clock_t clock(void)
471 {
472 if (g_rtcTimeFunc.RtcGetTickHook != NULL) {
473 return g_rtcTimeFunc.RtcGetTickHook();
474 }
475
476 clock_t clk;
477 struct timespec hwTime;
478 OsGetHwTime(&hwTime);
479
480 clk = hwTime.tv_sec * CLOCKS_PER_SEC;
481 clk += hwTime.tv_nsec / (OS_SYS_NS_PER_SECOND / CLOCKS_PER_SEC);
482
483 return clk;
484 }
485
GetCurrentTime(VOID)486 STATIC UINT64 GetCurrentTime(VOID)
487 {
488 UINT64 tickDelta = 0;
489 UINT64 currentTick;
490
491 if (g_rtcTimeFunc.RtcGetTickHook != NULL) {
492 currentTick = g_rtcTimeFunc.RtcGetTickHook();
493 if ((g_systickBase != 0) && (currentTick > g_systickBase)) {
494 tickDelta = currentTick - g_systickBase;
495 }
496 }
497 return g_rtcTimeBase + LOS_Tick2MS((UINT32)tickDelta);
498 }
499
time(time_t * timer)500 time_t time(time_t *timer)
501 {
502 UINT64 usec = 0;
503 time_t sec;
504 INT32 rtcRet;
505
506 if (g_rtcTimeFunc.RtcGetTimeHook != NULL) {
507 rtcRet = g_rtcTimeFunc.RtcGetTimeHook(&usec);
508 if (rtcRet != 0) {
509 UINT64 currentTime;
510 currentTime = GetCurrentTime();
511 sec = currentTime / OS_SYS_MS_PER_SECOND;
512 } else {
513 sec = usec / OS_SYS_US_PER_SECOND;
514 }
515 if (timer != NULL) {
516 *timer = sec;
517 }
518 return sec;
519 } else {
520 struct timespec ts;
521 if (-1 == clock_gettime(CLOCK_REALTIME, &ts)) {
522 return (time_t)-1;
523 }
524
525 if (timer != NULL) {
526 *timer = ts.tv_sec;
527 }
528 return ts.tv_sec;
529 }
530 }
531
532 #ifndef __USE_NEWLIB__
533 /*
534 * Compute the `struct tm' representation of T,
535 * offset OFFSET seconds east of UTC,
536 * and store year, yday, mon, mday, wday, hour, min, sec into *TP.
537 * Return nonzero if successful.
538 */
ConvertSecs2Utc(time_t t,INT32 offset,struct tm * tp)539 static INT32 ConvertSecs2Utc(time_t t, INT32 offset, struct tm *tp)
540 {
541 time_t days;
542 time_t rem;
543 time_t year;
544 time_t month;
545 time_t yearGuess;
546
547 days = t / SECS_PER_DAY;
548 rem = t % SECS_PER_DAY;
549 rem += offset;
550 while (rem < 0) {
551 rem += SECS_PER_DAY;
552 --days;
553 }
554 while (rem >= SECS_PER_DAY) {
555 rem -= SECS_PER_DAY;
556 ++days;
557 }
558 tp->tm_hour = rem / SECS_PER_HOUR;
559 rem %= SECS_PER_HOUR;
560 tp->tm_min = rem / SECS_PER_MIN;
561 tp->tm_sec = rem % SECS_PER_MIN;
562 /* January 1, 1970 was a Thursday. */
563 tp->tm_wday = (BEGIN_WEEKDAY + days) % DAYS_PER_WEEK;
564 if (tp->tm_wday < 0) {
565 tp->tm_wday += DAYS_PER_WEEK;
566 }
567 year = EPOCH_YEAR;
568
569 while ((days < 0) ||
570 (days >= (IS_LEAP_YEAR (year) ? DAYS_PER_LEAP_YEAR : DAYS_PER_NORMAL_YEAR))) {
571 /* Guess a corrected year, assuming 365 days per year. */
572 yearGuess = year + days / DAYS_PER_NORMAL_YEAR - (days % DAYS_PER_NORMAL_YEAR < 0);
573
574 /* Adjust days and year to match the guessed year. */
575 days -= ((yearGuess - year) * DAYS_PER_NORMAL_YEAR +
576 LEAPS_THRU_END_OF (yearGuess - 1) -
577 LEAPS_THRU_END_OF (year - 1));
578 year = yearGuess;
579 }
580 tp->tm_year = year - TM_YEAR_BASE;
581 if (tp->tm_year != year - TM_YEAR_BASE) {
582 return 0;
583 }
584 tp->tm_yday = days;
585 const UINT16 *daysInMonth = g_daysInMonth[IS_LEAP_YEAR(year)];
586 /* valid month value is 0-11 */
587 for (month = 11; days < (long int) daysInMonth[month]; --month) {
588 continue;
589 }
590 days -= daysInMonth[month];
591 tp->tm_mon = month;
592 tp->tm_mday = days + 1;
593 tp->__tm_gmtoff = offset;
594 tp->__tm_zone = NULL;
595 tp->tm_isdst = 0;
596 return 1;
597 }
598
gmtime_r(const time_t * timep,struct tm * result)599 struct tm *gmtime_r(const time_t *timep, struct tm *result)
600 {
601 if ((timep == NULL) || (result == NULL)) {
602 errno = EFAULT;
603 return NULL;
604 }
605 if (!ConvertSecs2Utc(*timep, 0, result)) {
606 errno = EINVAL;
607 return NULL;
608 }
609 return result;
610 }
611
gmtime(const time_t * timer)612 struct tm *gmtime(const time_t *timer)
613 {
614 static struct tm tm;
615 return gmtime_r(timer, &tm);
616 }
617
localtime_r(const time_t * timep,struct tm * result)618 struct tm *localtime_r(const time_t *timep, struct tm *result)
619 {
620 INT32 ret;
621
622 if ((timep == NULL) || (result == NULL)) {
623 errno = EFAULT;
624 return NULL;
625 }
626
627 if (g_rtcTimeFunc.RtcGetTimezoneHook != NULL) {
628 INT32 tempTimezone = 0;
629 g_rtcTimeFunc.RtcGetTimezoneHook(&tempTimezone);
630 ret = ConvertSecs2Utc(*timep, -tempTimezone, result);
631 } else {
632 ret = ConvertSecs2Utc(*timep, -g_timezone, result);
633 }
634
635 if (!ret) {
636 errno = EINVAL;
637 return NULL;
638 }
639 return result;
640 }
641
localtime(const time_t * timer)642 struct tm *localtime(const time_t *timer)
643 {
644 static struct tm tm;
645 return localtime_r(timer, &tm);
646 }
647
ConvertUtc2Secs(struct tm * tm)648 static time_t ConvertUtc2Secs(struct tm *tm)
649 {
650 time_t seconds = 0;
651 INT32 month = 0;
652 UINT8 leap = 0;
653
654 INT32 year = (EPOCH_YEAR - TM_YEAR_BASE);
655 while (year < tm->tm_year) {
656 seconds += SECS_PER_NORMAL_YEAR;
657 if (IS_LEAP_YEAR(year + TM_YEAR_BASE)) {
658 seconds += SECS_PER_DAY;
659 }
660 year++;
661 }
662
663 if (IS_LEAP_YEAR(tm->tm_year + TM_YEAR_BASE)) {
664 leap = 1;
665 }
666 while (month < tm->tm_mon) {
667 if ((month == 1) && leap) {
668 seconds += (g_montbl[month] + 1) * SECS_PER_DAY;
669 } else {
670 seconds += g_montbl[month] * SECS_PER_DAY;
671 }
672 month++;
673 }
674
675 seconds += (tm->tm_mday - 1) * SECS_PER_DAY;
676 seconds += tm->tm_hour * SECS_PER_HOUR + tm->tm_min * SECS_PER_MIN + tm->tm_sec;
677
678 if (g_rtcTimeFunc.RtcGetTimezoneHook != NULL) {
679 INT32 tempTimezone = 0;
680 g_rtcTimeFunc.RtcGetTimezoneHook(&tempTimezone);
681 seconds += tempTimezone;
682 } else {
683 seconds += g_timezone;
684 }
685
686 return seconds;
687 }
688
mktime(struct tm * tmptr)689 time_t mktime(struct tm *tmptr)
690 {
691 time_t timeInSeconds;
692 if (tmptr == NULL) {
693 errno = EFAULT;
694 return (time_t)-1;
695 }
696
697 /* tm_isdst is not supported and is ignored */
698 if (tmptr->tm_year < (EPOCH_YEAR - TM_YEAR_BASE) ||
699 tmptr->__tm_gmtoff > (-TIME_ZONE_MIN * SECS_PER_MIN) ||
700 tmptr->__tm_gmtoff < (-TIME_ZONE_MAX * SECS_PER_MIN) ||
701 tmptr->tm_sec > 60 || tmptr->tm_sec < 0 || /* Seconds [0-60] */
702 tmptr->tm_min > 59 || tmptr->tm_min < 0 || /* Minutes [0-59] */
703 tmptr->tm_hour > 23 || tmptr->tm_hour < 0 || /* Hours [0-23] */
704 tmptr->tm_mday > 31 || tmptr->tm_mday < 1 || /* Day of the month [1-31] */
705 tmptr->tm_mon > 11 || tmptr->tm_mon < 0) { /* Month [0-11] */
706 errno = EOVERFLOW;
707 return (time_t)-1;
708 }
709 timeInSeconds = ConvertUtc2Secs(tmptr);
710 /* normalize tm_wday and tm_yday */
711 if (g_rtcTimeFunc.RtcGetTimezoneHook != NULL) {
712 INT32 tempTimezone = 0;
713 g_rtcTimeFunc.RtcGetTimezoneHook(&tempTimezone);
714 ConvertSecs2Utc(timeInSeconds, -tempTimezone, tmptr);
715 } else {
716 ConvertSecs2Utc(timeInSeconds, -g_timezone, tmptr);
717 }
718
719 return timeInSeconds;
720 }
721
gettimeofday(struct timeval * tv,void * ptz)722 int gettimeofday(struct timeval *tv, void *ptz)
723 {
724 struct timezone *tz = (struct timezone *)ptz;
725
726 if (tv != NULL) {
727 INT32 rtcRet;
728 UINT64 usec = 0;
729 UINT64 currentTime;
730
731 if (g_rtcTimeFunc.RtcGetTimeHook != NULL) {
732 rtcRet = g_rtcTimeFunc.RtcGetTimeHook(&usec);
733 if (rtcRet != 0) {
734 currentTime = GetCurrentTime();
735 tv->tv_sec = currentTime / OS_SYS_MS_PER_SECOND;
736 tv->tv_usec = (currentTime % OS_SYS_MS_PER_SECOND) * OS_SYS_MS_PER_SECOND;
737 } else {
738 tv->tv_sec = usec / OS_SYS_US_PER_SECOND;
739 tv->tv_usec = usec % OS_SYS_US_PER_SECOND;
740 }
741 } else {
742 struct timespec ts;
743 if (-1 == clock_gettime(CLOCK_REALTIME, &ts)) {
744 return -1;
745 }
746 tv->tv_sec = ts.tv_sec;
747 tv->tv_usec = ts.tv_nsec / OS_SYS_NS_PER_US;
748 }
749 }
750
751 if (tz != NULL) {
752 INT32 timeZone = 0;
753 if (g_rtcTimeFunc.RtcGetTimezoneHook != NULL) {
754 g_rtcTimeFunc.RtcGetTimezoneHook(&timeZone);
755 tz->tz_minuteswest = timezone / SECS_PER_MIN;
756 } else {
757 tz->tz_minuteswest = g_timezone / SECS_PER_MIN;
758 }
759
760 tz->tz_dsttime = 0;
761 }
762 return 0;
763 }
764 #endif
765
settimeofday(const struct timeval * tv,const struct timezone * tz)766 int settimeofday(const struct timeval *tv, const struct timezone *tz)
767 {
768 struct timespec ts;
769
770 if ((tv == NULL) && (tz == NULL)) {
771 errno = EFAULT;
772 return -1;
773 }
774
775 if ((tv != NULL) && (tv->tv_usec >= OS_SYS_US_PER_SECOND)) {
776 errno = EINVAL;
777 return -1;
778 }
779
780 if (tz != NULL) {
781 if ((tz->tz_minuteswest >= TIME_ZONE_MIN) &&
782 (tz->tz_minuteswest <= TIME_ZONE_MAX)) {
783 g_timezone = tz->tz_minuteswest * SECS_PER_MIN;
784 } else {
785 errno = EINVAL;
786 return -1;
787 }
788
789 if (g_rtcTimeFunc.RtcSetTimezoneHook != NULL) {
790 g_rtcTimeFunc.RtcSetTimezoneHook(g_timezone);
791 }
792 }
793
794 if (tv != NULL) {
795 if (g_rtcTimeFunc.RtcSetTimeHook != NULL) {
796 UINT64 usec;
797 g_rtcTimeBase = tv->tv_sec * OS_SYS_MS_PER_SECOND + tv->tv_usec / OS_SYS_MS_PER_SECOND;
798 usec = tv->tv_sec * OS_SYS_US_PER_SECOND + tv->tv_usec;
799 if (g_rtcTimeFunc.RtcSetTimeHook(g_rtcTimeBase, &usec) < 0) {
800 return -1;
801 }
802 } else {
803 ts.tv_sec = tv->tv_sec;
804 ts.tv_nsec = tv->tv_usec * OS_SYS_NS_PER_US;
805 if (clock_settime(CLOCK_REALTIME, &ts) < 0) {
806 return -1;
807 }
808 }
809 }
810
811 if (g_rtcTimeFunc.RtcGetTickHook != NULL) {
812 g_systickBase = g_rtcTimeFunc.RtcGetTickHook();
813 }
814
815 return 0;
816 }
817
usleep(useconds_t useconds)818 int usleep(useconds_t useconds)
819 {
820 struct timespec specTime = { 0 };
821 UINT64 nanoseconds = (UINT64)useconds * OS_SYS_NS_PER_US;
822
823 specTime.tv_sec = (time_t)(nanoseconds / OS_SYS_NS_PER_SECOND);
824 specTime.tv_nsec = (long)(nanoseconds % OS_SYS_NS_PER_SECOND);
825 return nanosleep(&specTime, NULL);
826 }
827
sleep(unsigned seconds)828 unsigned sleep(unsigned seconds)
829 {
830 struct timespec specTime = { 0 };
831 UINT64 nanoseconds = (UINT64)seconds * OS_SYS_NS_PER_SECOND;
832
833 specTime.tv_sec = (time_t)(nanoseconds / OS_SYS_NS_PER_SECOND);
834 specTime.tv_nsec = (long)(nanoseconds % OS_SYS_NS_PER_SECOND);
835 return nanosleep(&specTime, NULL);
836 }
837
times(struct tms * tms)838 clock_t times(struct tms *tms)
839 {
840 clock_t clockTick = (clock_t)LOS_TickCountGet();
841
842 if (tms != NULL) {
843 tms->tms_cstime = clockTick;
844 tms->tms_cutime = clockTick;
845 tms->tms_stime = clockTick;
846 tms->tms_utime = clockTick;
847 }
848 return clockTick;
849 }
850