|
@@ -29,6 +29,11 @@
|
29
|
29
|
*
|
30
|
30
|
* A retry timer is a binary exponential backoff timer. It can be
|
31
|
31
|
* used to build automatic retransmission into network protocols.
|
|
32
|
+ *
|
|
33
|
+ * This implementation of the timer is designed to satisfy RFC 2988
|
|
34
|
+ * and therefore be usable as a TCP retransmission timer.
|
|
35
|
+ *
|
|
36
|
+ *
|
32
|
37
|
*/
|
33
|
38
|
|
34
|
39
|
/** Default timeout value */
|
|
@@ -94,14 +99,41 @@ void stop_timer ( struct retry_timer *timer ) {
|
94
|
99
|
* t := ( 7 t / 8 ) + ( r / 2 )
|
95
|
100
|
*
|
96
|
101
|
*/
|
97
|
|
- timer->timeout -= ( timer->timeout >> 3 );
|
98
|
|
- timer->timeout += ( runtime >> 1 );
|
99
|
|
- if ( timer->timeout != old_timeout ) {
|
100
|
|
- DBG ( "Timer updated to %dms\n",
|
101
|
|
- ( ( 1000 * timer->timeout ) / TICKS_PER_SEC ) );
|
|
102
|
+ if ( timer->count ) {
|
|
103
|
+ timer->count--;
|
|
104
|
+ } else {
|
|
105
|
+ timer->timeout -= ( timer->timeout >> 3 );
|
|
106
|
+ timer->timeout += ( runtime >> 1 );
|
|
107
|
+ if ( timer->timeout != old_timeout ) {
|
|
108
|
+ DBG ( "Timer updated to %dms\n",
|
|
109
|
+ ( ( 1000 * timer->timeout ) / TICKS_PER_SEC ) );
|
|
110
|
+ }
|
102
|
111
|
}
|
103
|
112
|
}
|
104
|
113
|
|
|
114
|
+/**
|
|
115
|
+ * Handle expired timer
|
|
116
|
+ *
|
|
117
|
+ * @v timer Retry timer
|
|
118
|
+ */
|
|
119
|
+static void timer_expired ( struct retry_timer *timer ) {
|
|
120
|
+ int fail;
|
|
121
|
+
|
|
122
|
+ /* Stop timer without performing RTT calculations */
|
|
123
|
+ list_del ( &timer->list );
|
|
124
|
+ timer->count++;
|
|
125
|
+
|
|
126
|
+ /* Back off the timeout value */
|
|
127
|
+ timer->timeout <<= 1;
|
|
128
|
+ if ( ( fail = ( timer->timeout > MAX_TIMEOUT ) ) )
|
|
129
|
+ timer->timeout = MAX_TIMEOUT;
|
|
130
|
+ DBG ( "Timer backed off to %dms\n",
|
|
131
|
+ ( ( 1000 * timer->timeout ) / TICKS_PER_SEC ) );
|
|
132
|
+
|
|
133
|
+ /* Call expiry callback */
|
|
134
|
+ timer->expired ( timer, fail );
|
|
135
|
+}
|
|
136
|
+
|
105
|
137
|
/**
|
106
|
138
|
* Single-step the retry timer list
|
107
|
139
|
*
|
|
@@ -112,22 +144,11 @@ static void retry_step ( struct process *process ) {
|
112
|
144
|
struct retry_timer *tmp;
|
113
|
145
|
unsigned long now = currticks();
|
114
|
146
|
unsigned long used;
|
115
|
|
- int fail;
|
116
|
147
|
|
117
|
148
|
list_for_each_entry_safe ( timer, tmp, &timers, list ) {
|
118
|
149
|
used = ( now - timer->start );
|
119
|
|
- if ( used >= timer->timeout ) {
|
120
|
|
- /* Stop timer without performing RTT calculations */
|
121
|
|
- list_del ( &timer->list );
|
122
|
|
- /* Back off the timeout value */
|
123
|
|
- timer->timeout <<= 1;
|
124
|
|
- if ( ( fail = ( timer->timeout > MAX_TIMEOUT ) ) )
|
125
|
|
- timer->timeout = MAX_TIMEOUT;
|
126
|
|
- DBG ( "Timer backed off to %dms\n",
|
127
|
|
- ( ( 1000 * timer->timeout ) / TICKS_PER_SEC ) );
|
128
|
|
- /* Call expiry callback */
|
129
|
|
- timer->expired ( timer, fail );
|
130
|
|
- }
|
|
150
|
+ if ( used >= timer->timeout )
|
|
151
|
+ timer_expired ( timer );
|
131
|
152
|
}
|
132
|
153
|
|
133
|
154
|
schedule ( process );
|