diff options
author | Michael Brown | 2006-08-09 17:54:17 +0200 |
---|---|---|
committer | Michael Brown | 2006-08-09 17:54:17 +0200 |
commit | c3a4f3c5da967b08c402c5ea7bb24dfd420d0feb (patch) | |
tree | 862dfd436bc28c76fb445d154d2ac0e8847642a9 /src/net/retry.c | |
parent | Don't call stop_timer() from within the timer expiry callback; it's (diff) | |
download | ipxe-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.c | 57 |
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 ); |