summaryrefslogtreecommitdiffstats
path: root/src/net/retry.c
diff options
context:
space:
mode:
authorMichael Brown2006-08-09 17:54:17 +0200
committerMichael Brown2006-08-09 17:54:17 +0200
commitc3a4f3c5da967b08c402c5ea7bb24dfd420d0feb (patch)
tree862dfd436bc28c76fb445d154d2ac0e8847642a9 /src/net/retry.c
parentDon't call stop_timer() from within the timer expiry callback; it's (diff)
downloadipxe-c3a4f3c5da967b08c402c5ea7bb24dfd420d0feb.tar.gz
ipxe-c3a4f3c5da967b08c402c5ea7bb24dfd420d0feb.tar.xz
ipxe-c3a4f3c5da967b08c402c5ea7bb24dfd420d0feb.zip
Towards an RFC2988-compliant timer.
Diffstat (limited to 'src/net/retry.c')
-rw-r--r--src/net/retry.c57
1 files changed, 39 insertions, 18 deletions
diff --git a/src/net/retry.c b/src/net/retry.c
index 531a1b95..07b4af4c 100644
--- a/src/net/retry.c
+++ b/src/net/retry.c
@@ -29,6 +29,11 @@
*
* A retry timer is a binary exponential backoff timer. It can be
* used to build automatic retransmission into network protocols.
+ *
+ * This implementation of the timer is designed to satisfy RFC 2988
+ * and therefore be usable as a TCP retransmission timer.
+ *
+ *
*/
/** Default timeout value */
@@ -94,15 +99,42 @@ void stop_timer ( struct retry_timer *timer ) {
* t := ( 7 t / 8 ) + ( r / 2 )
*
*/
- timer->timeout -= ( timer->timeout >> 3 );
- timer->timeout += ( runtime >> 1 );
- if ( timer->timeout != old_timeout ) {
- DBG ( "Timer updated to %dms\n",
- ( ( 1000 * timer->timeout ) / TICKS_PER_SEC ) );
+ if ( timer->count ) {
+ timer->count--;
+ } else {
+ timer->timeout -= ( timer->timeout >> 3 );
+ timer->timeout += ( runtime >> 1 );
+ if ( timer->timeout != old_timeout ) {
+ DBG ( "Timer updated to %dms\n",
+ ( ( 1000 * timer->timeout ) / TICKS_PER_SEC ) );
+ }
}
}
/**
+ * Handle expired timer
+ *
+ * @v timer Retry timer
+ */
+static void timer_expired ( struct retry_timer *timer ) {
+ int fail;
+
+ /* Stop timer without performing RTT calculations */
+ list_del ( &timer->list );
+ timer->count++;
+
+ /* Back off the timeout value */
+ timer->timeout <<= 1;
+ if ( ( fail = ( timer->timeout > MAX_TIMEOUT ) ) )
+ timer->timeout = MAX_TIMEOUT;
+ DBG ( "Timer backed off to %dms\n",
+ ( ( 1000 * timer->timeout ) / TICKS_PER_SEC ) );
+
+ /* Call expiry callback */
+ timer->expired ( timer, fail );
+}
+
+/**
* Single-step the retry timer list
*
* @v process Retry timer process
@@ -112,22 +144,11 @@ static void retry_step ( struct process *process ) {
struct retry_timer *tmp;
unsigned long now = currticks();
unsigned long used;
- int fail;
list_for_each_entry_safe ( timer, tmp, &timers, list ) {
used = ( now - timer->start );
- if ( used >= timer->timeout ) {
- /* Stop timer without performing RTT calculations */
- list_del ( &timer->list );
- /* Back off the timeout value */
- timer->timeout <<= 1;
- if ( ( fail = ( timer->timeout > MAX_TIMEOUT ) ) )
- timer->timeout = MAX_TIMEOUT;
- DBG ( "Timer backed off to %dms\n",
- ( ( 1000 * timer->timeout ) / TICKS_PER_SEC ) );
- /* Call expiry callback */
- timer->expired ( timer, fail );
- }
+ if ( used >= timer->timeout )
+ timer_expired ( timer );
}
schedule ( process );