Changeset 1971

Show
Ignore:
Timestamp:
04/09/08 15:37:35 (8 months ago)
Author:
aturner
Message:

switch to timespec (nanosecond precision) for sleeping. OS X's AbsoluteTime?
methods are really damn accurate! refs #41

Location:
features/performance/src
Files:
6 modified

Legend:

Unmodified
Added
Removed
  • features/performance/src/common/rdtsc.h

    r1970 r1971  
    106106 */ 
    107107static inline void 
    108 rdtsc_sleep(const struct timeval sleep) 
     108rdtsc_sleep(const struct timespec sleep) 
    109109{ 
    110110    u_int64_t sleep_until; 
     
    115115    clicks_per_usec = clicks_per_usec > 0 ? clicks_per_usec : rdtsc_calibrate(0); 
    116116     
    117     sleep_until += clicks_per_usec * TIMEVAL_TO_MICROSEC(&sleep); 
     117    sleep_until += clicks_per_usec * TIMESPEC_TO_MICROSEC(&sleep); 
    118118     
    119119    while (now < sleep_until) 
  • features/performance/src/common/timer.c

    r1970 r1971  
    5454    tvp->tv_usec = interval - (tvp->tv_sec * 1000000); 
    5555} 
     56 
     57/* Divide tvs by div, storing the result in tvs */ 
     58void timesdiv(struct timespec *tvs, float div) 
     59{ 
     60    double interval; 
     61     
     62    if (div == 0 || div == 1) 
     63        return; 
     64         
     65    interval = ((double)tvs->tv_sec * 1000000000 + tvs->tv_nsec) / (double)div; 
     66    tvs->tv_sec = interval / (int)1000000000; 
     67    tvs->tv_nsec = interval - (tvs->tv_nsec * 1000000000); 
     68} 
     69 
  • features/performance/src/common/timer.h

    r1970 r1971  
    5252 
    5353void timerdiv(struct timeval *tvp, float div); 
     54void timesdiv(struct timespec *tvs, float div); 
    5455 
    5556/* convert float time to struct timeval *tvp */ 
     
    6970#endif 
    7071 
     72#ifndef TIMESPEC_TO_TIMEVAL 
     73#define TIMESPEC_TO_TIMEVAL(tv, ts) {           \ 
     74    (tv)->tv_sec = (ts)->tv_sec;                \ 
     75    (tv)->tv_usec = (ts)->tv_nsec / 1000; } 
     76#endif 
     77 
    7178/* zero out a timer */ 
    7279#ifndef timerclear 
    7380#define timerclear(tvp)         (tvp)->tv_sec = (tvp)->tv_usec = 0 
     81#endif 
     82 
     83/* zero out a timespec */ 
     84#ifndef timesclear 
     85#define timesclear(tvs)     (tvs)->tv_sec = (tvs)->tv_nsec = 0 
    7486#endif 
    7587 
     
    7890#define timerisset(tvp)         ((tvp)->tv_sec || (tvp)->tv_usec) 
    7991#endif 
     92 
     93/* is timespec non-zero? */ 
     94#ifndef timesisset 
     95#define timesisset(tvs)         ((tvs)->tv_sec || (tvs)->tv_nsec) 
     96#endif 
     97 
    8098 
    8199/* add tvp and uvp and store in vvp */ 
     
    105123#endif 
    106124 
     125#ifndef timessub 
     126#define timessub(tsp, usp, vsp)                                 \ 
     127        do {                                                                    \ 
     128                (vsp)->tv_sec = (tsp)->tv_sec - (usp)->tv_sec;          \ 
     129                (vsp)->tv_nsec = (tsp)->tv_nsec - (usp)->tv_nsec;       \ 
     130                if ((vsp)->tv_nsec < 0) {                               \ 
     131                        (vsp)->tv_sec--;                                    \ 
     132                        (vsp)->tv_nsec += 1000000000;           \ 
     133                }                                                                   \ 
     134        } while (0) 
     135#endif 
     136 
    107137/* compare tvp and uvp using cmp */ 
    108138#ifndef timercmp 
     
    111141        ((tvp)->tv_usec cmp (uvp)->tv_usec) :           \ 
    112142        ((tvp)->tv_sec cmp (uvp)->tv_sec)) 
     143#endif 
     144 
     145#ifndef timescmp 
     146#define timescmp(tsp, usp, cmp)                             \ 
     147        (((tsp)->tv_sec == (usp)->tv_sec) ?                 \ 
     148        ((tsp)->tv_nsec cmp (usp)->tv_nsec) :           \ 
     149        ((tsp)->tv_sec cmp (usp)->tv_sec)) 
    113150#endif 
    114151 
  • features/performance/src/defines.h.in

    r1970 r1971  
    218218#define MILLISEC_TO_TIMEVAL(x, tv)          \ 
    219219    do {                                    \ 
    220         (tv)->tv_sec = x / 1000;            \ 
     220        (tv)->tv_sec = (x) / 1000;            \ 
    221221        (tv)->tv_usec = (x * 1000) - ((tv)->tv_sec * 1000000);   \ 
    222222    } while(0) 
     
    224224#define MICROSEC_TO_TIMEVAL(x, tv)          \ 
    225225    do {                                    \ 
    226         (tv)->tv_sec = x / 1000000;         \ 
    227         (tv)->tv_usec = x - ((tv)->tv_sec * 1000000);   \ 
     226        (tv)->tv_sec = (x) / 1000000;         \ 
     227        (tv)->tv_usec = (x) - ((tv)->tv_sec * 1000000);   \ 
    228228    } while(0) 
    229229 
    230230#define NANOSEC_TO_TIMEVAL(x, tv)           \ 
    231231    do {                                    \ 
    232         (tv)->tv_sec = x / 1000000000;      \ 
     232        (tv)->tv_sec = (x) / 1000000000;      \ 
    233233        (tv)->tv_usec = (x / 1000) - (tv)->tv_sec * 1000000);   \ 
    234234    } while(0) 
    235235 
     236#define NANOSEC_TO_TIMESPEC(x, ts)          \ 
     237    do {                                    \ 
     238        (ts)->tv_sec = (x) / 1000000000;      \ 
     239        (ts)->tv_nsec = (x) - ((ts)->tv_sec * 1000000000);   \ 
     240    } while(0) 
     241 
     242#define TIMESPEC_TO_MILLISEC(x)  (((x)->tv_sec * 1000) + ((x)->tv_nsec / 1000000)) 
     243#define TIMESPEC_TO_MICROSEC(x)  (((x)->tv_sec * 1000000) + (x)->tv_nsec / 1000) 
     244#define TIMESPEC_TO_NANOSEC(x) ((u_int64_t)((x)->tv_sec * 1000000000) + ((u_int64_t)(x)->tv_nsec)) 
     245 
     246 
     247 
    236248#endif /* DEFINES */ 
  • features/performance/src/send_packets.c

    r1970 r1971  
    327327    static int adjuster_flipper = 0; 
    328328#ifdef HAVE_TCPREPLAY 
    329     struct timeval adjuster = { 0, OPT_VALUE_SLEEP_ACCEL } 
     329    struct timespec adjuster = { 0, OPT_VALUE_SLEEP_ACCEL * 1000 } 
    330330#else 
    331     struct timeval adjuster = { 0, ADJUSTER_OFFSET }; 
    332 #endif 
    333     static struct timeval nap = { 0, 0 }; 
     331    struct timespec adjuster = { 0, ADJUSTER_OFFSET * 1000 }; 
     332#endif 
     333    static struct timespec nap = { 0, 0 }; 
    334334    static u_int32_t double_up = 0; 
    335     struct timeval now, sleep_until, nap_this_time; 
    336     struct timespec ignore, sleep; 
     335    struct timeval nap_for, now, sleep_until; 
     336    struct timespec ignore, sleep, nap_this_time; 
    337337    float n; 
    338338    static u_int32_t send = 0;      /* accellerator.   # of packets to send w/o sleeping */ 
    339     u_int32_t ppusec; /* packets per usec */ 
     339    u_int64_t ppnsec; /* packets per usec */ 
    340340     
    341341    /* just return if topspeed */ 
     
    373373         */ 
    374374        if (timerisset(last) && timercmp(time, last, >)) { 
    375             timersub(time, last, &nap); 
    376             timerdiv(&nap, options.speed.speed); 
     375            timersub(time, last, &nap_for); 
     376            TIMEVAL_TO_TIMESPEC(&nap_for, &nap); 
     377            timesdiv(&nap, options.speed.speed); 
    377378        } 
    378379        else { 
     
    382383             * last packet. 
    383384             */ 
    384             timerclear(&nap); 
     385            timesclear(&nap); 
    385386        } 
    386387        break; 
     
    394395            n = (float)len / (options.speed.speed * 1024 * 1024 / 8); /* convert Mbps to bps */ 
    395396            nap.tv_sec = n; 
    396             nap.tv_usec = (n - nap.tv_sec)  * 1000000; 
     397            nap.tv_nsec = (n - nap.tv_sec)  * 1000000000; 
    397398            dbgx(3, "packet size %d\t\tequals %f bps\t\tnap " TIMEVAL_FORMAT, len, n,  
    398                 nap.tv_sec, nap.tv_usec); 
     399                nap.tv_sec, nap.tv_nsec); 
    399400        } 
    400401        else { 
    401402            /* don't sleep at all for the first packet */ 
    402             timerclear(&nap); 
     403            timesclear(&nap); 
    403404        } 
    404405        break; 
     
    406407    case SPEED_PACKETRATE: 
    407408        /* only need to calculate this the first time */ 
    408         if (! timerisset(&nap)) { 
     409        if (! timesisset(&nap)) { 
    409410            /* run in packets/sec */ 
    410             ppusec = 1000000 / options.speed.speed; 
    411             MICROSEC_TO_TIMEVAL(ppusec, &nap); 
    412             dbgx(1, "sending 1 packet per %lu usec", nap.tv_usec); 
     411            ppnsec = 1000000000 / options.speed.speed; 
     412            NANOSEC_TO_TIMESPEC(ppnsec, &nap); 
     413            dbgx(1, "sending 1 packet per %lu nsec", nap.tv_nsec); 
    413414        } 
    414415        break; 
     
    439440     */ 
    440441    nap_this_time.tv_sec = nap.tv_sec; 
    441     nap_this_time.tv_usec = nap.tv_usec; 
     442    nap_this_time.tv_nsec = nap.tv_nsec; 
    442443 
    443444    /* apply the adjuster... */ 
    444     if (timerisset(&adjuster)) { 
    445         if (timercmp(&nap_this_time, &adjuster, >)) { 
    446             timersub(&nap_this_time, &adjuster, &nap_this_time); 
    447             dbgx(1, "adjusting nap_this_time by %lu usec", adjuster.tv_usec); 
     445    if (timesisset(&adjuster)) { 
     446        if (timescmp(&nap_this_time, &adjuster, >)) { 
     447            timessub(&nap_this_time, &adjuster, &nap_this_time); 
     448            dbgx(1, "adjusting nap_this_time by %lu nsec", adjuster.tv_nsec); 
    448449        } else {  
    449450            dbg(1, "resetting nap_this_time to 0"); 
    450             timerclear(&nap_this_time); 
     451            timesclear(&nap_this_time); 
    451452        } 
    452453    } 
    453454     
    454455    /* don't sleep if nap = { 0, 0} */ 
    455     if (!timerisset(&nap_this_time)) 
     456    if (!timesisset(&nap_this_time)) 
    456457        return; 
    457458 
  • features/performance/src/sleep.h

    r1970 r1971  
    5757 
    5858static inline void 
    59 nanosleep_sleep(struct timeval nap) 
     59nanosleep_sleep(struct timespec nap) 
    6060{ 
    61     struct timespec ts; 
    62     TIMEVAL_TO_TIMESPEC(&nap, &ts); 
    63     nanosleep(&ts, NULL); 
     61    nanosleep(&nap, NULL); 
    6462} 
    6563 
     
    7068 */ 
    7169static inline void 
    72 gettimeofday_sleep(struct timeval nap) 
     70gettimeofday_sleep(struct timespec nap) 
    7371{ 
    74     struct timeval now, sleep_until; 
     72    struct timeval now, sleep_until, nap_for; 
    7573    gettimeofday(&now, NULL); 
    76     timeradd(&now, &nap, &sleep_until); 
     74    TIMESPEC_TO_TIMEVAL(&nap_for, &nap); 
     75    timeradd(&now, &nap_for, &sleep_until); 
    7776     
    7877    do { 
     
    8786 
    8887 
     88/*  
     89 * Not sure if this is any better then a gettimeofday() loop, but  
     90 * in order to find out, nap needs to be a timespec (nanosec precision) 
     91 */ 
    8992static inline void 
    90 absolute_time_sleep(struct timeval nap) 
     93absolute_time_sleep(struct timespec nap) 
    9194{ 
    9295    AbsoluteTime sleep_until, naptime, time_left; 
     96    Nanoseconds nanosec; 
    9397 
    94     naptime = DurationToAbsolute(TIMEVAL_TO_MICROSEC(&nap)); 
     98    nanosec = UInt64ToUnsignedWide(TIMESPEC_TO_NANOSEC(&nap)); 
     99    naptime = NanosecondsToAbsolute(nanosec); 
    95100 
    96101    sleep_until = AddAbsoluteToAbsolute(UpTime(), naptime); 
    97      
     102 
    98103    do { 
    99104        time_left = SubAbsoluteFromAbsolute(sleep_until, UpTime()); 
     
    112117 */ 
    113118static inline void  
    114 select_sleep(const struct timeval nap) 
     119select_sleep(const struct timespec nap) 
    115120{ 
    116121    struct timeval timeout; 
    117122 
    118     timeout.tv_sec = nap.tv_sec; 
    119     timeout.tv_usec = nap.tv_usec; 
     123    TIMESPEC_TO_TIMEVAL(&timeout, &nap); 
    120124 
    121125    if (select(0, NULL, NULL, NULL, &timeout) < 0) 
     
    137141 
    138142static inline void  
    139 ioport_sleep(const struct timeval nap)  
     143ioport_sleep(const struct timespec nap)  
    140144{ 
     145    struct timeval nap_for; 
    141146    u_int32_t usec; 
    142147    time_t i; 
     148     
     149    TIMESPEC_TO_TIMEVAL(&nap_for, &nap); 
    143150     
    144151    /*  
     
    146153     * use slower 64bit integers or worry about integer overflows. 
    147154     */ 
    148     for (i = 0; i < nap.tv_sec; i ++) { 
    149         usec = SEC_TO_MICROSEC(nap.tv_sec); 
     155    for (i = 0; i < nap_for.tv_sec; i ++) { 
     156        usec = SEC_TO_MICROSEC(nap_for.tv_sec); 
    150157        while (usec > 0) { 
    151158            usec --; 
     
    155162     
    156163    /* process the usec */ 
    157     usec = nap.tv_usec; 
     164    usec = nap.tv_nsec / 1000; 
    158165    usec --; /* fudge factor for all the above */ 
    159166    while (usec > 0) {