Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset 7f9d97f3 in mainline


Ignore:
Timestamp:
2015-03-14T21:48:01Z (7 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master
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.

Location:
uspace
Files:
14 edited

Legend:

Unmodified
Added
Removed
  • uspace/app/barber/barber.c

    rc0c38c7c r7f9d97f3  
    233233        getuptime(&cur);
    234234       
    235         plan_frame_timer(tv_sub(&cur, &prev));
     235        plan_frame_timer(tv_sub_diff(&cur, &prev));
    236236}
    237237
  • uspace/app/nettest1/nettest1.c

    rc0c38c7c r7f9d97f3  
    412412        gettimeofday(&time_after, NULL);
    413413       
    414         printf("Tested in %ld microseconds\n", tv_sub(&time_after,
     414        printf("Tested in %ld microseconds\n", tv_sub_diff(&time_after,
    415415            &time_before));
    416416       
  • uspace/app/nettest2/nettest2.c

    rc0c38c7c r7f9d97f3  
    370370       
    371371        printf("sendto + recvfrom tested in %ld microseconds\n",
    372             tv_sub(&time_after, &time_before));
     372            tv_sub_diff(&time_after, &time_before));
    373373       
    374374        gettimeofday(&time_before, NULL);
     
    390390       
    391391        printf("sendto, recvfrom tested in %ld microseconds\n",
    392             tv_sub(&time_after, &time_before));
     392            tv_sub_diff(&time_after, &time_before));
    393393       
    394394        rc = sockets_close(verbose, socket_ids, sockets);
  • uspace/app/rcubench/rcubench.c

    rc0c38c7c r7f9d97f3  
    264264       
    265265        getuptime(&end);
    266         int64_t duration = tv_sub(&end, &start);
     266        int64_t duration = tv_sub_diff(&end, &start);
    267267       
    268268        uint64_t secs = (uint64_t)duration / 1000 / 1000;
  • uspace/app/tester/ipc/ping_pong.c

    rc0c38c7c r7f9d97f3  
    5050                gettimeofday(&now, NULL);
    5151               
    52                 if (tv_sub(&now, &start) >= DURATION_SECS * 1000000L)
     52                if (tv_sub_diff(&now, &start) >= DURATION_SECS * 1000000L)
    5353                        break;
    5454               
  • uspace/app/tester/ipc/starve.c

    rc0c38c7c r7f9d97f3  
    5252                gettimeofday(&now, NULL);
    5353               
    54                 if (tv_sub(&now, &start) >= DURATION_SECS * 1000000L)
     54                if (tv_sub_diff(&now, &start) >= DURATION_SECS * 1000000L)
    5555                        break;
    5656               
  • uspace/drv/time/cmos-rtc/cmos-rtc.c

    rc0c38c7c r7f9d97f3  
    7676        int clients_connected;
    7777        /** time at which the system booted */
    78         time_t boottime;
     78        struct timeval boot_time;
    7979} rtc_t;
    8080
     
    9797static int rtc_dev_remove(ddf_dev_t *dev);
    9898static void rtc_register_write(rtc_t *rtc, int reg, int data);
    99 static time_t uptime_get(void);
    10099static bool is_battery_ok(rtc_t *rtc);
    101100static int  rtc_fun_online(ddf_fun_t *fun);
     
    205204        ddf_msg(LVL_DEBUG, "rtc_dev_initialize %s", ddf_dev_get_name(rtc->dev));
    206205
    207         rtc->boottime = 0;
     206        rtc->boot_time.tv_sec = 0;
     207        rtc->boot_time.tv_usec = 0;
    208208        rtc->clients_connected = 0;
    209209
     
    326326        fibril_mutex_lock(&rtc->mutex);
    327327
    328         if (rtc->boottime != 0) {
     328        if (rtc->boot_time.tv_sec) {
    329329                /* There is no need to read the current time from the
    330330                 * device because it has already been cached.
    331331                 */
    332332
    333                 time_t cur_time = rtc->boottime + uptime_get();
    334 
     333                struct timeval curtime;
     334               
     335                getuptime(&curtime);
     336                tv_add(&curtime, &rtc->boot_time);
    335337                fibril_mutex_unlock(&rtc->mutex);
    336338
    337                 return time_local2tm(cur_time, t);
     339                return time_tv2tm(&curtime, t);
    338340        }
    339341
     
    344346        }
    345347
     348        /* Microseconds are below RTC's resolution, assume 0. */
     349        t->tm_usec = 0;
     350
    346351        /* now read the registers */
    347352        do {
    348353                /* Suspend until the update process has finished */
    349                 while (rtc_update_in_progress(rtc));
    350 
    351                 t->tm_sec  = rtc_register_read(rtc, RTC_SEC);
    352                 t->tm_min  = rtc_register_read(rtc, RTC_MIN);
     354                while (rtc_update_in_progress(rtc))
     355                        ;
     356
     357                t->tm_sec = rtc_register_read(rtc, RTC_SEC);
     358                t->tm_min = rtc_register_read(rtc, RTC_MIN);
    353359                t->tm_hour = rtc_register_read(rtc, RTC_HOUR);
    354360                t->tm_mday = rtc_register_read(rtc, RTC_DAY);
    355                 t->tm_mon  = rtc_register_read(rtc, RTC_MON);
     361                t->tm_mon = rtc_register_read(rtc, RTC_MON);
    356362                t->tm_year = rtc_register_read(rtc, RTC_YEAR);
    357363
    358364                /* Now check if it is stable */
    359         } while(t->tm_sec  != rtc_register_read(rtc, RTC_SEC) ||
    360             t->tm_min  != rtc_register_read(rtc, RTC_MIN) ||
     365        } while(t->tm_sec != rtc_register_read(rtc, RTC_SEC) ||
     366            t->tm_min != rtc_register_read(rtc, RTC_MIN) ||
    361367            t->tm_mday != rtc_register_read(rtc, RTC_DAY) ||
    362             t->tm_mon  != rtc_register_read(rtc, RTC_MON) ||
     368            t->tm_mon != rtc_register_read(rtc, RTC_MON) ||
    363369            t->tm_year != rtc_register_read(rtc, RTC_YEAR));
    364370
     
    366372        bool _12h_mode = !(rtc_register_read(rtc, RTC_STATUS_B) &
    367373            RTC_B_24H);
    368 
    369374        if (_12h_mode) {
    370375                /* The RTC is working in 12h mode, check if it is AM or PM */
     
    378383        /* Check if the RTC is working in BCD mode */
    379384        bcd_mode = !(rtc_register_read(rtc, RTC_STATUS_B) & RTC_B_BCD);
    380 
    381385        if (bcd_mode) {
    382                 t->tm_sec  = bcd2bin(t->tm_sec);
    383                 t->tm_min  = bcd2bin(t->tm_min);
     386                t->tm_sec = bcd2bin(t->tm_sec);
     387                t->tm_min = bcd2bin(t->tm_min);
    384388                t->tm_hour = bcd2bin(t->tm_hour);
    385389                t->tm_mday = bcd2bin(t->tm_mday);
    386                 t->tm_mon  = bcd2bin(t->tm_mon);
     390                t->tm_mon = bcd2bin(t->tm_mon);
    387391                t->tm_year = bcd2bin(t->tm_year);
    388392        }
     
    414418                result = EINVAL;
    415419        else {
    416                 rtc->boottime = r - uptime_get();
     420                struct timeval uptime;
     421
     422                getuptime(&uptime);
     423                rtc->boot_time.tv_sec = r;
     424                rtc->boot_time.tv_usec = t->tm_usec;    /* normalized */
     425                tv_sub(&rtc->boot_time, &uptime);
    417426                result = EOK;
    418427        }
     
    435444        bool bcd_mode;
    436445        time_t norm_time;
    437         time_t uptime;
     446        struct timeval uptime;
     447        struct timeval ntv;
    438448        int  reg_b;
    439449        int  reg_a;
     
    445455                return EINVAL;
    446456
    447         uptime = uptime_get();
    448         if (norm_time <= uptime) {
     457        ntv.tv_sec = norm_time;
     458        ntv.tv_usec = t->tm_usec;
     459        getuptime(&uptime);
     460
     461        if (tv_gteq(&uptime, &ntv)) {
    449462                /* This is not acceptable */
    450463                return EINVAL;
     
    458471        }
    459472
    460         /* boottime must be recomputed */
    461         rtc->boottime = 0;
     473        /* boot_time must be recomputed */
     474        rtc->boot_time.tv_sec = 0;
     475        rtc->boot_time.tv_usec = 0;
    462476
    463477        /* Detect the RTC epoch */
     
    731745}
    732746
    733 static time_t
    734 uptime_get(void)
    735 {
    736         struct timeval tv;
    737 
    738         getuptime(&tv);
    739 
    740         return tv.tv_sec;
    741 }
    742 
    743747static int
    744748rtc_fun_online(ddf_fun_t *fun)
  • uspace/lib/c/generic/async.c

    rc0c38c7c r7f9d97f3  
    820820        if (usecs) {
    821821                getuptime(&conn->wdata.to_event.expires);
    822                 tv_add(&conn->wdata.to_event.expires, usecs);
     822                tv_add_diff(&conn->wdata.to_event.expires, usecs);
    823823        } else
    824824                conn->wdata.to_event.inlist = false;
     
    12141214
    12151215                        } else {
    1216                                 timeout = tv_sub(&waiter->to_event.expires, &tv);
     1216                                timeout = tv_sub_diff(&waiter->to_event.expires,
     1217                                    &tv);
    12171218                                futex_up(&async_futex);
    12181219                        }
     
    15051506
    15061507        getuptime(&msg->wdata.to_event.expires);
    1507         tv_add(&msg->wdata.to_event.expires, timeout);
     1508        tv_add_diff(&msg->wdata.to_event.expires, timeout);
    15081509       
    15091510        /*
     
    15871588       
    15881589        getuptime(&msg->wdata.to_event.expires);
    1589         tv_add(&msg->wdata.to_event.expires, timeout);
     1590        tv_add_diff(&msg->wdata.to_event.expires, timeout);
    15901591       
    15911592        futex_down(&async_futex);
  • uspace/lib/c/generic/fibril_synch.c

    rc0c38c7c r7f9d97f3  
    380380        if (timeout) {
    381381                getuptime(&wdata.to_event.expires);
    382                 tv_add(&wdata.to_event.expires, timeout);
     382                tv_add_diff(&wdata.to_event.expires, timeout);
    383383                async_insert_timeout(&wdata);
    384384        }
  • uspace/lib/c/generic/io/console.c

    rc0c38c7c r7f9d97f3  
    259259        struct timeval t1;
    260260        gettimeofday(&t1, NULL);
    261         *timeout -= tv_sub(&t1, &t0);
     261        *timeout -= tv_sub_diff(&t1, &t0);
    262262       
    263263        return true;
  • 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
  • uspace/lib/c/include/sys/time.h

    rc0c38c7c r7f9d97f3  
    5050
    5151struct tm {
     52        int tm_usec;   /* Microseconds [0,999999]. */
    5253        int tm_sec;    /* Seconds [0,60]. */
    5354        int tm_min;    /* Minutes [0,59]. */
     
    7172};
    7273
    73 extern void tv_add(struct timeval *, suseconds_t);
    74 extern suseconds_t tv_sub(struct timeval *, struct timeval *);
     74extern void tv_add_diff(struct timeval *, suseconds_t);
     75extern void tv_add(struct timeval *, struct timeval *);
     76extern suseconds_t tv_sub_diff(struct timeval *, struct timeval *);
     77extern void tv_sub(struct timeval *, struct timeval *);
    7578extern int tv_gt(struct timeval *, struct timeval *);
    7679extern int tv_gteq(struct timeval *, struct timeval *);
     
    8588extern int time_utc2str(const time_t, char *);
    8689extern void time_tm2str(const struct tm *, char *);
     90extern int time_tv2tm(const struct timeval *, struct tm *);
    8791extern int time_local2tm(const time_t, struct tm *);
    8892extern int time_local2str(const time_t, char *);
  • uspace/lib/usbdev/src/hub.c

    rc0c38c7c r7f9d97f3  
    229229         * above might use much of this time so we should only wait to fill
    230230         * up the 100ms quota*/
    231         const suseconds_t elapsed = tv_sub(&end_time, &start_time);
     231        const suseconds_t elapsed = tv_sub_diff(&end_time, &start_time);
    232232        if (elapsed < 100000) {
    233233                async_usleep(100000 - elapsed);
  • uspace/srv/audio/hound/audio_device.c

    rc0c38c7c r7f9d97f3  
    279279                        getuptime(&time2);
    280280                        log_verbose("Time to mix sources: %li\n",
    281                             tv_sub(&time2, &time1));
     281                            tv_sub_diff(&time2, &time1));
    282282                        break;
    283283                }
Note: See TracChangeset for help on using the changeset viewer.