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