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>