2 * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 #include <gpxe/list.h>
22 #include <gpxe/process.h>
23 #include <gpxe/init.h>
24 #include <gpxe/retry.h>
30 * A retry timer is a truncated binary exponential backoff timer. It
31 * can be used to build automatic retransmission into network
35 /** List of running timers */
36 static LIST_HEAD ( timers );
41 * @v timer Retry timer
43 * This reloads the timer with a new expiry time. The expiry time
44 * will be the timer's base timeout value, shifted left by the number
45 * of retries (i.e. the number of timer expiries since the last timer
48 static void reload_timer ( struct retry_timer *timer ) {
52 if ( exp > BACKOFF_LIMIT )
54 timer->expiry = currticks() + ( timer->base << exp );
60 * @v timer Retry timer
62 * This resets the timer, i.e. clears its retry count and starts it
63 * running with its base timeout value.
65 * Note that it is explicitly permitted to call reset_timer() on an
68 void reset_timer ( struct retry_timer *timer ) {
70 reload_timer ( timer );
76 * @v timer Retry timer
78 * This resets the timer and starts it running (i.e. adds it to the
79 * list of running timers). The retry_timer::base and
80 * retry_timer::callback fields must have been filled in.
82 void start_timer ( struct retry_timer *timer ) {
83 list_add ( &timer->list, &timers );
84 reset_timer ( timer );
90 * @v timer Retry timer
92 * This stops the timer (i.e. removes it from the list of running
95 void stop_timer ( struct retry_timer *timer ) {
96 list_del ( &timer->list );
100 * Single-step the retry timer list
102 * @v process Retry timer process
104 static void retry_step ( struct process *process ) {
105 struct retry_timer *timer;
106 struct retry_timer *tmp;
107 unsigned long now = currticks();
109 list_for_each_entry_safe ( timer, tmp, &timers, list ) {
110 if ( timer->expiry <= now ) {
112 reload_timer ( timer );
113 timer->expired ( timer );
117 schedule ( process );
120 /** Retry timer process */
121 static struct process retry_process = {
125 /** Initialise the retry timer module */
126 static void init_retry ( void ) {
127 schedule ( &retry_process );
130 INIT_FN ( INIT_PROCESS, init_retry, NULL, NULL );