david/ipxe
david
/
ipxe
Archived
1
0
Fork 0

Towards an RFC2988-compliant timer.

This commit is contained in:
Michael Brown 2006-08-09 15:54:17 +00:00
parent f0718d562f
commit c3a4f3c5da
2 changed files with 41 additions and 18 deletions

View File

@ -17,6 +17,8 @@ struct retry_timer {
unsigned long timeout; unsigned long timeout;
/** Start time (in ticks) */ /** Start time (in ticks) */
unsigned long start; unsigned long start;
/** Retry count */
unsigned int count;
/** Timer expired callback /** Timer expired callback
* *
* @v timer Retry timer * @v timer Retry timer

View File

@ -29,6 +29,11 @@
* *
* A retry timer is a binary exponential backoff timer. It can be * A retry timer is a binary exponential backoff timer. It can be
* used to build automatic retransmission into network protocols. * 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 */ /** Default timeout value */
@ -94,14 +99,41 @@ void stop_timer ( struct retry_timer *timer ) {
* t := ( 7 t / 8 ) + ( r / 2 ) * t := ( 7 t / 8 ) + ( r / 2 )
* *
*/ */
timer->timeout -= ( timer->timeout >> 3 ); if ( timer->count ) {
timer->timeout += ( runtime >> 1 ); timer->count--;
if ( timer->timeout != old_timeout ) { } else {
DBG ( "Timer updated to %dms\n", timer->timeout -= ( timer->timeout >> 3 );
( ( 1000 * timer->timeout ) / TICKS_PER_SEC ) ); 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 * Single-step the retry timer list
* *
@ -112,22 +144,11 @@ static void retry_step ( struct process *process ) {
struct retry_timer *tmp; struct retry_timer *tmp;
unsigned long now = currticks(); unsigned long now = currticks();
unsigned long used; unsigned long used;
int fail;
list_for_each_entry_safe ( timer, tmp, &timers, list ) { list_for_each_entry_safe ( timer, tmp, &timers, list ) {
used = ( now - timer->start ); used = ( now - timer->start );
if ( used >= timer->timeout ) { if ( used >= timer->timeout )
/* Stop timer without performing RTT calculations */ timer_expired ( timer );
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 );
}
} }
schedule ( process ); schedule ( process );