• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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