ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

timers.c
Go to the documentation of this file.
00001 
00009 /*
00010  * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
00011  * All rights reserved.
00012  *
00013  * Redistribution and use in source and binary forms, with or without modification,
00014  * are permitted provided that the following conditions are met:
00015  *
00016  * 1. Redistributions of source code must retain the above copyright notice,
00017  *    this list of conditions and the following disclaimer.
00018  * 2. Redistributions in binary form must reproduce the above copyright notice,
00019  *    this list of conditions and the following disclaimer in the documentation
00020  *    and/or other materials provided with the distribution.
00021  * 3. The name of the author may not be used to endorse or promote products
00022  *    derived from this software without specific prior written permission.
00023  *
00024  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
00025  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
00026  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
00027  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00028  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
00029  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00030  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00031  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
00032  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
00033  * OF SUCH DAMAGE.
00034  *
00035  * This file is part of the lwIP TCP/IP stack.
00036  *
00037  * Author: Adam Dunkels <adam@sics.se>
00038  *         Simon Goldschmidt
00039  *
00040  */
00041 
00042 #include "lwip/opt.h"
00043 
00044 #include "lwip/timers.h"
00045 #include "lwip/tcp_impl.h"
00046 
00047 #if LWIP_TIMERS
00048 
00049 #include "lwip/def.h"
00050 #include "lwip/memp.h"
00051 #include "lwip/tcpip.h"
00052 
00053 #include "lwip/ip_frag.h"
00054 #include "netif/etharp.h"
00055 #include "lwip/dhcp.h"
00056 #include "lwip/autoip.h"
00057 #include "lwip/igmp.h"
00058 #include "lwip/dns.h"
00059 
00060 
00062 static struct sys_timeo *next_timeout;
00063 #if NO_SYS
00064 static u32_t timeouts_last_time;
00065 #endif /* NO_SYS */
00066 
00067 #if LWIP_TCP
00068 
00069 static int tcpip_tcp_timer_active;
00070 
00076 static void
00077 tcpip_tcp_timer(void *arg)
00078 {
00079   LWIP_UNUSED_ARG(arg);
00080 
00081   /* call TCP timer handler */
00082   tcp_tmr();
00083   /* timer still needed? */
00084   if (tcp_active_pcbs || tcp_tw_pcbs) {
00085     /* restart timer */
00086     sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL);
00087   } else {
00088     /* disable timer */
00089     tcpip_tcp_timer_active = 0;
00090   }
00091 }
00092 
00098 void
00099 tcp_timer_needed(void)
00100 {
00101   /* timer is off but needed again? */
00102   if (!tcpip_tcp_timer_active && (tcp_active_pcbs || tcp_tw_pcbs)) {
00103     /* enable and start timer */
00104     tcpip_tcp_timer_active = 1;
00105     sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL);
00106   }
00107 }
00108 #endif /* LWIP_TCP */
00109 
00110 #if IP_REASSEMBLY
00111 
00116 static void
00117 ip_reass_timer(void *arg)
00118 {
00119   LWIP_UNUSED_ARG(arg);
00120   LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: ip_reass_tmr()\n"));
00121   ip_reass_tmr();
00122   sys_timeout(IP_TMR_INTERVAL, ip_reass_timer, NULL);
00123 }
00124 #endif /* IP_REASSEMBLY */
00125 
00126 #if LWIP_ARP
00127 
00132 static void
00133 arp_timer(void *arg)
00134 {
00135   LWIP_UNUSED_ARG(arg);
00136   LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: etharp_tmr()\n"));
00137   etharp_tmr();
00138   sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL);
00139 }
00140 #endif /* LWIP_ARP */
00141 
00142 #if LWIP_DHCP
00143 
00148 static void
00149 dhcp_timer_coarse(void *arg)
00150 {
00151   LWIP_UNUSED_ARG(arg);
00152   LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: dhcp_coarse_tmr()\n"));
00153   dhcp_coarse_tmr();
00154   sys_timeout(DHCP_COARSE_TIMER_MSECS, dhcp_timer_coarse, NULL);
00155 }
00156 
00162 static void
00163 dhcp_timer_fine(void *arg)
00164 {
00165   LWIP_UNUSED_ARG(arg);
00166   LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: dhcp_fine_tmr()\n"));
00167   dhcp_fine_tmr();
00168   sys_timeout(DHCP_FINE_TIMER_MSECS, dhcp_timer_fine, NULL);
00169 }
00170 #endif /* LWIP_DHCP */
00171 
00172 #if LWIP_AUTOIP
00173 
00178 static void
00179 autoip_timer(void *arg)
00180 {
00181   LWIP_UNUSED_ARG(arg);
00182   LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: autoip_tmr()\n"));
00183   autoip_tmr();
00184   sys_timeout(AUTOIP_TMR_INTERVAL, autoip_timer, NULL);
00185 }
00186 #endif /* LWIP_AUTOIP */
00187 
00188 #if LWIP_IGMP
00189 
00194 static void
00195 igmp_timer(void *arg)
00196 {
00197   LWIP_UNUSED_ARG(arg);
00198   LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: igmp_tmr()\n"));
00199   igmp_tmr();
00200   sys_timeout(IGMP_TMR_INTERVAL, igmp_timer, NULL);
00201 }
00202 #endif /* LWIP_IGMP */
00203 
00204 #if LWIP_DNS
00205 
00210 static void
00211 dns_timer(void *arg)
00212 {
00213   LWIP_UNUSED_ARG(arg);
00214   LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: dns_tmr()\n"));
00215   dns_tmr();
00216   sys_timeout(DNS_TMR_INTERVAL, dns_timer, NULL);
00217 }
00218 #endif /* LWIP_DNS */
00219 
00221 void sys_timeouts_init(void)
00222 {
00223 #if IP_REASSEMBLY
00224   sys_timeout(IP_TMR_INTERVAL, ip_reass_timer, NULL);
00225 #endif /* IP_REASSEMBLY */
00226 #if LWIP_ARP
00227   sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL);
00228 #endif /* LWIP_ARP */
00229 #if LWIP_DHCP
00230   sys_timeout(DHCP_COARSE_TIMER_MSECS, dhcp_timer_coarse, NULL);
00231   sys_timeout(DHCP_FINE_TIMER_MSECS, dhcp_timer_fine, NULL);
00232 #endif /* LWIP_DHCP */
00233 #if LWIP_AUTOIP
00234   sys_timeout(AUTOIP_TMR_INTERVAL, autoip_timer, NULL);
00235 #endif /* LWIP_AUTOIP */
00236 #if LWIP_IGMP
00237   sys_timeout(IGMP_TMR_INTERVAL, igmp_timer, NULL);
00238 #endif /* LWIP_IGMP */
00239 #if LWIP_DNS
00240   sys_timeout(DNS_TMR_INTERVAL, dns_timer, NULL);
00241 #endif /* LWIP_DNS */
00242 
00243 #if NO_SYS
00244   /* Initialise timestamp for sys_check_timeouts */
00245   timeouts_last_time = sys_now();
00246 #endif
00247 }
00248 
00259 #if LWIP_DEBUG_TIMERNAMES
00260 void
00261 sys_timeout_debug(u32_t msecs, sys_timeout_handler handler, void *arg, const char* handler_name)
00262 #else /* LWIP_DEBUG_TIMERNAMES */
00263 void
00264 sys_timeout(u32_t msecs, sys_timeout_handler handler, void *arg)
00265 #endif /* LWIP_DEBUG_TIMERNAMES */
00266 {
00267   struct sys_timeo *timeout, *t;
00268 
00269   timeout = (struct sys_timeo *)memp_malloc(MEMP_SYS_TIMEOUT);
00270   if (timeout == NULL) {
00271     LWIP_ASSERT("sys_timeout: timeout != NULL, pool MEMP_SYS_TIMEOUT is empty", timeout != NULL);
00272     return;
00273   }
00274   timeout->next = NULL;
00275   timeout->h = handler;
00276   timeout->arg = arg;
00277   timeout->time = msecs;
00278 #if LWIP_DEBUG_TIMERNAMES
00279   timeout->handler_name = handler_name;
00280   LWIP_DEBUGF(TIMERS_DEBUG, ("sys_timeout: %p msecs=%"U32_F" handler=%s arg=%p\n",
00281     (void *)timeout, msecs, handler_name, (void *)arg));
00282 #endif /* LWIP_DEBUG_TIMERNAMES */
00283 
00284   if (next_timeout == NULL) {
00285     next_timeout = timeout;
00286     return;
00287   }
00288 
00289   if (next_timeout->time > msecs) {
00290     next_timeout->time -= msecs;
00291     timeout->next = next_timeout;
00292     next_timeout = timeout;
00293   } else {
00294     for(t = next_timeout; t != NULL; t = t->next) {
00295       timeout->time -= t->time;
00296       if (t->next == NULL || t->next->time > timeout->time) {
00297         if (t->next != NULL) {
00298           t->next->time -= timeout->time;
00299         }
00300         timeout->next = t->next;
00301         t->next = timeout;
00302         break;
00303       }
00304     }
00305   }
00306 }
00307 
00318 void
00319 sys_untimeout(sys_timeout_handler handler, void *arg)
00320 {
00321   struct sys_timeo *prev_t, *t;
00322 
00323   if (next_timeout == NULL) {
00324     return;
00325   }
00326 
00327   for (t = next_timeout, prev_t = NULL; t != NULL; prev_t = t, t = t->next) {
00328     if ((t->h == handler) && (t->arg == arg)) {
00329       /* We have a match */
00330       /* Unlink from previous in list */
00331       if (prev_t == NULL) {
00332         next_timeout = t->next;
00333       } else {
00334         prev_t->next = t->next;
00335       }
00336       /* If not the last one, add time of this one back to next */
00337       if (t->next != NULL) {
00338         t->next->time += t->time;
00339       }
00340       memp_free(MEMP_SYS_TIMEOUT, t);
00341       return;
00342     }
00343   }
00344   return;
00345 }
00346 
00347 #if NO_SYS
00348 
00355 void
00356 sys_check_timeouts(void)
00357 {
00358   struct sys_timeo *tmptimeout;
00359   u32_t diff;
00360   sys_timeout_handler handler;
00361   void *arg;
00362   int had_one;
00363   u32_t now;
00364 
00365   now = sys_now();
00366   if (next_timeout) {
00367     /* this cares for wraparounds */
00368     diff = LWIP_U32_DIFF(now, timeouts_last_time);
00369     do
00370     {
00371       had_one = 0;
00372       tmptimeout = next_timeout;
00373       if (tmptimeout->time <= diff) {
00374         /* timeout has expired */
00375         had_one = 1;
00376         timeouts_last_time = now;
00377         diff -= tmptimeout->time;
00378         next_timeout = tmptimeout->next;
00379         handler = tmptimeout->h;
00380         arg = tmptimeout->arg;
00381 #if LWIP_DEBUG_TIMERNAMES
00382         if (handler != NULL) {
00383           LWIP_DEBUGF(TIMERS_DEBUG, ("sct calling h=%s arg=%p\n",
00384             tmptimeout->handler_name, arg));
00385         }
00386 #endif /* LWIP_DEBUG_TIMERNAMES */
00387         memp_free(MEMP_SYS_TIMEOUT, tmptimeout);
00388         if (handler != NULL) {
00389           handler(arg);
00390         }
00391       }
00392     /* repeat until all expired timers have been called */
00393     }while(had_one);
00394   }
00395 }
00396 
00402 void
00403 sys_restart_timeouts(void)
00404 {
00405   timeouts_last_time = sys_now();
00406 }
00407 
00408 #else /* NO_SYS */
00409 
00417 void
00418 sys_timeouts_mbox_fetch(sys_mbox_t *mbox, void **msg)
00419 {
00420   u32_t time_needed;
00421   struct sys_timeo *tmptimeout;
00422   sys_timeout_handler handler;
00423   void *arg;
00424 
00425  again:
00426   if (!next_timeout) {
00427     time_needed = sys_arch_mbox_fetch(mbox, msg, 0);
00428   } else {
00429     if (next_timeout->time > 0) {
00430       time_needed = sys_arch_mbox_fetch(mbox, msg, next_timeout->time);
00431     } else {
00432       time_needed = SYS_ARCH_TIMEOUT;
00433     }
00434 
00435     if (time_needed == SYS_ARCH_TIMEOUT) {
00436       /* If time == SYS_ARCH_TIMEOUT, a timeout occured before a message
00437          could be fetched. We should now call the timeout handler and
00438          deallocate the memory allocated for the timeout. */
00439       tmptimeout = next_timeout;
00440       next_timeout = tmptimeout->next;
00441       handler = tmptimeout->h;
00442       arg = tmptimeout->arg;
00443 #if LWIP_DEBUG_TIMERNAMES
00444       if (handler != NULL) {
00445         LWIP_DEBUGF(TIMERS_DEBUG, ("stmf calling h=%s arg=%p\n",
00446           tmptimeout->handler_name, arg));
00447       }
00448 #endif /* LWIP_DEBUG_TIMERNAMES */
00449       memp_free(MEMP_SYS_TIMEOUT, tmptimeout);
00450       if (handler != NULL) {
00451         /* For LWIP_TCPIP_CORE_LOCKING, lock the core before calling the
00452            timeout handler function. */
00453         LOCK_TCPIP_CORE();
00454         handler(arg);
00455         UNLOCK_TCPIP_CORE();
00456       }
00457       LWIP_TCPIP_THREAD_ALIVE();
00458 
00459       /* We try again to fetch a message from the mbox. */
00460       goto again;
00461     } else {
00462       /* If time != SYS_ARCH_TIMEOUT, a message was received before the timeout
00463          occured. The time variable is set to the number of
00464          milliseconds we waited for the message. */
00465       if (time_needed < next_timeout->time) {
00466         next_timeout->time -= time_needed;
00467       } else {
00468         next_timeout->time = 0;
00469       }
00470     }
00471   }
00472 }
00473 
00474 #endif /* NO_SYS */
00475 
00476 #else /* LWIP_TIMERS */
00477 /* Satisfy the TCP code which calls this function */
00478 void
00479 tcp_timer_needed(void)
00480 {
00481 }
00482 #endif /* LWIP_TIMERS */

Generated on Thu May 24 2012 04:36:34 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.