*
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/list.h>
-/** Default timeout value */
+/** Default minimum timeout value (in ticks) */
#define DEFAULT_MIN_TIMEOUT ( TICKS_PER_SEC / 4 )
-/** Limit after which the timeout will be deemed permanent */
+/** Default maximum timeout value (in ticks) */
#define DEFAULT_MAX_TIMEOUT ( 10 * TICKS_PER_SEC )
/** A retry timer */
unsigned int running;
/** Timeout value (in ticks) */
unsigned long timeout;
- /** Minimum timeout value (in ticks)
+ /** Minimum timeout value (in ticks), or zero to use default
*
- * A value of zero means "use default timeout."
+ * The timeout will never be reduced below this value.
*/
- unsigned long min_timeout;
- /** Maximum timeout value before failure (in ticks)
+ unsigned long min;
+ /** Maximum timeout value (in ticks), or zero to use default
*
- * A value of zero means "use default timeout."
+ * The timeout will be deemed permanent (according to the
+ * failure indicator passed to expired()) when it exceeds this
+ * value.
*/
- unsigned long max_timeout;
+ unsigned long max;
/** Start time (in ticks) */
unsigned long start;
/** Retry count */
*
* The timer will already be stopped when this method is
* called. The failure indicator will be True if the retry
- * timeout has already exceeded @c MAX_TIMEOUT.
+ * timeout has already exceeded @c max_timeout.
*/
void ( * expired ) ( struct retry_timer *timer, int over );
/** Reference counter
return ( timer->running );
}
+/**
+ * Set minimum and maximum timeouts
+ *
+ * @v timer Retry timer
+ * @v min Minimum timeout (in ticks), or zero to use default
+ * @v max Maximum timeout (in ticks), or zero to use default
+ */
+static inline __attribute__ (( always_inline )) void
+set_timer_limits ( struct retry_timer *timer, unsigned long min,
+ unsigned long max ) {
+ timer->min = min;
+ timer->max = max;
+}
+
#endif /* _IPXE_RETRY_H */
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <stddef.h>
#include <ipxe/timer.h>
*
* This implementation of the timer is designed to satisfy RFC 2988
* and therefore be usable as a TCP retransmission timer.
- *
*
*/
static LIST_HEAD ( timers );
/**
- * Start timer
+ * Start timer with a specified timeout
*
* @v timer Retry timer
+ * @v timeout Timeout, in ticks
*
- * This starts the timer running with the current timeout value. If
+ * This starts the timer running with the specified timeout value. If
* stop_timer() is not called before the timer expires, the timer will
* be stopped and the timer's callback function will be called.
*/
-void start_timer ( struct retry_timer *timer ) {
+void start_timer_fixed ( struct retry_timer *timer, unsigned long timeout ) {
+
+ /* Add to list of running timers (if applicable) */
if ( ! timer->running ) {
list_add ( &timer->list, &timers );
ref_get ( timer->refcnt );
+ timer->running = 1;
}
+
+ /* Record start time */
timer->start = currticks();
- timer->running = 1;
-
- /* 0 means "use default timeout" */
- if ( timer->min_timeout == 0 )
- timer->min_timeout = DEFAULT_MIN_TIMEOUT;
- /* We must never be less than MIN_TIMEOUT under any circumstances */
- if ( timer->min_timeout < MIN_TIMEOUT )
- timer->min_timeout = MIN_TIMEOUT;
- /* Honor user-specified minimum timeout */
- if ( timer->timeout < timer->min_timeout )
- timer->timeout = timer->min_timeout;
+
+ /* Record timeout */
+ timer->timeout = timeout;
DBG2 ( "Timer %p started at time %ld (expires at %ld)\n",
timer, timer->start, ( timer->start + timer->timeout ) );
}
/**
- * Start timer with a specified fixed timeout
+ * Start timer
*
* @v timer Retry timer
- * @v timeout Timeout, in ticks
+ *
+ * This starts the timer running with the current timeout value
+ * (rounded up to the minimum timeout value). If stop_timer() is not
+ * called before the timer expires, the timer will be stopped and the
+ * timer's callback function will be called.
*/
-void start_timer_fixed ( struct retry_timer *timer, unsigned long timeout ) {
- start_timer ( timer );
- timer->timeout = timeout;
- DBG2 ( "Timer %p expiry time changed to %ld\n",
- timer, ( timer->start + timer->timeout ) );
+void start_timer ( struct retry_timer *timer ) {
+ unsigned long timeout = timer->timeout;
+ unsigned long min;
+
+ /* Calculate minimum timeout */
+ min = ( timer->min ? timer->min : DEFAULT_MIN_TIMEOUT );
+ if ( min < MIN_TIMEOUT )
+ min = MIN_TIMEOUT;
+
+ /* Ensure timeout is at least the minimum */
+ if ( timeout < min )
+ timeout = min;
+
+ /* Start timer with this timeout */
+ start_timer_fixed ( timer, timeout );
}
/**
*/
static void timer_expired ( struct retry_timer *timer ) {
struct refcnt *refcnt = timer->refcnt;
+ unsigned long max = ( timer->max ? timer->max : DEFAULT_MAX_TIMEOUT );
int fail;
/* Stop timer without performing RTT calculations */
/* Back off the timeout value */
timer->timeout <<= 1;
- if ( timer->max_timeout == 0 ) /* 0 means "use default timeout" */
- timer->max_timeout = DEFAULT_MAX_TIMEOUT;
- if ( ( fail = ( timer->timeout > timer->max_timeout ) ) )
- timer->timeout = timer->max_timeout;
+ if ( ( fail = ( timer->timeout > max ) ) )
+ timer->timeout = max;
DBG ( "Timer %p timeout backed off to %ld\n",
timer, timer->timeout );