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