Annotation of embedaddon/iperf/src/timer.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * iperf, Copyright (c) 2014, The Regents of the University of
        !             3:  * California, through Lawrence Berkeley National Laboratory (subject
        !             4:  * to receipt of any required approvals from the U.S. Dept. of
        !             5:  * Energy).  All rights reserved.
        !             6:  *
        !             7:  * If you have questions about your rights to use or distribute this
        !             8:  * software, please contact Berkeley Lab's Technology Transfer
        !             9:  * Department at TTD@lbl.gov.
        !            10:  *
        !            11:  * NOTICE.  This software is owned by the U.S. Department of Energy.
        !            12:  * As such, the U.S. Government has been granted for itself and others
        !            13:  * acting on its behalf a paid-up, nonexclusive, irrevocable,
        !            14:  * worldwide license in the Software to reproduce, prepare derivative
        !            15:  * works, and perform publicly and display publicly.  Beginning five
        !            16:  * (5) years after the date permission to assert copyright is obtained
        !            17:  * from the U.S. Department of Energy, and subject to any subsequent
        !            18:  * five (5) year renewals, the U.S. Government is granted for itself
        !            19:  * and others acting on its behalf a paid-up, nonexclusive,
        !            20:  * irrevocable, worldwide license in the Software to reproduce,
        !            21:  * prepare derivative works, distribute copies to the public, perform
        !            22:  * publicly and display publicly, and to permit others to do so.
        !            23:  *
        !            24:  * This code is distributed under a BSD style license, see the LICENSE
        !            25:  * file for complete information.
        !            26:  *
        !            27:  * Based on timers.c by Jef Poskanzer. Used with permission.
        !            28:  */
        !            29: 
        !            30: #include <sys/types.h>
        !            31: #include <stdlib.h>
        !            32: 
        !            33: #include "timer.h"
        !            34: 
        !            35: 
        !            36: static Timer* timers = NULL;
        !            37: static Timer* free_timers = NULL;
        !            38: 
        !            39: TimerClientData JunkClientData;
        !            40: 
        !            41: 
        !            42: 
        !            43: /* This is an efficiency tweak.  All the routines that need to know the
        !            44: ** current time get passed a pointer to a struct timeval.  If it's non-NULL
        !            45: ** it gets used, otherwise we do our own gettimeofday() to fill it in.
        !            46: ** This lets the caller avoid extraneous gettimeofday()s when efficiency
        !            47: ** is needed, and not bother with the extra code when efficiency doesn't
        !            48: ** matter too much.
        !            49: */
        !            50: static void
        !            51: getnow( struct timeval* nowP, struct timeval* nowP2 )
        !            52: {
        !            53:     if ( nowP != NULL )
        !            54:        *nowP2 = *nowP;
        !            55:     else
        !            56:        (void) gettimeofday( nowP2, NULL );
        !            57: }
        !            58: 
        !            59: 
        !            60: static void
        !            61: list_add( Timer* t )
        !            62: {
        !            63:     Timer* t2;
        !            64:     Timer* t2prev;
        !            65: 
        !            66:     if ( timers == NULL ) {
        !            67:        /* The list is empty. */
        !            68:        timers = t;
        !            69:        t->prev = t->next = NULL;
        !            70:     } else {
        !            71:        if ( t->time.tv_sec < timers->time.tv_sec ||
        !            72:             ( t->time.tv_sec == timers->time.tv_sec &&
        !            73:               t->time.tv_usec < timers->time.tv_usec ) ) {
        !            74:            /* The new timer goes at the head of the list. */
        !            75:            t->prev = NULL;
        !            76:            t->next = timers;
        !            77:            timers->prev = t;
        !            78:            timers = t;
        !            79:        } else {
        !            80:            /* Walk the list to find the insertion point. */
        !            81:            for ( t2prev = timers, t2 = timers->next; t2 != NULL;
        !            82:                  t2prev = t2, t2 = t2->next ) {
        !            83:                if ( t->time.tv_sec < t2->time.tv_sec ||
        !            84:                     ( t->time.tv_sec == t2->time.tv_sec &&
        !            85:                       t->time.tv_usec < t2->time.tv_usec ) ) {
        !            86:                    /* Found it. */
        !            87:                    t2prev->next = t;
        !            88:                    t->prev = t2prev;
        !            89:                    t->next = t2;
        !            90:                    t2->prev = t;
        !            91:                    return;
        !            92:                }
        !            93:            }
        !            94:            /* Oops, got to the end of the list.  Add to tail. */
        !            95:            t2prev->next = t;
        !            96:            t->prev = t2prev;
        !            97:            t->next = NULL;
        !            98:        }
        !            99:     }
        !           100: }
        !           101: 
        !           102: 
        !           103: static void
        !           104: list_remove( Timer* t )
        !           105: {
        !           106:     if ( t->prev == NULL )
        !           107:        timers = t->next;
        !           108:     else
        !           109:        t->prev->next = t->next;
        !           110:     if ( t->next != NULL )
        !           111:        t->next->prev = t->prev;
        !           112: }
        !           113: 
        !           114: 
        !           115: static void
        !           116: list_resort( Timer* t )
        !           117: {
        !           118:     /* Remove the timer from the list. */
        !           119:     list_remove( t );
        !           120:     /* And add it back in, sorted correctly. */
        !           121:     list_add( t );
        !           122: }
        !           123: 
        !           124: 
        !           125: static void
        !           126: add_usecs( struct timeval* t, int64_t usecs )
        !           127: {
        !           128:     t->tv_sec += usecs / 1000000L;
        !           129:     t->tv_usec += usecs % 1000000L;
        !           130:     if ( t->tv_usec >= 1000000L ) {
        !           131:        t->tv_sec += t->tv_usec / 1000000L;
        !           132:        t->tv_usec %= 1000000L;
        !           133:     }
        !           134: }
        !           135: 
        !           136: 
        !           137: Timer*
        !           138: tmr_create(
        !           139:     struct timeval* nowP, TimerProc* timer_proc, TimerClientData client_data,
        !           140:     int64_t usecs, int periodic )
        !           141: {
        !           142:     struct timeval now;
        !           143:     Timer* t;
        !           144: 
        !           145:     getnow( nowP, &now );
        !           146: 
        !           147:     if ( free_timers != NULL ) {
        !           148:        t = free_timers;
        !           149:        free_timers = t->next;
        !           150:     } else {
        !           151:        t = (Timer*) malloc( sizeof(Timer) );
        !           152:        if ( t == NULL )
        !           153:            return NULL;
        !           154:     }
        !           155: 
        !           156:     t->timer_proc = timer_proc;
        !           157:     t->client_data = client_data;
        !           158:     t->usecs = usecs;
        !           159:     t->periodic = periodic;
        !           160:     t->time = now;
        !           161:     add_usecs( &t->time, usecs );
        !           162:     /* Add the new timer to the active list. */
        !           163:     list_add( t );
        !           164: 
        !           165:     return t;
        !           166: }
        !           167: 
        !           168: 
        !           169: struct timeval*
        !           170: tmr_timeout( struct timeval* nowP )
        !           171: {
        !           172:     struct timeval now;
        !           173:     int64_t usecs;
        !           174:     static struct timeval timeout;
        !           175: 
        !           176:     getnow( nowP, &now );
        !           177:     /* Since the list is sorted, we only need to look at the first timer. */
        !           178:     if ( timers == NULL )
        !           179:        return NULL;
        !           180:     usecs = ( timers->time.tv_sec - now.tv_sec ) * 1000000LL +
        !           181:            ( timers->time.tv_usec - now.tv_usec );
        !           182:     if ( usecs <= 0 )
        !           183:        usecs = 0;
        !           184:     timeout.tv_sec = usecs / 1000000LL;
        !           185:     timeout.tv_usec = usecs % 1000000LL;
        !           186:     return &timeout;
        !           187: }
        !           188: 
        !           189: 
        !           190: void
        !           191: tmr_run( struct timeval* nowP )
        !           192: {
        !           193:     struct timeval now;
        !           194:     Timer* t;
        !           195:     Timer* next;
        !           196: 
        !           197:     getnow( nowP, &now );
        !           198:     for ( t = timers; t != NULL; t = next ) {
        !           199:        next = t->next;
        !           200:        /* Since the list is sorted, as soon as we find a timer
        !           201:        ** that isn't ready yet, we are done.
        !           202:        */
        !           203:        if ( t->time.tv_sec > now.tv_sec ||
        !           204:             ( t->time.tv_sec == now.tv_sec &&
        !           205:               t->time.tv_usec > now.tv_usec ) )
        !           206:            break;
        !           207:        (t->timer_proc)( t->client_data, &now );
        !           208:        if ( t->periodic ) {
        !           209:            /* Reschedule. */
        !           210:            add_usecs( &t->time, t->usecs );
        !           211:            list_resort( t );
        !           212:        } else
        !           213:            tmr_cancel( t );
        !           214:     }
        !           215: }
        !           216: 
        !           217: 
        !           218: void
        !           219: tmr_reset( struct timeval* nowP, Timer* t )
        !           220: {
        !           221:     struct timeval now;
        !           222:     
        !           223:     getnow( nowP, &now );
        !           224:     t->time = now;
        !           225:     add_usecs( &t->time, t->usecs );
        !           226:     list_resort( t );
        !           227: }
        !           228: 
        !           229: 
        !           230: void
        !           231: tmr_cancel( Timer* t )
        !           232: {
        !           233:     /* Remove it from the active list. */
        !           234:     list_remove( t );
        !           235:     /* And put it on the free list. */
        !           236:     t->next = free_timers;
        !           237:     free_timers = t;
        !           238:     t->prev = NULL;
        !           239: }
        !           240: 
        !           241: 
        !           242: void
        !           243: tmr_cleanup( void )
        !           244: {
        !           245:     Timer* t;
        !           246: 
        !           247:     while ( free_timers != NULL ) {
        !           248:        t = free_timers;
        !           249:        free_timers = t->next;
        !           250:        free( (void*) t );
        !           251:     }
        !           252: }
        !           253: 
        !           254: 
        !           255: void
        !           256: tmr_destroy( void )
        !           257: {
        !           258:     while ( timers != NULL )
        !           259:        tmr_cancel( timers );
        !           260:     tmr_cleanup();
        !           261: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>