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 */ 51STATIC struct timespec g_accDeltaFromSet; 52 53STATIC 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 60STATIC 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 */ 71long TIMEZONE = -8 * 60 * 60; // set default to CST(UTC+8) 72#endif 73 74/* 75 * store register rtc func 76 */ 77STATIC struct RtcTimeHook g_rtcTimeFunc; 78 79STATIC UINT64 g_rtcTimeBase = 0; 80STATIC UINT64 g_systickBase = 0; 81 82VOID 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 94int 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 129int 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 159int 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 170int 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 239int 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 267int 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 278STATIC 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 288STATIC 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 300STATIC 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 312int 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 351int 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 391int 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 430int 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 467clock_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 483STATIC 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 497time_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 */ 535static 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 595struct 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 608struct tm *gmtime(const time_t *timer) 609{ 610 static struct tm tm; 611 return gmtime_r(timer, &tm); 612} 613 614struct 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 638struct tm *localtime(const time_t *timer) 639{ 640 static struct tm tm; 641 return localtime_r(timer, &tm); 642} 643 644static 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 685time_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 718int 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) 752FUNC_ALIAS(gettimeofday, _gettimeofday, (struct timeval *tv, void *ptz), int); 753#endif 754 755int 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 807int 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 817unsigned 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 827clock_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