timeouts.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451
  1. /**
  2. * @file
  3. * Stack-internal timers implementation.
  4. * This file includes timer callbacks for stack-internal timers as well as
  5. * functions to set up or stop timers and check for expired timers.
  6. *
  7. */
  8. /*
  9. * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
  10. * All rights reserved.
  11. *
  12. * Redistribution and use in source and binary forms, with or without modification,
  13. * are permitted provided that the following conditions are met:
  14. *
  15. * 1. Redistributions of source code must retain the above copyright notice,
  16. * this list of conditions and the following disclaimer.
  17. * 2. Redistributions in binary form must reproduce the above copyright notice,
  18. * this list of conditions and the following disclaimer in the documentation
  19. * and/or other materials provided with the distribution.
  20. * 3. The name of the author may not be used to endorse or promote products
  21. * derived from this software without specific prior written permission.
  22. *
  23. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
  24. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  25. * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
  26. * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  27. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
  28. * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  29. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  30. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
  31. * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
  32. * OF SUCH DAMAGE.
  33. *
  34. * This file is part of the lwIP TCP/IP stack.
  35. *
  36. * Author: Adam Dunkels <adam@sics.se>
  37. * Simon Goldschmidt
  38. *
  39. */
  40. #include "lwip/opt.h"
  41. #include "lwip/timeouts.h"
  42. #include "lwip/priv/tcp_priv.h"
  43. #include "lwip/def.h"
  44. #include "lwip/memp.h"
  45. #include "lwip/priv/tcpip_priv.h"
  46. #include "lwip/ip4_frag.h"
  47. #include "lwip/etharp.h"
  48. #include "lwip/dhcp.h"
  49. #include "lwip/acd.h"
  50. #include "lwip/igmp.h"
  51. #include "lwip/dns.h"
  52. #include "lwip/nd6.h"
  53. #include "lwip/ip6_frag.h"
  54. #include "lwip/mld6.h"
  55. #include "lwip/dhcp6.h"
  56. #include "lwip/sys.h"
  57. #include "lwip/pbuf.h"
  58. #if LWIP_DEBUG_TIMERNAMES
  59. #define HANDLER(x) x, #x
  60. #else /* LWIP_DEBUG_TIMERNAMES */
  61. #define HANDLER(x) x
  62. #endif /* LWIP_DEBUG_TIMERNAMES */
  63. #define LWIP_MAX_TIMEOUT 0x7fffffff
  64. /* Check if timer's expiry time is greater than time and care about u32_t wraparounds */
  65. #define TIME_LESS_THAN(t, compare_to) ( (((u32_t)((t)-(compare_to))) > LWIP_MAX_TIMEOUT) ? 1 : 0 )
  66. /** This array contains all stack-internal cyclic timers. To get the number of
  67. * timers, use LWIP_ARRAYSIZE() */
  68. const struct lwip_cyclic_timer lwip_cyclic_timers[] = {
  69. #if LWIP_TCP
  70. /* The TCP timer is a special case: it does not have to run always and
  71. is triggered to start from TCP using tcp_timer_needed() */
  72. {TCP_TMR_INTERVAL, HANDLER(tcp_tmr)},
  73. #endif /* LWIP_TCP */
  74. #if LWIP_IPV4
  75. #if IP_REASSEMBLY
  76. {IP_TMR_INTERVAL, HANDLER(ip_reass_tmr)},
  77. #endif /* IP_REASSEMBLY */
  78. #if LWIP_ARP
  79. {ARP_TMR_INTERVAL, HANDLER(etharp_tmr)},
  80. #endif /* LWIP_ARP */
  81. #if LWIP_DHCP
  82. {DHCP_COARSE_TIMER_MSECS, HANDLER(dhcp_coarse_tmr)},
  83. {DHCP_FINE_TIMER_MSECS, HANDLER(dhcp_fine_tmr)},
  84. #endif /* LWIP_DHCP */
  85. #if LWIP_ACD
  86. {ACD_TMR_INTERVAL, HANDLER(acd_tmr)},
  87. #endif /* LWIP_ACD */
  88. #if LWIP_IGMP
  89. {IGMP_TMR_INTERVAL, HANDLER(igmp_tmr)},
  90. #endif /* LWIP_IGMP */
  91. #endif /* LWIP_IPV4 */
  92. #if LWIP_DNS
  93. {DNS_TMR_INTERVAL, HANDLER(dns_tmr)},
  94. #endif /* LWIP_DNS */
  95. #if LWIP_IPV6
  96. {ND6_TMR_INTERVAL, HANDLER(nd6_tmr)},
  97. #if LWIP_IPV6_REASS
  98. {IP6_REASS_TMR_INTERVAL, HANDLER(ip6_reass_tmr)},
  99. #endif /* LWIP_IPV6_REASS */
  100. #if LWIP_IPV6_MLD
  101. {MLD6_TMR_INTERVAL, HANDLER(mld6_tmr)},
  102. #endif /* LWIP_IPV6_MLD */
  103. #if LWIP_IPV6_DHCP6
  104. {DHCP6_TIMER_MSECS, HANDLER(dhcp6_tmr)},
  105. #endif /* LWIP_IPV6_DHCP6 */
  106. #endif /* LWIP_IPV6 */
  107. };
  108. const int lwip_num_cyclic_timers = LWIP_ARRAYSIZE(lwip_cyclic_timers);
  109. #if LWIP_TIMERS && !LWIP_TIMERS_CUSTOM
  110. /** The one and only timeout list */
  111. static struct sys_timeo *next_timeout;
  112. static u32_t current_timeout_due_time;
  113. #if LWIP_TESTMODE
  114. struct sys_timeo**
  115. sys_timeouts_get_next_timeout(void)
  116. {
  117. return &next_timeout;
  118. }
  119. #endif
  120. #if LWIP_TCP
  121. /** global variable that shows if the tcp timer is currently scheduled or not */
  122. static int tcpip_tcp_timer_active;
  123. /**
  124. * Timer callback function that calls tcp_tmr() and reschedules itself.
  125. *
  126. * @param arg unused argument
  127. */
  128. static void
  129. tcpip_tcp_timer(void *arg)
  130. {
  131. LWIP_UNUSED_ARG(arg);
  132. /* call TCP timer handler */
  133. tcp_tmr();
  134. /* timer still needed? */
  135. if (tcp_active_pcbs || tcp_tw_pcbs) {
  136. /* restart timer */
  137. sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL);
  138. } else {
  139. /* disable timer */
  140. tcpip_tcp_timer_active = 0;
  141. }
  142. }
  143. /**
  144. * Called from TCP_REG when registering a new PCB:
  145. * the reason is to have the TCP timer only running when
  146. * there are active (or time-wait) PCBs.
  147. */
  148. void
  149. tcp_timer_needed(void)
  150. {
  151. LWIP_ASSERT_CORE_LOCKED();
  152. /* timer is off but needed again? */
  153. if (!tcpip_tcp_timer_active && (tcp_active_pcbs || tcp_tw_pcbs)) {
  154. /* enable and start timer */
  155. tcpip_tcp_timer_active = 1;
  156. sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL);
  157. }
  158. }
  159. #endif /* LWIP_TCP */
  160. static void
  161. #if LWIP_DEBUG_TIMERNAMES
  162. sys_timeout_abs(u32_t abs_time, sys_timeout_handler handler, void *arg, const char *handler_name)
  163. #else /* LWIP_DEBUG_TIMERNAMES */
  164. sys_timeout_abs(u32_t abs_time, sys_timeout_handler handler, void *arg)
  165. #endif
  166. {
  167. struct sys_timeo *timeout, *t;
  168. timeout = (struct sys_timeo *)memp_malloc(MEMP_SYS_TIMEOUT);
  169. if (timeout == NULL) {
  170. LWIP_ASSERT("sys_timeout: timeout != NULL, pool MEMP_SYS_TIMEOUT is empty", timeout != NULL);
  171. return;
  172. }
  173. timeout->next = NULL;
  174. timeout->h = handler;
  175. timeout->arg = arg;
  176. timeout->time = abs_time;
  177. #if LWIP_DEBUG_TIMERNAMES
  178. timeout->handler_name = handler_name;
  179. LWIP_DEBUGF(TIMERS_DEBUG, ("sys_timeout: %p abs_time=%"U32_F" handler=%s arg=%p\n",
  180. (void *)timeout, abs_time, handler_name, (void *)arg));
  181. #endif /* LWIP_DEBUG_TIMERNAMES */
  182. if (next_timeout == NULL) {
  183. next_timeout = timeout;
  184. return;
  185. }
  186. if (TIME_LESS_THAN(timeout->time, next_timeout->time)) {
  187. timeout->next = next_timeout;
  188. next_timeout = timeout;
  189. } else {
  190. for (t = next_timeout; t != NULL; t = t->next) {
  191. if ((t->next == NULL) || TIME_LESS_THAN(timeout->time, t->next->time)) {
  192. timeout->next = t->next;
  193. t->next = timeout;
  194. break;
  195. }
  196. }
  197. }
  198. }
  199. /**
  200. * Timer callback function that calls cyclic->handler() and reschedules itself.
  201. *
  202. * @param arg unused argument
  203. */
  204. #if !LWIP_TESTMODE
  205. static
  206. #endif
  207. void
  208. lwip_cyclic_timer(void *arg)
  209. {
  210. u32_t now;
  211. u32_t next_timeout_time;
  212. const struct lwip_cyclic_timer *cyclic = (const struct lwip_cyclic_timer *)arg;
  213. #if LWIP_DEBUG_TIMERNAMES
  214. LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: %s()\n", cyclic->handler_name));
  215. #endif
  216. cyclic->handler();
  217. now = sys_now();
  218. next_timeout_time = (u32_t)(current_timeout_due_time + cyclic->interval_ms); /* overflow handled by TIME_LESS_THAN macro */
  219. if (TIME_LESS_THAN(next_timeout_time, now)) {
  220. /* timer would immediately expire again -> "overload" -> restart without any correction */
  221. #if LWIP_DEBUG_TIMERNAMES
  222. sys_timeout_abs((u32_t)(now + cyclic->interval_ms), lwip_cyclic_timer, arg, cyclic->handler_name);
  223. #else
  224. sys_timeout_abs((u32_t)(now + cyclic->interval_ms), lwip_cyclic_timer, arg);
  225. #endif
  226. } else {
  227. /* correct cyclic interval with handler execution delay and sys_check_timeouts jitter */
  228. #if LWIP_DEBUG_TIMERNAMES
  229. sys_timeout_abs(next_timeout_time, lwip_cyclic_timer, arg, cyclic->handler_name);
  230. #else
  231. sys_timeout_abs(next_timeout_time, lwip_cyclic_timer, arg);
  232. #endif
  233. }
  234. }
  235. /** Initialize this module */
  236. void sys_timeouts_init(void)
  237. {
  238. size_t i;
  239. /* tcp_tmr() at index 0 is started on demand */
  240. for (i = (LWIP_TCP ? 1 : 0); i < LWIP_ARRAYSIZE(lwip_cyclic_timers); i++) {
  241. /* we have to cast via size_t to get rid of const warning
  242. (this is OK as cyclic_timer() casts back to const* */
  243. sys_timeout(lwip_cyclic_timers[i].interval_ms, lwip_cyclic_timer, LWIP_CONST_CAST(void *, &lwip_cyclic_timers[i]));
  244. }
  245. }
  246. /**
  247. * Create a one-shot timer (aka timeout). Timeouts are processed in the
  248. * following cases:
  249. * - while waiting for a message using sys_timeouts_mbox_fetch()
  250. * - by calling sys_check_timeouts() (NO_SYS==1 only)
  251. *
  252. * @param msecs time in milliseconds after that the timer should expire
  253. * @param handler callback function to call when msecs have elapsed
  254. * @param arg argument to pass to the callback function
  255. */
  256. #if LWIP_DEBUG_TIMERNAMES
  257. void
  258. sys_timeout_debug(u32_t msecs, sys_timeout_handler handler, void *arg, const char *handler_name)
  259. #else /* LWIP_DEBUG_TIMERNAMES */
  260. void
  261. sys_timeout(u32_t msecs, sys_timeout_handler handler, void *arg)
  262. #endif /* LWIP_DEBUG_TIMERNAMES */
  263. {
  264. u32_t next_timeout_time;
  265. LWIP_ASSERT_CORE_LOCKED();
  266. LWIP_ASSERT("Timeout time too long, max is LWIP_UINT32_MAX/4 msecs", msecs <= (LWIP_UINT32_MAX / 4));
  267. next_timeout_time = (u32_t)(sys_now() + msecs); /* overflow handled by TIME_LESS_THAN macro */
  268. #if LWIP_DEBUG_TIMERNAMES
  269. sys_timeout_abs(next_timeout_time, handler, arg, handler_name);
  270. #else
  271. sys_timeout_abs(next_timeout_time, handler, arg);
  272. #endif
  273. }
  274. /**
  275. * Go through timeout list (for this task only) and remove the first matching
  276. * entry (subsequent entries remain untouched), even though the timeout has not
  277. * triggered yet.
  278. *
  279. * @param handler callback function that would be called by the timeout
  280. * @param arg callback argument that would be passed to handler
  281. */
  282. void
  283. sys_untimeout(sys_timeout_handler handler, void *arg)
  284. {
  285. struct sys_timeo *prev_t, *t;
  286. LWIP_ASSERT_CORE_LOCKED();
  287. if (next_timeout == NULL) {
  288. return;
  289. }
  290. for (t = next_timeout, prev_t = NULL; t != NULL; prev_t = t, t = t->next) {
  291. if ((t->h == handler) && (t->arg == arg)) {
  292. /* We have a match */
  293. /* Unlink from previous in list */
  294. if (prev_t == NULL) {
  295. next_timeout = t->next;
  296. } else {
  297. prev_t->next = t->next;
  298. }
  299. memp_free(MEMP_SYS_TIMEOUT, t);
  300. return;
  301. }
  302. }
  303. return;
  304. }
  305. /**
  306. * @ingroup lwip_nosys
  307. * Handle timeouts for NO_SYS==1 (i.e. without using
  308. * tcpip_thread/sys_timeouts_mbox_fetch(). Uses sys_now() to call timeout
  309. * handler functions when timeouts expire.
  310. *
  311. * Must be called periodically from your main loop.
  312. */
  313. void
  314. sys_check_timeouts(void)
  315. {
  316. u32_t now;
  317. LWIP_ASSERT_CORE_LOCKED();
  318. /* Process only timers expired at the start of the function. */
  319. now = sys_now();
  320. do {
  321. struct sys_timeo *tmptimeout;
  322. sys_timeout_handler handler;
  323. void *arg;
  324. PBUF_CHECK_FREE_OOSEQ();
  325. tmptimeout = next_timeout;
  326. if (tmptimeout == NULL) {
  327. return;
  328. }
  329. if (TIME_LESS_THAN(now, tmptimeout->time)) {
  330. return;
  331. }
  332. /* Timeout has expired */
  333. next_timeout = tmptimeout->next;
  334. handler = tmptimeout->h;
  335. arg = tmptimeout->arg;
  336. current_timeout_due_time = tmptimeout->time;
  337. #if LWIP_DEBUG_TIMERNAMES
  338. if (handler != NULL) {
  339. LWIP_DEBUGF(TIMERS_DEBUG, ("sct calling h=%s t=%"U32_F" arg=%p\n",
  340. tmptimeout->handler_name, sys_now() - tmptimeout->time, arg));
  341. }
  342. #endif /* LWIP_DEBUG_TIMERNAMES */
  343. memp_free(MEMP_SYS_TIMEOUT, tmptimeout);
  344. if (handler != NULL) {
  345. handler(arg);
  346. }
  347. LWIP_TCPIP_THREAD_ALIVE();
  348. /* Repeat until all expired timers have been called */
  349. } while (1);
  350. }
  351. /** Rebase the timeout times to the current time.
  352. * This is necessary if sys_check_timeouts() hasn't been called for a long
  353. * time (e.g. while saving energy) to prevent all timer functions of that
  354. * period being called.
  355. */
  356. void
  357. sys_restart_timeouts(void)
  358. {
  359. u32_t now;
  360. u32_t base;
  361. struct sys_timeo *t;
  362. if (next_timeout == NULL) {
  363. return;
  364. }
  365. now = sys_now();
  366. base = next_timeout->time;
  367. for (t = next_timeout; t != NULL; t = t->next) {
  368. t->time = (t->time - base) + now;
  369. }
  370. }
  371. /** Return the time left before the next timeout is due. If no timeouts are
  372. * enqueued, returns 0xffffffff
  373. */
  374. u32_t
  375. sys_timeouts_sleeptime(void)
  376. {
  377. u32_t now;
  378. LWIP_ASSERT_CORE_LOCKED();
  379. if (next_timeout == NULL) {
  380. return SYS_TIMEOUTS_SLEEPTIME_INFINITE;
  381. }
  382. now = sys_now();
  383. if (TIME_LESS_THAN(next_timeout->time, now)) {
  384. return 0;
  385. } else {
  386. u32_t ret = (u32_t)(next_timeout->time - now);
  387. LWIP_ASSERT("invalid sleeptime", ret <= LWIP_MAX_TIMEOUT);
  388. return ret;
  389. }
  390. }
  391. #else /* LWIP_TIMERS && !LWIP_TIMERS_CUSTOM */
  392. /* Satisfy the TCP code which calls this function */
  393. void
  394. tcp_timer_needed(void)
  395. {
  396. }
  397. #endif /* LWIP_TIMERS && !LWIP_TIMERS_CUSTOM */