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

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"
1.1.1.2   misho      34: #include "iperf_time.h"
1.1       misho      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
1.1.1.2   misho      44: ** current time get passed a pointer to a struct iperf_time.  If it's non-NULL
                     45: ** it gets used, otherwise we do our own iperf_time_now() to fill it in.
                     46: ** This lets the caller avoid extraneous iperf_time_now()s when efficiency
1.1       misho      47: ** is needed, and not bother with the extra code when efficiency doesn't
                     48: ** matter too much.
                     49: */
                     50: static void
1.1.1.2   misho      51: getnow( struct iperf_time* nowP, struct iperf_time* nowP2 )
1.1       misho      52: {
                     53:     if ( nowP != NULL )
                     54:        *nowP2 = *nowP;
                     55:     else
1.1.1.2   misho      56:        iperf_time_now(nowP2);
1.1       misho      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 {
1.1.1.2   misho      71:        if (iperf_time_compare(&t->time, &timers->time) < 0) {
1.1       misho      72:            /* The new timer goes at the head of the list. */
                     73:            t->prev = NULL;
                     74:            t->next = timers;
                     75:            timers->prev = t;
                     76:            timers = t;
                     77:        } else {
                     78:            /* Walk the list to find the insertion point. */
                     79:            for ( t2prev = timers, t2 = timers->next; t2 != NULL;
                     80:                  t2prev = t2, t2 = t2->next ) {
1.1.1.2   misho      81:                if (iperf_time_compare(&t->time, &t2->time) < 0) {
1.1       misho      82:                    /* Found it. */
                     83:                    t2prev->next = t;
                     84:                    t->prev = t2prev;
                     85:                    t->next = t2;
                     86:                    t2->prev = t;
                     87:                    return;
                     88:                }
                     89:            }
                     90:            /* Oops, got to the end of the list.  Add to tail. */
                     91:            t2prev->next = t;
                     92:            t->prev = t2prev;
                     93:            t->next = NULL;
                     94:        }
                     95:     }
                     96: }
                     97: 
                     98: 
                     99: static void
                    100: list_remove( Timer* t )
                    101: {
                    102:     if ( t->prev == NULL )
                    103:        timers = t->next;
                    104:     else
                    105:        t->prev->next = t->next;
                    106:     if ( t->next != NULL )
                    107:        t->next->prev = t->prev;
                    108: }
                    109: 
                    110: 
                    111: static void
                    112: list_resort( Timer* t )
                    113: {
                    114:     /* Remove the timer from the list. */
                    115:     list_remove( t );
                    116:     /* And add it back in, sorted correctly. */
                    117:     list_add( t );
                    118: }
                    119: 
                    120: 
                    121: Timer*
                    122: tmr_create(
1.1.1.2   misho     123:     struct iperf_time* nowP, TimerProc* timer_proc, TimerClientData client_data,
1.1       misho     124:     int64_t usecs, int periodic )
                    125: {
1.1.1.2   misho     126:     struct iperf_time now;
1.1       misho     127:     Timer* t;
                    128: 
                    129:     getnow( nowP, &now );
                    130: 
                    131:     if ( free_timers != NULL ) {
                    132:        t = free_timers;
                    133:        free_timers = t->next;
                    134:     } else {
                    135:        t = (Timer*) malloc( sizeof(Timer) );
                    136:        if ( t == NULL )
                    137:            return NULL;
                    138:     }
                    139: 
                    140:     t->timer_proc = timer_proc;
                    141:     t->client_data = client_data;
                    142:     t->usecs = usecs;
                    143:     t->periodic = periodic;
                    144:     t->time = now;
1.1.1.2   misho     145:     iperf_time_add_usecs(&t->time, usecs);
1.1       misho     146:     /* Add the new timer to the active list. */
                    147:     list_add( t );
                    148: 
                    149:     return t;
                    150: }
                    151: 
                    152: 
                    153: struct timeval*
1.1.1.2   misho     154: tmr_timeout( struct iperf_time* nowP )
1.1       misho     155: {
1.1.1.2   misho     156:     struct iperf_time now, diff;
1.1       misho     157:     int64_t usecs;
1.1.1.2   misho     158:     int past;
1.1       misho     159:     static struct timeval timeout;
                    160: 
                    161:     getnow( nowP, &now );
                    162:     /* Since the list is sorted, we only need to look at the first timer. */
                    163:     if ( timers == NULL )
                    164:        return NULL;
1.1.1.2   misho     165:     past = iperf_time_diff(&timers->time, &now, &diff);
                    166:     if (past)
                    167:         usecs = 0;
                    168:     else
                    169:         usecs = iperf_time_in_usecs(&diff);
1.1       misho     170:     timeout.tv_sec = usecs / 1000000LL;
                    171:     timeout.tv_usec = usecs % 1000000LL;
                    172:     return &timeout;
                    173: }
                    174: 
                    175: 
                    176: void
1.1.1.2   misho     177: tmr_run( struct iperf_time* nowP )
1.1       misho     178: {
1.1.1.2   misho     179:     struct iperf_time now;
1.1       misho     180:     Timer* t;
                    181:     Timer* next;
                    182: 
                    183:     getnow( nowP, &now );
                    184:     for ( t = timers; t != NULL; t = next ) {
                    185:        next = t->next;
                    186:        /* Since the list is sorted, as soon as we find a timer
                    187:        ** that isn't ready yet, we are done.
                    188:        */
1.1.1.2   misho     189:        if (iperf_time_compare(&t->time, &now) > 0)
1.1       misho     190:            break;
                    191:        (t->timer_proc)( t->client_data, &now );
                    192:        if ( t->periodic ) {
                    193:            /* Reschedule. */
1.1.1.2   misho     194:            iperf_time_add_usecs(&t->time, t->usecs);
1.1       misho     195:            list_resort( t );
                    196:        } else
                    197:            tmr_cancel( t );
                    198:     }
                    199: }
                    200: 
                    201: 
                    202: void
1.1.1.2   misho     203: tmr_reset( struct iperf_time* nowP, Timer* t )
1.1       misho     204: {
1.1.1.2   misho     205:     struct iperf_time now;
1.1.1.3 ! misho     206: 
1.1       misho     207:     getnow( nowP, &now );
                    208:     t->time = now;
1.1.1.2   misho     209:     iperf_time_add_usecs( &t->time, t->usecs );
1.1       misho     210:     list_resort( t );
                    211: }
                    212: 
                    213: 
                    214: void
                    215: tmr_cancel( Timer* t )
                    216: {
                    217:     /* Remove it from the active list. */
                    218:     list_remove( t );
                    219:     /* And put it on the free list. */
                    220:     t->next = free_timers;
                    221:     free_timers = t;
                    222:     t->prev = NULL;
                    223: }
                    224: 
                    225: 
                    226: void
                    227: tmr_cleanup( void )
                    228: {
                    229:     Timer* t;
                    230: 
                    231:     while ( free_timers != NULL ) {
                    232:        t = free_timers;
                    233:        free_timers = t->next;
                    234:        free( (void*) t );
                    235:     }
                    236: }
                    237: 
                    238: 
                    239: void
                    240: tmr_destroy( void )
                    241: {
                    242:     while ( timers != NULL )
                    243:        tmr_cancel( timers );
                    244:     tmr_cleanup();
                    245: }

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