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>