Changeset 7f9d97f3 in mainline for uspace/lib/c/generic/time.c


Ignore:
Timestamp:
2015-03-14T21:48:01Z (9 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
270bf4f
Parents:
c0c38c7c
Message:

Make gettimeofday() return the actual microseconds.

Enhance struct tm to also have a field to hold microseconds and make
sure that this information propagates from the RTC driver.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/c/generic/time.c

    rc0c38c7c r7f9d97f3  
    5959#define MINS_PER_HOUR  60
    6060#define SECS_PER_MIN   60
     61#define USECS_PER_SEC  1000000
    6162#define MINS_PER_DAY   (MINS_PER_HOUR * HOURS_PER_DAY)
    6263#define SECS_PER_HOUR  (SECS_PER_MIN * MINS_PER_HOUR)
     
    252253 * Optionally add specified amount of seconds.
    253254 *
    254  * @param tm      Broken-down time to normalize.
    255  * @param sec_add Seconds to add.
     255 * @param tm Broken-down time to normalize.
     256 * @param tv Timeval to add.
    256257 *
    257258 * @return 0 on success, -1 on overflow
    258259 *
    259260 */
    260 static int normalize_time(struct tm *tm, time_t sec_add)
     261static int normalize_tm_tv(struct tm *tm, const struct timeval *tv)
    261262{
    262263        // TODO: DST correction
    263264       
    264265        /* Set initial values. */
    265         time_t sec = tm->tm_sec + sec_add;
     266        time_t usec = tm->tm_usec + tv->tv_usec;
     267        time_t sec = tm->tm_sec + tv->tv_sec;
    266268        time_t min = tm->tm_min;
    267269        time_t hour = tm->tm_hour;
     
    271273       
    272274        /* Adjust time. */
     275        sec += floor_div(usec, USECS_PER_SEC);
     276        usec = floor_mod(usec, USECS_PER_SEC);
    273277        min += floor_div(sec, SECS_PER_MIN);
    274278        sec = floor_mod(sec, SECS_PER_MIN);
     
    319323       
    320324        /* And put the values back to the struct. */
     325        tm->tm_usec = (int) usec;
    321326        tm->tm_sec = (int) sec;
    322327        tm->tm_min = (int) min;
     
    335340}
    336341
     342static int normalize_tm_time(struct tm *tm, time_t time)
     343{
     344        struct timeval tv = {
     345                .tv_sec = time,
     346                .tv_usec = 0
     347        };
     348
     349        return normalize_tm_tv(tm, &tv);
     350}
     351
     352
    337353/** Which day the week-based year starts on.
    338354 *
     
    442458}
    443459
     460static void tv_normalize(struct timeval *tv)
     461{
     462        while (tv->tv_usec > USECS_PER_SEC) {
     463                tv->tv_sec++;
     464                tv->tv_usec -= USECS_PER_SEC;
     465        }
     466        while (tv->tv_usec < 0) {
     467                tv->tv_sec--;
     468                tv->tv_usec += USECS_PER_SEC;
     469        }
     470}
     471
    444472/** Add microseconds to given timeval.
    445473 *
     
    448476 *
    449477 */
    450 void tv_add(struct timeval *tv, suseconds_t usecs)
    451 {
    452         tv->tv_sec += usecs / 1000000;
    453         tv->tv_usec += usecs % 1000000;
    454        
    455         if (tv->tv_usec > 1000000) {
    456                 tv->tv_sec++;
    457                 tv->tv_usec -= 1000000;
    458         }
    459 }
    460 
    461 /** Subtract two timevals.
     478void tv_add_diff(struct timeval *tv, suseconds_t usecs)
     479{
     480        tv->tv_sec += usecs / USECS_PER_SEC;
     481        tv->tv_usec += usecs % USECS_PER_SEC;
     482        tv_normalize(tv);
     483}
     484
     485/** Add two timevals.
    462486 *
    463487 * @param tv1 First timeval.
    464488 * @param tv2 Second timeval.
     489 */
     490void tv_add(struct timeval *tv1, struct timeval *tv2)
     491{
     492        tv1->tv_sec += tv2->tv_sec;
     493        tv1->tv_usec += tv2->tv_usec;
     494        tv_normalize(tv1);
     495}
     496
     497/** Subtract two timevals.
     498 *
     499 * @param tv1 First timeval.
     500 * @param tv2 Second timeval.
    465501 *
    466502 * @return Difference between tv1 and tv2 (tv1 - tv2) in
     
    468504 *
    469505 */
    470 suseconds_t tv_sub(struct timeval *tv1, struct timeval *tv2)
     506suseconds_t tv_sub_diff(struct timeval *tv1, struct timeval *tv2)
    471507{
    472508        return (tv1->tv_usec - tv2->tv_usec) +
    473             ((tv1->tv_sec - tv2->tv_sec) * 1000000);
     509            ((tv1->tv_sec - tv2->tv_sec) * USECS_PER_SEC);
     510}
     511
     512/** Subtract two timevals.
     513 *
     514 * @param tv1 First timeval.
     515 * @param tv2 Second timeval.
     516 *
     517 */
     518void tv_sub(struct timeval *tv1, struct timeval *tv2)
     519{
     520        tv1->tv_sec -= tv2->tv_sec;
     521        tv1->tv_usec -= tv2->tv_usec;
     522        tv_normalize(tv1);
    474523}
    475524
     
    573622                goto fallback;
    574623       
    575         tv->tv_usec = 0;
     624        tv->tv_usec = time.tm_usec;
    576625        tv->tv_sec = mktime(&time);
    577626       
     
    689738        // TODO: detect overflow
    690739       
    691         normalize_time(tm, 0);
     740        normalize_tm_time(tm, 0);
    692741        return secs_since_epoch(tm);
    693742}
     
    944993       
    945994        /* Set result to epoch. */
     995        result->tm_usec = 0;
    946996        result->tm_sec = 0;
    947997        result->tm_min = 0;
     
    9511001        result->tm_year = 70; /* 1970 */
    9521002       
    953         if (normalize_time(result, time) == -1)
     1003        if (normalize_tm_time(result, time) == -1)
    9541004                return EOVERFLOW;
    9551005       
     
    10141064 * Time is expressed relative to the user's specified timezone.
    10151065 *
    1016  * @param timer  Time to convert.
     1066 * @param tv     Timeval to convert.
    10171067 * @param result Structure to store the result to.
    10181068 *
     
    10201070 *
    10211071 */
    1022 int time_local2tm(const time_t time, struct tm *restrict result)
     1072int time_tv2tm(const struct timeval *tv, struct tm *restrict result)
    10231073{
    10241074        // TODO: Deal with timezones.
     
    10261076       
    10271077        /* Set result to epoch. */
     1078        result->tm_usec = 0;
    10281079        result->tm_sec = 0;
    10291080        result->tm_min = 0;
     
    10331084        result->tm_year = 70; /* 1970 */
    10341085       
    1035         if (normalize_time(result, time) == -1)
     1086        if (normalize_tm_tv(result, tv) == -1)
    10361087                return EOVERFLOW;
    10371088       
    10381089        return EOK;
     1090}
     1091
     1092/** Converts a time value to a broken-down local time.
     1093 *
     1094 * Time is expressed relative to the user's specified timezone.
     1095 *
     1096 * @param timer  Time to convert.
     1097 * @param result Structure to store the result to.
     1098 *
     1099 * @return EOK on success or a negative error code.
     1100 *
     1101 */
     1102int time_local2tm(const time_t time, struct tm *restrict result)
     1103{
     1104        struct timeval tv = {
     1105                .tv_sec = time,
     1106                .tv_usec = 0
     1107        };
     1108
     1109        return time_tv2tm(&tv, result);
    10391110}
    10401111
Note: See TracChangeset for help on using the changeset viewer.