Annotation of embedaddon/iperf/src/timer.c, revision 1.1.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>