Changes in uspace/lib/c/generic/time.c [3c45353:05882233] in mainline
- File:
-
- 1 edited
-
uspace/lib/c/generic/time.c (modified) (20 diffs)
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/generic/time.c
r3c45353 r05882233 35 35 */ 36 36 37 #include <sys/time.h> 37 38 #include <time.h> 38 39 #include <stdbool.h> … … 50 51 #include <loc.h> 51 52 #include <device/clock_dev.h> 52 #include <stats.h>53 53 54 54 #define ASCTIME_BUF_LEN 26 … … 57 57 #define MINS_PER_HOUR 60 58 58 #define SECS_PER_MIN 60 59 #define NSECS_PER_SEC 1000000000ll59 #define USECS_PER_SEC 1000000 60 60 #define MINS_PER_DAY (MINS_PER_HOUR * HOURS_PER_DAY) 61 61 #define SECS_PER_HOUR (SECS_PER_MIN * MINS_PER_HOUR) … … 71 71 static async_sess_t *clock_conn = NULL; 72 72 73 /**74 * Get CPU time used since the process invocation.75 *76 * @return Consumed microseconds by this process or -1 if not available.77 */78 clock_t clock(void)79 {80 static_assert(CLOCKS_PER_SEC == 1000000);81 82 size_t count;83 stats_cpu_t *cpu_stats = stats_get_cpus(&count);84 if (!cpu_stats)85 return (clock_t) -1;86 if (!cpu_stats->frequency_mhz) {87 free(cpu_stats);88 return (clock_t) -1;89 }90 91 clock_t total_usecs = -1;92 if (cpu_stats) {93 stats_task_t *task_stats = stats_get_task(task_get_id());94 if (task_stats) {95 total_usecs = (clock_t) (task_stats->kcycles +96 task_stats->ucycles) / cpu_stats->frequency_mhz;97 free(task_stats);98 }99 free(cpu_stats);100 }101 102 return total_usecs;103 }104 105 73 /** Check whether the year is a leap year. 106 74 * … … 284 252 * 285 253 * @param tm Broken-down time to normalize. 286 * @param t s Timespecto add.254 * @param tv Timeval to add. 287 255 * 288 256 * @return 0 on success, -1 on overflow 289 257 * 290 258 */ 291 static int normalize_tm_t s(struct tm *tm, const struct timespec *ts)259 static int normalize_tm_tv(struct tm *tm, const struct timeval *tv) 292 260 { 293 261 // TODO: DST correction 294 262 295 263 /* Set initial values. */ 296 time_t nsec = tm->tm_nsec + ts->tv_nsec;297 time_t sec = tm->tm_sec + t s->tv_sec;264 time_t usec = tm->tm_usec + tv->tv_usec; 265 time_t sec = tm->tm_sec + tv->tv_sec; 298 266 time_t min = tm->tm_min; 299 267 time_t hour = tm->tm_hour; … … 303 271 304 272 /* Adjust time. */ 305 sec += floor_div( nsec, NSECS_PER_SEC);306 nsec = floor_mod(nsec, NSECS_PER_SEC);273 sec += floor_div(usec, USECS_PER_SEC); 274 usec = floor_mod(usec, USECS_PER_SEC); 307 275 min += floor_div(sec, SECS_PER_MIN); 308 276 sec = floor_mod(sec, SECS_PER_MIN); … … 353 321 354 322 /* And put the values back to the struct. */ 355 tm->tm_ nsec = (int) nsec;323 tm->tm_usec = (int) usec; 356 324 tm->tm_sec = (int) sec; 357 325 tm->tm_min = (int) min; … … 372 340 static int normalize_tm_time(struct tm *tm, time_t time) 373 341 { 374 struct time spec ts= {342 struct timeval tv = { 375 343 .tv_sec = time, 376 .tv_ nsec = 0344 .tv_usec = 0 377 345 }; 378 346 379 return normalize_tm_t s(tm, &ts);347 return normalize_tm_tv(tm, &tv); 380 348 } 381 349 … … 488 456 } 489 457 490 static void ts_normalize(struct timespec *ts) 491 { 492 while (ts->tv_nsec >= NSECS_PER_SEC) { 493 ts->tv_sec++; 494 ts->tv_nsec -= NSECS_PER_SEC; 495 } 496 while (ts->tv_nsec < 0) { 497 ts->tv_sec--; 498 ts->tv_nsec += NSECS_PER_SEC; 499 } 500 } 501 502 /** Add nanoseconds to given timespec. 503 * 504 * @param ts Destination timespec. 505 * @param nsecs Number of nanoseconds to add. 506 * 507 */ 508 void ts_add_diff(struct timespec *ts, nsec_t nsecs) 509 { 510 ts->tv_sec += nsecs / NSECS_PER_SEC; 511 ts->tv_nsec += nsecs % NSECS_PER_SEC; 512 ts_normalize(ts); 513 } 514 515 /** Add two timespecs. 516 * 517 * @param ts1 First timespec. 518 * @param ts2 Second timespec. 519 */ 520 void ts_add(struct timespec *ts1, const struct timespec *ts2) 521 { 522 ts1->tv_sec += ts2->tv_sec; 523 ts1->tv_nsec += ts2->tv_nsec; 524 ts_normalize(ts1); 525 } 526 527 /** Subtract two timespecs. 528 * 529 * @param ts1 First timespec. 530 * @param ts2 Second timespec. 531 * 532 * @return Difference between ts1 and ts2 (ts1 - ts2) in nanoseconds. 533 * 534 */ 535 nsec_t ts_sub_diff(const struct timespec *ts1, const struct timespec *ts2) 536 { 537 return (nsec_t) (ts1->tv_nsec - ts2->tv_nsec) + 538 SEC2NSEC((ts1->tv_sec - ts2->tv_sec)); 539 } 540 541 /** Subtract two timespecs. 542 * 543 * @param ts1 First timespec. 544 * @param ts2 Second timespec. 545 * 546 */ 547 void ts_sub(struct timespec *ts1, const struct timespec *ts2) 548 { 549 ts1->tv_sec -= ts2->tv_sec; 550 ts1->tv_nsec -= ts2->tv_nsec; 551 ts_normalize(ts1); 552 } 553 554 /** Decide if one timespec is greater than the other. 555 * 556 * @param ts1 First timespec. 557 * @param ts2 Second timespec. 558 * 559 * @return True if ts1 is greater than ts2. 560 * @return False otherwise. 561 * 562 */ 563 bool ts_gt(const struct timespec *ts1, const struct timespec *ts2) 564 { 565 if (ts1->tv_sec > ts2->tv_sec) 458 static void tv_normalize(struct timeval *tv) 459 { 460 while (tv->tv_usec > USECS_PER_SEC) { 461 tv->tv_sec++; 462 tv->tv_usec -= USECS_PER_SEC; 463 } 464 while (tv->tv_usec < 0) { 465 tv->tv_sec--; 466 tv->tv_usec += USECS_PER_SEC; 467 } 468 } 469 470 /** Add microseconds to given timeval. 471 * 472 * @param tv Destination timeval. 473 * @param usecs Number of microseconds to add. 474 * 475 */ 476 void tv_add_diff(struct timeval *tv, suseconds_t usecs) 477 { 478 tv->tv_sec += usecs / USECS_PER_SEC; 479 tv->tv_usec += usecs % USECS_PER_SEC; 480 tv_normalize(tv); 481 } 482 483 /** Add two timevals. 484 * 485 * @param tv1 First timeval. 486 * @param tv2 Second timeval. 487 */ 488 void tv_add(struct timeval *tv1, const struct timeval *tv2) 489 { 490 tv1->tv_sec += tv2->tv_sec; 491 tv1->tv_usec += tv2->tv_usec; 492 tv_normalize(tv1); 493 } 494 495 /** Subtract two timevals. 496 * 497 * @param tv1 First timeval. 498 * @param tv2 Second timeval. 499 * 500 * @return Difference between tv1 and tv2 (tv1 - tv2) in 501 * microseconds. 502 * 503 */ 504 suseconds_t tv_sub_diff(const struct timeval *tv1, const struct timeval *tv2) 505 { 506 return (tv1->tv_usec - tv2->tv_usec) + 507 ((tv1->tv_sec - tv2->tv_sec) * USECS_PER_SEC); 508 } 509 510 /** Subtract two timevals. 511 * 512 * @param tv1 First timeval. 513 * @param tv2 Second timeval. 514 * 515 */ 516 void tv_sub(struct timeval *tv1, const struct timeval *tv2) 517 { 518 tv1->tv_sec -= tv2->tv_sec; 519 tv1->tv_usec -= tv2->tv_usec; 520 tv_normalize(tv1); 521 } 522 523 /** Decide if one timeval is greater than the other. 524 * 525 * @param t1 First timeval. 526 * @param t2 Second timeval. 527 * 528 * @return True if tv1 is greater than tv2. 529 * @return False otherwise. 530 * 531 */ 532 int tv_gt(const struct timeval *tv1, const struct timeval *tv2) 533 { 534 if (tv1->tv_sec > tv2->tv_sec) 566 535 return true; 567 536 568 if ((t s1->tv_sec == ts2->tv_sec) && (ts1->tv_nsec > ts2->tv_nsec))537 if ((tv1->tv_sec == tv2->tv_sec) && (tv1->tv_usec > tv2->tv_usec)) 569 538 return true; 570 539 … … 572 541 } 573 542 574 /** Decide if one time specis greater than or equal to the other.575 * 576 * @param t s1 First timespec.577 * @param t s2 Second timespec.578 * 579 * @return True if ts1 is greater than or equal to ts2.580 * @return False otherwise.581 * 582 */ 583 bool ts_gteq(const struct timespec *ts1, const struct timespec *ts2)584 { 585 if (t s1->tv_sec > ts2->tv_sec)543 /** Decide if one timeval is greater than or equal to the other. 544 * 545 * @param tv1 First timeval. 546 * @param tv2 Second timeval. 547 * 548 * @return True if tv1 is greater than or equal to tv2. 549 * @return False otherwise. 550 * 551 */ 552 int tv_gteq(const struct timeval *tv1, const struct timeval *tv2) 553 { 554 if (tv1->tv_sec > tv2->tv_sec) 586 555 return true; 587 556 588 if ((t s1->tv_sec == ts2->tv_sec) && (ts1->tv_nsec >= ts2->tv_nsec))557 if ((tv1->tv_sec == tv2->tv_sec) && (tv1->tv_usec >= tv2->tv_usec)) 589 558 return true; 590 559 … … 592 561 } 593 562 594 /** Get real time from a RTC service. 595 * 596 * @param[out] ts Timespec to hold time read from the RTC service (if 597 * available). If no such service exists, the returned time 598 * corresponds to system uptime. 599 */ 600 void getrealtime(struct timespec *ts) 601 { 563 /** Get time of day. 564 * 565 * The time variables are memory mapped (read-only) from kernel which 566 * updates them periodically. 567 * 568 * As it is impossible to read 2 values atomically, we use a trick: 569 * First we read the seconds, then we read the microseconds, then we 570 * read the seconds again. If a second elapsed in the meantime, set 571 * the microseconds to zero. 572 * 573 * This assures that the values returned by two subsequent calls 574 * to gettimeofday() are monotonous. 575 * 576 */ 577 void gettimeofday(struct timeval *tv, struct timezone *tz) 578 { 579 if (tz) { 580 tz->tz_minuteswest = 0; 581 tz->tz_dsttime = DST_NONE; 582 } 583 602 584 if (clock_conn == NULL) { 603 585 category_id_t cat_id; … … 638 620 goto fallback; 639 621 640 t s->tv_nsec = time.tm_nsec;641 t s->tv_sec = mktime(&time);622 tv->tv_usec = time.tm_usec; 623 tv->tv_sec = mktime(&time); 642 624 643 625 return; 644 626 645 627 fallback: 646 getuptime(ts); 647 } 648 649 /** Get system uptime. 650 * 651 * @param[out] ts Timespec to hold time current uptime. 652 * 653 * The time variables are memory mapped (read-only) from kernel which 654 * updates them periodically. 655 * 656 * As it is impossible to read 2 values atomically, we use a trick: 657 * First we read the seconds, then we read the microseconds, then we 658 * read the seconds again. If a second elapsed in the meantime, set 659 * the microseconds to zero. 660 * 661 * This assures that the values returned by two subsequent calls 662 * to getuptime() are monotonous. 663 * 664 */ 665 void getuptime(struct timespec *ts) 628 getuptime(tv); 629 } 630 631 void getuptime(struct timeval *tv) 666 632 { 667 633 if (ktime == NULL) { … … 688 654 689 655 read_barrier(); 690 t s->tv_nsec = USEC2NSEC(ktime->useconds);656 tv->tv_usec = ktime->useconds; 691 657 692 658 read_barrier(); … … 694 660 695 661 if (s1 != s2) { 696 t s->tv_sec = max(s1, s2);697 t s->tv_nsec = 0;662 tv->tv_sec = max(s1, s2); 663 tv->tv_usec = 0; 698 664 } else 699 t s->tv_sec = s1;665 tv->tv_sec = s1; 700 666 701 667 return; 702 668 703 669 fallback: 704 t s->tv_sec = 0;705 t s->tv_nsec = 0;670 tv->tv_sec = 0; 671 tv->tv_usec = 0; 706 672 } 707 673 708 674 time_t time(time_t *tloc) 709 675 { 710 struct time spec ts;711 get realtime(&ts);676 struct timeval tv; 677 gettimeofday(&tv, NULL); 712 678 713 679 if (tloc) 714 *tloc = t s.tv_sec;715 716 return t s.tv_sec;717 } 718 719 void udelay( sysarg_t time)680 *tloc = tv.tv_sec; 681 682 return tv.tv_sec; 683 } 684 685 void udelay(useconds_t time) 720 686 { 721 687 (void) __SYSCALL1(SYS_THREAD_UDELAY, (sysarg_t) time); … … 918 884 break; 919 885 case 's': 920 APPEND("%l ld", secs_since_epoch(tm));886 APPEND("%ld", secs_since_epoch(tm)); 921 887 break; 922 888 case 'S': … … 995 961 996 962 /* Set result to epoch. */ 997 result->tm_ nsec = 0;963 result->tm_usec = 0; 998 964 result->tm_sec = 0; 999 965 result->tm_min = 0; … … 1072 1038 * 1073 1039 */ 1074 errno_t time_t s2tm(const struct timespec *ts, struct tm *restrict result)1040 errno_t time_tv2tm(const struct timeval *tv, struct tm *restrict result) 1075 1041 { 1076 1042 // TODO: Deal with timezones. … … 1078 1044 1079 1045 /* Set result to epoch. */ 1080 result->tm_ nsec = 0;1046 result->tm_usec = 0; 1081 1047 result->tm_sec = 0; 1082 1048 result->tm_min = 0; … … 1086 1052 result->tm_year = 70; /* 1970 */ 1087 1053 1088 if (normalize_tm_t s(result, ts) == -1)1054 if (normalize_tm_tv(result, tv) == -1) 1089 1055 return EOVERFLOW; 1090 1056 … … 1104 1070 errno_t time_local2tm(const time_t time, struct tm *restrict result) 1105 1071 { 1106 struct time spec ts= {1072 struct timeval tv = { 1107 1073 .tv_sec = time, 1108 .tv_ nsec = 01074 .tv_usec = 0 1109 1075 }; 1110 1076 1111 return time_t s2tm(&ts, result);1077 return time_tv2tm(&tv, result); 1112 1078 } 1113 1079
Note:
See TracChangeset
for help on using the changeset viewer.
