|
@@ -15,9 +15,13 @@
|
15
|
15
|
* along with this program; if not, write to the Free Software
|
16
|
16
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
17
|
17
|
* 02110-1301, USA.
|
|
18
|
+ *
|
|
19
|
+ * You can also choose to distribute this program under the terms of
|
|
20
|
+ * the Unmodified Binary Distribution Licence (as given in the file
|
|
21
|
+ * COPYING.UBDL), provided that you have satisfied its requirements.
|
18
|
22
|
*/
|
19
|
23
|
|
20
|
|
-FILE_LICENCE ( GPL2_OR_LATER );
|
|
24
|
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
21
|
25
|
|
22
|
26
|
#include <stddef.h>
|
23
|
27
|
#include <ipxe/timer.h>
|
|
@@ -35,7 +39,6 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
35
|
39
|
*
|
36
|
40
|
* This implementation of the timer is designed to satisfy RFC 2988
|
37
|
41
|
* and therefore be usable as a TCP retransmission timer.
|
38
|
|
- *
|
39
|
42
|
*
|
40
|
43
|
*/
|
41
|
44
|
|
|
@@ -49,47 +52,59 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
49
|
52
|
static LIST_HEAD ( timers );
|
50
|
53
|
|
51
|
54
|
/**
|
52
|
|
- * Start timer
|
|
55
|
+ * Start timer with a specified timeout
|
53
|
56
|
*
|
54
|
57
|
* @v timer Retry timer
|
|
58
|
+ * @v timeout Timeout, in ticks
|
55
|
59
|
*
|
56
|
|
- * This starts the timer running with the current timeout value. If
|
|
60
|
+ * This starts the timer running with the specified timeout value. If
|
57
|
61
|
* stop_timer() is not called before the timer expires, the timer will
|
58
|
62
|
* be stopped and the timer's callback function will be called.
|
59
|
63
|
*/
|
60
|
|
-void start_timer ( struct retry_timer *timer ) {
|
|
64
|
+void start_timer_fixed ( struct retry_timer *timer, unsigned long timeout ) {
|
|
65
|
+
|
|
66
|
+ /* Add to list of running timers (if applicable) */
|
61
|
67
|
if ( ! timer->running ) {
|
62
|
68
|
list_add ( &timer->list, &timers );
|
63
|
69
|
ref_get ( timer->refcnt );
|
|
70
|
+ timer->running = 1;
|
64
|
71
|
}
|
|
72
|
+
|
|
73
|
+ /* Record start time */
|
65
|
74
|
timer->start = currticks();
|
66
|
|
- timer->running = 1;
|
67
|
|
-
|
68
|
|
- /* 0 means "use default timeout" */
|
69
|
|
- if ( timer->min_timeout == 0 )
|
70
|
|
- timer->min_timeout = DEFAULT_MIN_TIMEOUT;
|
71
|
|
- /* We must never be less than MIN_TIMEOUT under any circumstances */
|
72
|
|
- if ( timer->min_timeout < MIN_TIMEOUT )
|
73
|
|
- timer->min_timeout = MIN_TIMEOUT;
|
74
|
|
- /* Honor user-specified minimum timeout */
|
75
|
|
- if ( timer->timeout < timer->min_timeout )
|
76
|
|
- timer->timeout = timer->min_timeout;
|
|
75
|
+
|
|
76
|
+ /* Record timeout */
|
|
77
|
+ timer->timeout = timeout;
|
77
|
78
|
|
78
|
79
|
DBG2 ( "Timer %p started at time %ld (expires at %ld)\n",
|
79
|
80
|
timer, timer->start, ( timer->start + timer->timeout ) );
|
80
|
81
|
}
|
81
|
82
|
|
82
|
83
|
/**
|
83
|
|
- * Start timer with a specified fixed timeout
|
|
84
|
+ * Start timer
|
84
|
85
|
*
|
85
|
86
|
* @v timer Retry timer
|
86
|
|
- * @v timeout Timeout, in ticks
|
|
87
|
+ *
|
|
88
|
+ * This starts the timer running with the current timeout value
|
|
89
|
+ * (rounded up to the minimum timeout value). If stop_timer() is not
|
|
90
|
+ * called before the timer expires, the timer will be stopped and the
|
|
91
|
+ * timer's callback function will be called.
|
87
|
92
|
*/
|
88
|
|
-void start_timer_fixed ( struct retry_timer *timer, unsigned long timeout ) {
|
89
|
|
- start_timer ( timer );
|
90
|
|
- timer->timeout = timeout;
|
91
|
|
- DBG2 ( "Timer %p expiry time changed to %ld\n",
|
92
|
|
- timer, ( timer->start + timer->timeout ) );
|
|
93
|
+void start_timer ( struct retry_timer *timer ) {
|
|
94
|
+ unsigned long timeout = timer->timeout;
|
|
95
|
+ unsigned long min;
|
|
96
|
+
|
|
97
|
+ /* Calculate minimum timeout */
|
|
98
|
+ min = ( timer->min ? timer->min : DEFAULT_MIN_TIMEOUT );
|
|
99
|
+ if ( min < MIN_TIMEOUT )
|
|
100
|
+ min = MIN_TIMEOUT;
|
|
101
|
+
|
|
102
|
+ /* Ensure timeout is at least the minimum */
|
|
103
|
+ if ( timeout < min )
|
|
104
|
+ timeout = min;
|
|
105
|
+
|
|
106
|
+ /* Start timer with this timeout */
|
|
107
|
+ start_timer_fixed ( timer, timeout );
|
93
|
108
|
}
|
94
|
109
|
|
95
|
110
|
/**
|
|
@@ -150,6 +165,7 @@ void stop_timer ( struct retry_timer *timer ) {
|
150
|
165
|
*/
|
151
|
166
|
static void timer_expired ( struct retry_timer *timer ) {
|
152
|
167
|
struct refcnt *refcnt = timer->refcnt;
|
|
168
|
+ unsigned long max = ( timer->max ? timer->max : DEFAULT_MAX_TIMEOUT );
|
153
|
169
|
int fail;
|
154
|
170
|
|
155
|
171
|
/* Stop timer without performing RTT calculations */
|
|
@@ -162,10 +178,8 @@ static void timer_expired ( struct retry_timer *timer ) {
|
162
|
178
|
|
163
|
179
|
/* Back off the timeout value */
|
164
|
180
|
timer->timeout <<= 1;
|
165
|
|
- if ( timer->max_timeout == 0 ) /* 0 means "use default timeout" */
|
166
|
|
- timer->max_timeout = DEFAULT_MAX_TIMEOUT;
|
167
|
|
- if ( ( fail = ( timer->timeout > timer->max_timeout ) ) )
|
168
|
|
- timer->timeout = timer->max_timeout;
|
|
181
|
+ if ( ( fail = ( timer->timeout > max ) ) )
|
|
182
|
+ timer->timeout = max;
|
169
|
183
|
DBG ( "Timer %p timeout backed off to %ld\n",
|
170
|
184
|
timer, timer->timeout );
|
171
|
185
|
|