First step: AutoIP compiled in and working

Dependencies:   mbed

Committer:
darran
Date:
Fri Jun 18 09:11:35 2010 +0000
Revision:
0:55a05330f8cc

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
darran 0:55a05330f8cc 1 /**
darran 0:55a05330f8cc 2 * @file
darran 0:55a05330f8cc 3 * Stack-internal timers implementation.
darran 0:55a05330f8cc 4 * This file includes timer callbacks for stack-internal timers as well as
darran 0:55a05330f8cc 5 * functions to set up or stop timers and check for expired timers.
darran 0:55a05330f8cc 6 *
darran 0:55a05330f8cc 7 */
darran 0:55a05330f8cc 8
darran 0:55a05330f8cc 9 /*
darran 0:55a05330f8cc 10 * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
darran 0:55a05330f8cc 11 * All rights reserved.
darran 0:55a05330f8cc 12 *
darran 0:55a05330f8cc 13 * Redistribution and use in source and binary forms, with or without modification,
darran 0:55a05330f8cc 14 * are permitted provided that the following conditions are met:
darran 0:55a05330f8cc 15 *
darran 0:55a05330f8cc 16 * 1. Redistributions of source code must retain the above copyright notice,
darran 0:55a05330f8cc 17 * this list of conditions and the following disclaimer.
darran 0:55a05330f8cc 18 * 2. Redistributions in binary form must reproduce the above copyright notice,
darran 0:55a05330f8cc 19 * this list of conditions and the following disclaimer in the documentation
darran 0:55a05330f8cc 20 * and/or other materials provided with the distribution.
darran 0:55a05330f8cc 21 * 3. The name of the author may not be used to endorse or promote products
darran 0:55a05330f8cc 22 * derived from this software without specific prior written permission.
darran 0:55a05330f8cc 23 *
darran 0:55a05330f8cc 24 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
darran 0:55a05330f8cc 25 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
darran 0:55a05330f8cc 26 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
darran 0:55a05330f8cc 27 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
darran 0:55a05330f8cc 28 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
darran 0:55a05330f8cc 29 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
darran 0:55a05330f8cc 30 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
darran 0:55a05330f8cc 31 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
darran 0:55a05330f8cc 32 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
darran 0:55a05330f8cc 33 * OF SUCH DAMAGE.
darran 0:55a05330f8cc 34 *
darran 0:55a05330f8cc 35 * This file is part of the lwIP TCP/IP stack.
darran 0:55a05330f8cc 36 *
darran 0:55a05330f8cc 37 * Author: Adam Dunkels <adam@sics.se>
darran 0:55a05330f8cc 38 * Simon Goldschmidt
darran 0:55a05330f8cc 39 *
darran 0:55a05330f8cc 40 */
darran 0:55a05330f8cc 41
darran 0:55a05330f8cc 42 #include "lwip/opt.h"
darran 0:55a05330f8cc 43
darran 0:55a05330f8cc 44 #include "lwip/timers.h"
darran 0:55a05330f8cc 45 #include "lwip/def.h"
darran 0:55a05330f8cc 46 #include "lwip/memp.h"
darran 0:55a05330f8cc 47 #include "lwip/tcpip.h"
darran 0:55a05330f8cc 48
darran 0:55a05330f8cc 49 #include "lwip/tcp_impl.h"
darran 0:55a05330f8cc 50 #include "lwip/ip_frag.h"
darran 0:55a05330f8cc 51 #include "netif/etharp.h"
darran 0:55a05330f8cc 52 #include "lwip/dhcp.h"
darran 0:55a05330f8cc 53 #include "lwip/autoip.h"
darran 0:55a05330f8cc 54 #include "lwip/igmp.h"
darran 0:55a05330f8cc 55 #include "lwip/dns.h"
darran 0:55a05330f8cc 56
darran 0:55a05330f8cc 57
darran 0:55a05330f8cc 58 /** The one and only timeout list */
darran 0:55a05330f8cc 59 static struct sys_timeo *next_timeout;
darran 0:55a05330f8cc 60 #if NO_SYS
darran 0:55a05330f8cc 61 static u32_t timeouts_last_time;
darran 0:55a05330f8cc 62 #endif /* NO_SYS */
darran 0:55a05330f8cc 63
darran 0:55a05330f8cc 64 #if LWIP_TCP
darran 0:55a05330f8cc 65 /** global variable that shows if the tcp timer is currently scheduled or not */
darran 0:55a05330f8cc 66 static int tcpip_tcp_timer_active;
darran 0:55a05330f8cc 67
darran 0:55a05330f8cc 68 /**
darran 0:55a05330f8cc 69 * Timer callback function that calls tcp_tmr() and reschedules itself.
darran 0:55a05330f8cc 70 *
darran 0:55a05330f8cc 71 * @param arg unused argument
darran 0:55a05330f8cc 72 */
darran 0:55a05330f8cc 73 static void
darran 0:55a05330f8cc 74 tcpip_tcp_timer(void *arg)
darran 0:55a05330f8cc 75 {
darran 0:55a05330f8cc 76 LWIP_UNUSED_ARG(arg);
darran 0:55a05330f8cc 77
darran 0:55a05330f8cc 78 /* call TCP timer handler */
darran 0:55a05330f8cc 79 tcp_tmr();
darran 0:55a05330f8cc 80 /* timer still needed? */
darran 0:55a05330f8cc 81 if (tcp_active_pcbs || tcp_tw_pcbs) {
darran 0:55a05330f8cc 82 /* restart timer */
darran 0:55a05330f8cc 83 sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL);
darran 0:55a05330f8cc 84 } else {
darran 0:55a05330f8cc 85 /* disable timer */
darran 0:55a05330f8cc 86 tcpip_tcp_timer_active = 0;
darran 0:55a05330f8cc 87 }
darran 0:55a05330f8cc 88 }
darran 0:55a05330f8cc 89
darran 0:55a05330f8cc 90 /**
darran 0:55a05330f8cc 91 * Called from TCP_REG when registering a new PCB:
darran 0:55a05330f8cc 92 * the reason is to have the TCP timer only running when
darran 0:55a05330f8cc 93 * there are active (or time-wait) PCBs.
darran 0:55a05330f8cc 94 */
darran 0:55a05330f8cc 95 void
darran 0:55a05330f8cc 96 tcp_timer_needed(void)
darran 0:55a05330f8cc 97 {
darran 0:55a05330f8cc 98 /* timer is off but needed again? */
darran 0:55a05330f8cc 99 if (!tcpip_tcp_timer_active && (tcp_active_pcbs || tcp_tw_pcbs)) {
darran 0:55a05330f8cc 100 /* enable and start timer */
darran 0:55a05330f8cc 101 tcpip_tcp_timer_active = 1;
darran 0:55a05330f8cc 102 sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL);
darran 0:55a05330f8cc 103 }
darran 0:55a05330f8cc 104 }
darran 0:55a05330f8cc 105 #endif /* LWIP_TCP */
darran 0:55a05330f8cc 106
darran 0:55a05330f8cc 107 #if IP_REASSEMBLY
darran 0:55a05330f8cc 108 /**
darran 0:55a05330f8cc 109 * Timer callback function that calls ip_reass_tmr() and reschedules itself.
darran 0:55a05330f8cc 110 *
darran 0:55a05330f8cc 111 * @param arg unused argument
darran 0:55a05330f8cc 112 */
darran 0:55a05330f8cc 113 static void
darran 0:55a05330f8cc 114 ip_reass_timer(void *arg)
darran 0:55a05330f8cc 115 {
darran 0:55a05330f8cc 116 LWIP_UNUSED_ARG(arg);
darran 0:55a05330f8cc 117 LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: ip_reass_tmr()\n"));
darran 0:55a05330f8cc 118 ip_reass_tmr();
darran 0:55a05330f8cc 119 sys_timeout(IP_TMR_INTERVAL, ip_reass_timer, NULL);
darran 0:55a05330f8cc 120 }
darran 0:55a05330f8cc 121 #endif /* IP_REASSEMBLY */
darran 0:55a05330f8cc 122
darran 0:55a05330f8cc 123 #if LWIP_ARP
darran 0:55a05330f8cc 124 /**
darran 0:55a05330f8cc 125 * Timer callback function that calls etharp_tmr() and reschedules itself.
darran 0:55a05330f8cc 126 *
darran 0:55a05330f8cc 127 * @param arg unused argument
darran 0:55a05330f8cc 128 */
darran 0:55a05330f8cc 129 static void
darran 0:55a05330f8cc 130 arp_timer(void *arg)
darran 0:55a05330f8cc 131 {
darran 0:55a05330f8cc 132 LWIP_UNUSED_ARG(arg);
darran 0:55a05330f8cc 133 LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: etharp_tmr()\n"));
darran 0:55a05330f8cc 134 etharp_tmr();
darran 0:55a05330f8cc 135 sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL);
darran 0:55a05330f8cc 136 }
darran 0:55a05330f8cc 137 #endif /* LWIP_ARP */
darran 0:55a05330f8cc 138
darran 0:55a05330f8cc 139 #if LWIP_DHCP
darran 0:55a05330f8cc 140 /**
darran 0:55a05330f8cc 141 * Timer callback function that calls dhcp_coarse_tmr() and reschedules itself.
darran 0:55a05330f8cc 142 *
darran 0:55a05330f8cc 143 * @param arg unused argument
darran 0:55a05330f8cc 144 */
darran 0:55a05330f8cc 145 static void
darran 0:55a05330f8cc 146 dhcp_timer_coarse(void *arg)
darran 0:55a05330f8cc 147 {
darran 0:55a05330f8cc 148 LWIP_UNUSED_ARG(arg);
darran 0:55a05330f8cc 149 LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: dhcp_coarse_tmr()\n"));
darran 0:55a05330f8cc 150 dhcp_coarse_tmr();
darran 0:55a05330f8cc 151 sys_timeout(DHCP_COARSE_TIMER_MSECS, dhcp_timer_coarse, NULL);
darran 0:55a05330f8cc 152 }
darran 0:55a05330f8cc 153
darran 0:55a05330f8cc 154 /**
darran 0:55a05330f8cc 155 * Timer callback function that calls dhcp_fine_tmr() and reschedules itself.
darran 0:55a05330f8cc 156 *
darran 0:55a05330f8cc 157 * @param arg unused argument
darran 0:55a05330f8cc 158 */
darran 0:55a05330f8cc 159 static void
darran 0:55a05330f8cc 160 dhcp_timer_fine(void *arg)
darran 0:55a05330f8cc 161 {
darran 0:55a05330f8cc 162 LWIP_UNUSED_ARG(arg);
darran 0:55a05330f8cc 163 LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: dhcp_fine_tmr()\n"));
darran 0:55a05330f8cc 164 dhcp_fine_tmr();
darran 0:55a05330f8cc 165 sys_timeout(DHCP_FINE_TIMER_MSECS, dhcp_timer_fine, NULL);
darran 0:55a05330f8cc 166 }
darran 0:55a05330f8cc 167 #endif /* LWIP_DHCP */
darran 0:55a05330f8cc 168
darran 0:55a05330f8cc 169 #if LWIP_AUTOIP
darran 0:55a05330f8cc 170 /**
darran 0:55a05330f8cc 171 * Timer callback function that calls autoip_tmr() and reschedules itself.
darran 0:55a05330f8cc 172 *
darran 0:55a05330f8cc 173 * @param arg unused argument
darran 0:55a05330f8cc 174 */
darran 0:55a05330f8cc 175 static void
darran 0:55a05330f8cc 176 autoip_timer(void *arg)
darran 0:55a05330f8cc 177 {
darran 0:55a05330f8cc 178 LWIP_UNUSED_ARG(arg);
darran 0:55a05330f8cc 179 LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: autoip_tmr()\n"));
darran 0:55a05330f8cc 180 autoip_tmr();
darran 0:55a05330f8cc 181 sys_timeout(AUTOIP_TMR_INTERVAL, autoip_timer, NULL);
darran 0:55a05330f8cc 182 }
darran 0:55a05330f8cc 183 #endif /* LWIP_AUTOIP */
darran 0:55a05330f8cc 184
darran 0:55a05330f8cc 185 #if LWIP_IGMP
darran 0:55a05330f8cc 186 /**
darran 0:55a05330f8cc 187 * Timer callback function that calls igmp_tmr() and reschedules itself.
darran 0:55a05330f8cc 188 *
darran 0:55a05330f8cc 189 * @param arg unused argument
darran 0:55a05330f8cc 190 */
darran 0:55a05330f8cc 191 static void
darran 0:55a05330f8cc 192 igmp_timer(void *arg)
darran 0:55a05330f8cc 193 {
darran 0:55a05330f8cc 194 LWIP_UNUSED_ARG(arg);
darran 0:55a05330f8cc 195 LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: igmp_tmr()\n"));
darran 0:55a05330f8cc 196 igmp_tmr();
darran 0:55a05330f8cc 197 sys_timeout(IGMP_TMR_INTERVAL, igmp_timer, NULL);
darran 0:55a05330f8cc 198 }
darran 0:55a05330f8cc 199 #endif /* LWIP_IGMP */
darran 0:55a05330f8cc 200
darran 0:55a05330f8cc 201 #if LWIP_DNS
darran 0:55a05330f8cc 202 /**
darran 0:55a05330f8cc 203 * Timer callback function that calls dns_tmr() and reschedules itself.
darran 0:55a05330f8cc 204 *
darran 0:55a05330f8cc 205 * @param arg unused argument
darran 0:55a05330f8cc 206 */
darran 0:55a05330f8cc 207 static void
darran 0:55a05330f8cc 208 dns_timer(void *arg)
darran 0:55a05330f8cc 209 {
darran 0:55a05330f8cc 210 LWIP_UNUSED_ARG(arg);
darran 0:55a05330f8cc 211 LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: dns_tmr()\n"));
darran 0:55a05330f8cc 212 dns_tmr();
darran 0:55a05330f8cc 213 sys_timeout(DNS_TMR_INTERVAL, dns_timer, NULL);
darran 0:55a05330f8cc 214 }
darran 0:55a05330f8cc 215 #endif /* LWIP_DNS */
darran 0:55a05330f8cc 216
darran 0:55a05330f8cc 217 /** Initialize this module */
darran 0:55a05330f8cc 218 void sys_timeouts_init(void)
darran 0:55a05330f8cc 219 {
darran 0:55a05330f8cc 220 #if IP_REASSEMBLY
darran 0:55a05330f8cc 221 sys_timeout(IP_TMR_INTERVAL, ip_reass_timer, NULL);
darran 0:55a05330f8cc 222 #endif /* IP_REASSEMBLY */
darran 0:55a05330f8cc 223 #if LWIP_ARP
darran 0:55a05330f8cc 224 sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL);
darran 0:55a05330f8cc 225 #endif /* LWIP_ARP */
darran 0:55a05330f8cc 226 #if LWIP_DHCP
darran 0:55a05330f8cc 227 sys_timeout(DHCP_COARSE_TIMER_MSECS, dhcp_timer_coarse, NULL);
darran 0:55a05330f8cc 228 sys_timeout(DHCP_FINE_TIMER_MSECS, dhcp_timer_fine, NULL);
darran 0:55a05330f8cc 229 #endif /* LWIP_DHCP */
darran 0:55a05330f8cc 230 #if LWIP_AUTOIP
darran 0:55a05330f8cc 231 sys_timeout(AUTOIP_TMR_INTERVAL, autoip_timer, NULL);
darran 0:55a05330f8cc 232 #endif /* LWIP_AUTOIP */
darran 0:55a05330f8cc 233 #if LWIP_IGMP
darran 0:55a05330f8cc 234 sys_timeout(IGMP_TMR_INTERVAL, igmp_timer, NULL);
darran 0:55a05330f8cc 235 #endif /* LWIP_IGMP */
darran 0:55a05330f8cc 236 #if LWIP_DNS
darran 0:55a05330f8cc 237 sys_timeout(DNS_TMR_INTERVAL, dns_timer, NULL);
darran 0:55a05330f8cc 238 #endif /* LWIP_DNS */
darran 0:55a05330f8cc 239
darran 0:55a05330f8cc 240 #if NO_SYS
darran 0:55a05330f8cc 241 /* Initialise timestamp for sys_check_timeouts */
darran 0:55a05330f8cc 242 timeouts_last_time = sys_now();
darran 0:55a05330f8cc 243 #endif
darran 0:55a05330f8cc 244 }
darran 0:55a05330f8cc 245
darran 0:55a05330f8cc 246 /**
darran 0:55a05330f8cc 247 * Create a one-shot timer (aka timeout). Timeouts are processed in the
darran 0:55a05330f8cc 248 * following cases:
darran 0:55a05330f8cc 249 * - while waiting for a message using sys_timeouts_mbox_fetch()
darran 0:55a05330f8cc 250 * - by calling sys_check_timeouts() (NO_SYS==1 only)
darran 0:55a05330f8cc 251 *
darran 0:55a05330f8cc 252 * @param msecs time in milliseconds after that the timer should expire
darran 0:55a05330f8cc 253 * @param h callback function to call when msecs have elapsed
darran 0:55a05330f8cc 254 * @param arg argument to pass to the callback function
darran 0:55a05330f8cc 255 */
darran 0:55a05330f8cc 256 #if LWIP_DEBUG_TIMERNAMES
darran 0:55a05330f8cc 257 void
darran 0:55a05330f8cc 258 sys_timeout_debug(u32_t msecs, sys_timeout_handler h, void *arg, const char* handler_name)
darran 0:55a05330f8cc 259 #else /* LWIP_DEBUG_TIMERNAMES */
darran 0:55a05330f8cc 260 void
darran 0:55a05330f8cc 261 sys_timeout(u32_t msecs, sys_timeout_handler h, void *arg)
darran 0:55a05330f8cc 262 #endif /* LWIP_DEBUG_TIMERNAMES */
darran 0:55a05330f8cc 263 {
darran 0:55a05330f8cc 264 struct sys_timeo *timeout, *t;
darran 0:55a05330f8cc 265
darran 0:55a05330f8cc 266 timeout = (struct sys_timeo *)memp_malloc(MEMP_SYS_TIMEOUT);
darran 0:55a05330f8cc 267 if (timeout == NULL) {
darran 0:55a05330f8cc 268 LWIP_ASSERT("sys_timeout: timeout != NULL, pool MEMP_SYS_TIMEOUT is empty", timeout != NULL);
darran 0:55a05330f8cc 269 return;
darran 0:55a05330f8cc 270 }
darran 0:55a05330f8cc 271 timeout->next = NULL;
darran 0:55a05330f8cc 272 timeout->h = h;
darran 0:55a05330f8cc 273 timeout->arg = arg;
darran 0:55a05330f8cc 274 timeout->time = msecs;
darran 0:55a05330f8cc 275 #if LWIP_DEBUG_TIMERNAMES
darran 0:55a05330f8cc 276 timeout->handler_name = handler_name;
darran 0:55a05330f8cc 277 #endif /* LWIP_DEBUG_TIMERNAMES */
darran 0:55a05330f8cc 278
darran 0:55a05330f8cc 279 #if LWIP_DEBUG_TIMERNAMES
darran 0:55a05330f8cc 280 LWIP_DEBUGF(TIMERS_DEBUG, ("sys_timeout: %p msecs=%"U32_F" h=%p arg=%p name=%s\n",
darran 0:55a05330f8cc 281 (void *)timeout, msecs, *(void**)&h, (void *)arg, handler_name));
darran 0:55a05330f8cc 282 #else /* LWIP_DEBUG_TIMERNAMES */
darran 0:55a05330f8cc 283 LWIP_DEBUGF(TIMERS_DEBUG, ("sys_timeout: %p msecs=%"U32_F" h=%p arg=%p\n",
darran 0:55a05330f8cc 284 (void *)timeout, msecs, *(void**)&h, (void *)arg));
darran 0:55a05330f8cc 285 #endif /* LWIP_DEBUG_TIMERNAMES */
darran 0:55a05330f8cc 286
darran 0:55a05330f8cc 287 if (next_timeout == NULL) {
darran 0:55a05330f8cc 288 next_timeout = timeout;
darran 0:55a05330f8cc 289 return;
darran 0:55a05330f8cc 290 }
darran 0:55a05330f8cc 291
darran 0:55a05330f8cc 292 if (next_timeout->time > msecs) {
darran 0:55a05330f8cc 293 next_timeout->time -= msecs;
darran 0:55a05330f8cc 294 timeout->next = next_timeout;
darran 0:55a05330f8cc 295 next_timeout = timeout;
darran 0:55a05330f8cc 296 } else {
darran 0:55a05330f8cc 297 for(t = next_timeout; t != NULL; t = t->next) {
darran 0:55a05330f8cc 298 timeout->time -= t->time;
darran 0:55a05330f8cc 299 if (t->next == NULL || t->next->time > timeout->time) {
darran 0:55a05330f8cc 300 if (t->next != NULL) {
darran 0:55a05330f8cc 301 t->next->time -= timeout->time;
darran 0:55a05330f8cc 302 }
darran 0:55a05330f8cc 303 timeout->next = t->next;
darran 0:55a05330f8cc 304 t->next = timeout;
darran 0:55a05330f8cc 305 break;
darran 0:55a05330f8cc 306 }
darran 0:55a05330f8cc 307 }
darran 0:55a05330f8cc 308 }
darran 0:55a05330f8cc 309 }
darran 0:55a05330f8cc 310
darran 0:55a05330f8cc 311 /**
darran 0:55a05330f8cc 312 * Go through timeout list (for this task only) and remove the first matching
darran 0:55a05330f8cc 313 * entry, even though the timeout has not triggered yet.
darran 0:55a05330f8cc 314 *
darran 0:55a05330f8cc 315 * @note This function only works as expected if there is only one timeout
darran 0:55a05330f8cc 316 * calling 'h' in the list of timeouts.
darran 0:55a05330f8cc 317 *
darran 0:55a05330f8cc 318 * @param h callback function that would be called by the timeout
darran 0:55a05330f8cc 319 * @param arg callback argument that would be passed to h
darran 0:55a05330f8cc 320 */
darran 0:55a05330f8cc 321 void
darran 0:55a05330f8cc 322 sys_untimeout(sys_timeout_handler h, void *arg)
darran 0:55a05330f8cc 323 {
darran 0:55a05330f8cc 324 struct sys_timeo *prev_t, *t;
darran 0:55a05330f8cc 325
darran 0:55a05330f8cc 326 if (next_timeout == NULL) {
darran 0:55a05330f8cc 327 return;
darran 0:55a05330f8cc 328 }
darran 0:55a05330f8cc 329
darran 0:55a05330f8cc 330 for (t = next_timeout, prev_t = NULL; t != NULL; prev_t = t, t = t->next) {
darran 0:55a05330f8cc 331 if ((t->h == h) && (t->arg == arg)) {
darran 0:55a05330f8cc 332 /* We have a match */
darran 0:55a05330f8cc 333 /* Unlink from previous in list */
darran 0:55a05330f8cc 334 if (prev_t == NULL) {
darran 0:55a05330f8cc 335 next_timeout = t->next;
darran 0:55a05330f8cc 336 } else {
darran 0:55a05330f8cc 337 prev_t->next = t->next;
darran 0:55a05330f8cc 338 }
darran 0:55a05330f8cc 339 /* If not the last one, add time of this one back to next */
darran 0:55a05330f8cc 340 if (t->next != NULL) {
darran 0:55a05330f8cc 341 t->next->time += t->time;
darran 0:55a05330f8cc 342 }
darran 0:55a05330f8cc 343 memp_free(MEMP_SYS_TIMEOUT, t);
darran 0:55a05330f8cc 344 return;
darran 0:55a05330f8cc 345 }
darran 0:55a05330f8cc 346 }
darran 0:55a05330f8cc 347 return;
darran 0:55a05330f8cc 348 }
darran 0:55a05330f8cc 349
darran 0:55a05330f8cc 350 #if NO_SYS
darran 0:55a05330f8cc 351
darran 0:55a05330f8cc 352 /** Handle timeouts for NO_SYS==1 (i.e. without using
darran 0:55a05330f8cc 353 * tcpip_thread/sys_timeouts_mbox_fetch(). Uses sys_now() to call timeout
darran 0:55a05330f8cc 354 * handler functions when timeouts expire.
darran 0:55a05330f8cc 355 *
darran 0:55a05330f8cc 356 * Must be called periodically from your main loop.
darran 0:55a05330f8cc 357 */
darran 0:55a05330f8cc 358 void
darran 0:55a05330f8cc 359 sys_check_timeouts(void)
darran 0:55a05330f8cc 360 {
darran 0:55a05330f8cc 361 struct sys_timeo *tmptimeout;
darran 0:55a05330f8cc 362 u32_t diff;
darran 0:55a05330f8cc 363 sys_timeout_handler h;
darran 0:55a05330f8cc 364 void *arg;
darran 0:55a05330f8cc 365 int had_one;
darran 0:55a05330f8cc 366 u32_t now;
darran 0:55a05330f8cc 367 #if LWIP_DEBUG_TIMERNAMES
darran 0:55a05330f8cc 368 const char *handler_name;
darran 0:55a05330f8cc 369 #endif /* LWIP_DEBUG_TIMERNAMES */
darran 0:55a05330f8cc 370
darran 0:55a05330f8cc 371 now = sys_now();
darran 0:55a05330f8cc 372 if (next_timeout) {
darran 0:55a05330f8cc 373 /* @todo: wrap around? */
darran 0:55a05330f8cc 374 diff = now - timeouts_last_time;
darran 0:55a05330f8cc 375 do
darran 0:55a05330f8cc 376 {
darran 0:55a05330f8cc 377 had_one = 0;
darran 0:55a05330f8cc 378 tmptimeout = next_timeout;
darran 0:55a05330f8cc 379 if (tmptimeout->time <= diff) {
darran 0:55a05330f8cc 380 /* timeout has expired */
darran 0:55a05330f8cc 381 had_one = 1;
darran 0:55a05330f8cc 382 timeouts_last_time = now;
darran 0:55a05330f8cc 383 diff -= tmptimeout->time;
darran 0:55a05330f8cc 384 next_timeout = tmptimeout->next;
darran 0:55a05330f8cc 385 h = tmptimeout->h;
darran 0:55a05330f8cc 386 arg = tmptimeout->arg;
darran 0:55a05330f8cc 387 #if LWIP_DEBUG_TIMERNAMES
darran 0:55a05330f8cc 388 handler_name = tmptimeout->handler_name;
darran 0:55a05330f8cc 389 #endif /* LWIP_DEBUG_TIMERNAMES */
darran 0:55a05330f8cc 390 memp_free(MEMP_SYS_TIMEOUT, tmptimeout);
darran 0:55a05330f8cc 391 if (h != NULL) {
darran 0:55a05330f8cc 392 #if LWIP_DEBUG_TIMERNAMES
darran 0:55a05330f8cc 393 LWIP_DEBUGF(TIMERS_DEBUG, ("sct calling h=%p(%p) (%s)\n", *(void**)&h, arg, handler_name));
darran 0:55a05330f8cc 394 #else /* LWIP_DEBUG_TIMERNAMES */
darran 0:55a05330f8cc 395 LWIP_DEBUGF(TIMERS_DEBUG, ("sct calling h=%p(%p)\n", *(void**)&h, arg));
darran 0:55a05330f8cc 396 #endif /* LWIP_DEBUG_TIMERNAMES */
darran 0:55a05330f8cc 397 h(arg);
darran 0:55a05330f8cc 398 }
darran 0:55a05330f8cc 399 }
darran 0:55a05330f8cc 400 /* repeat until all expired timers have been called */
darran 0:55a05330f8cc 401 }while(had_one);
darran 0:55a05330f8cc 402 }
darran 0:55a05330f8cc 403 }
darran 0:55a05330f8cc 404
darran 0:55a05330f8cc 405 /** Set back the timestamp of the last call to sys_check_timeouts()
darran 0:55a05330f8cc 406 * This is necessary if sys_check_timeouts() hasn't been called for a long
darran 0:55a05330f8cc 407 * time (e.g. while saving energy) to prevent all timer functions of that
darran 0:55a05330f8cc 408 * period being called.
darran 0:55a05330f8cc 409 */
darran 0:55a05330f8cc 410 void
darran 0:55a05330f8cc 411 sys_restart_timeouts(void)
darran 0:55a05330f8cc 412 {
darran 0:55a05330f8cc 413 timeouts_last_time = sys_now();
darran 0:55a05330f8cc 414 }
darran 0:55a05330f8cc 415
darran 0:55a05330f8cc 416 #else /* NO_SYS */
darran 0:55a05330f8cc 417
darran 0:55a05330f8cc 418 /**
darran 0:55a05330f8cc 419 * Wait (forever) for a message to arrive in an mbox.
darran 0:55a05330f8cc 420 * While waiting, timeouts are processed.
darran 0:55a05330f8cc 421 *
darran 0:55a05330f8cc 422 * @param mbox the mbox to fetch the message from
darran 0:55a05330f8cc 423 * @param msg the place to store the message
darran 0:55a05330f8cc 424 */
darran 0:55a05330f8cc 425 void
darran 0:55a05330f8cc 426 sys_timeouts_mbox_fetch(sys_mbox_t *mbox, void **msg)
darran 0:55a05330f8cc 427 {
darran 0:55a05330f8cc 428 u32_t time_needed;
darran 0:55a05330f8cc 429 struct sys_timeo *tmptimeout;
darran 0:55a05330f8cc 430 sys_timeout_handler h;
darran 0:55a05330f8cc 431 void *arg;
darran 0:55a05330f8cc 432 #if LWIP_DEBUG_TIMERNAMES
darran 0:55a05330f8cc 433 const char *handler_name;
darran 0:55a05330f8cc 434 #endif /* LWIP_DEBUG_TIMERNAMES */
darran 0:55a05330f8cc 435
darran 0:55a05330f8cc 436 again:
darran 0:55a05330f8cc 437 if (!next_timeout) {
darran 0:55a05330f8cc 438 time_needed = sys_arch_mbox_fetch(mbox, msg, 0);
darran 0:55a05330f8cc 439 } else {
darran 0:55a05330f8cc 440 if (next_timeout->time > 0) {
darran 0:55a05330f8cc 441 time_needed = sys_arch_mbox_fetch(mbox, msg, next_timeout->time);
darran 0:55a05330f8cc 442 } else {
darran 0:55a05330f8cc 443 time_needed = SYS_ARCH_TIMEOUT;
darran 0:55a05330f8cc 444 }
darran 0:55a05330f8cc 445
darran 0:55a05330f8cc 446 if (time_needed == SYS_ARCH_TIMEOUT) {
darran 0:55a05330f8cc 447 /* If time == SYS_ARCH_TIMEOUT, a timeout occured before a message
darran 0:55a05330f8cc 448 could be fetched. We should now call the timeout handler and
darran 0:55a05330f8cc 449 deallocate the memory allocated for the timeout. */
darran 0:55a05330f8cc 450 tmptimeout = next_timeout;
darran 0:55a05330f8cc 451 next_timeout = tmptimeout->next;
darran 0:55a05330f8cc 452 h = tmptimeout->h;
darran 0:55a05330f8cc 453 arg = tmptimeout->arg;
darran 0:55a05330f8cc 454 #if LWIP_DEBUG_TIMERNAMES
darran 0:55a05330f8cc 455 handler_name = tmptimeout->handler_name;
darran 0:55a05330f8cc 456 #endif /* LWIP_DEBUG_TIMERNAMES */
darran 0:55a05330f8cc 457 memp_free(MEMP_SYS_TIMEOUT, tmptimeout);
darran 0:55a05330f8cc 458 if (h != NULL) {
darran 0:55a05330f8cc 459 #if LWIP_DEBUG_TIMERNAMES
darran 0:55a05330f8cc 460 LWIP_DEBUGF(TIMERS_DEBUG, ("stmf calling h=%p(%p) (%s)\n", *(void**)&h, arg, handler_name));
darran 0:55a05330f8cc 461 #else /* LWIP_DEBUG_TIMERNAMES */
darran 0:55a05330f8cc 462 LWIP_DEBUGF(TIMERS_DEBUG, ("stmf calling h=%p(%p)\n", *(void**)&h, arg));
darran 0:55a05330f8cc 463 #endif /* LWIP_DEBUG_TIMERNAMES */
darran 0:55a05330f8cc 464 /* For LWIP_TCPIP_CORE_LOCKING, lock the core before calling the
darran 0:55a05330f8cc 465 timeout handler function. */
darran 0:55a05330f8cc 466 LOCK_TCPIP_CORE();
darran 0:55a05330f8cc 467 h(arg);
darran 0:55a05330f8cc 468 UNLOCK_TCPIP_CORE();
darran 0:55a05330f8cc 469 }
darran 0:55a05330f8cc 470
darran 0:55a05330f8cc 471 /* We try again to fetch a message from the mbox. */
darran 0:55a05330f8cc 472 goto again;
darran 0:55a05330f8cc 473 } else {
darran 0:55a05330f8cc 474 /* If time != SYS_ARCH_TIMEOUT, a message was received before the timeout
darran 0:55a05330f8cc 475 occured. The time variable is set to the number of
darran 0:55a05330f8cc 476 milliseconds we waited for the message. */
darran 0:55a05330f8cc 477 if (time_needed < next_timeout->time) {
darran 0:55a05330f8cc 478 next_timeout->time -= time_needed;
darran 0:55a05330f8cc 479 } else {
darran 0:55a05330f8cc 480 next_timeout->time = 0;
darran 0:55a05330f8cc 481 }
darran 0:55a05330f8cc 482 }
darran 0:55a05330f8cc 483 }
darran 0:55a05330f8cc 484 }
darran 0:55a05330f8cc 485
darran 0:55a05330f8cc 486 #endif /* NO_SYS */