ReactOS 0.4.16-dev-736-g28b802b
timeouts.c
Go to the documentation of this file.
1
9/*
10 * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
11 * All rights reserved.
12 *
13 * Redistribution and use in source and binary forms, with or without modification,
14 * are permitted provided that the following conditions are met:
15 *
16 * 1. Redistributions of source code must retain the above copyright notice,
17 * this list of conditions and the following disclaimer.
18 * 2. Redistributions in binary form must reproduce the above copyright notice,
19 * this list of conditions and the following disclaimer in the documentation
20 * and/or other materials provided with the distribution.
21 * 3. The name of the author may not be used to endorse or promote products
22 * derived from this software without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
25 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
26 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
27 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
28 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
29 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
32 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
33 * OF SUCH DAMAGE.
34 *
35 * This file is part of the lwIP TCP/IP stack.
36 *
37 * Author: Adam Dunkels <adam@sics.se>
38 * Simon Goldschmidt
39 *
40 */
41
42#include "lwip/opt.h"
43
44#include "lwip/timeouts.h"
45#include "lwip/priv/tcp_priv.h"
46
47#include "lwip/def.h"
48#include "lwip/memp.h"
50
51#include "lwip/ip4_frag.h"
52#include "lwip/etharp.h"
53#include "lwip/dhcp.h"
54#include "lwip/acd.h"
55#include "lwip/igmp.h"
56#include "lwip/dns.h"
57#include "lwip/nd6.h"
58#include "lwip/ip6_frag.h"
59#include "lwip/mld6.h"
60#include "lwip/dhcp6.h"
61#include "lwip/sys.h"
62#include "lwip/pbuf.h"
63
64#if LWIP_DEBUG_TIMERNAMES
65#define HANDLER(x) x, #x
66#else /* LWIP_DEBUG_TIMERNAMES */
67#define HANDLER(x) x
68#endif /* LWIP_DEBUG_TIMERNAMES */
69
70#define LWIP_MAX_TIMEOUT 0x7fffffff
71
72/* Check if timer's expiry time is greater than time and care about u32_t wraparounds */
73#define TIME_LESS_THAN(t, compare_to) ( (((u32_t)((t)-(compare_to))) > LWIP_MAX_TIMEOUT) ? 1 : 0 )
74
78#if LWIP_TCP
79 /* The TCP timer is a special case: it does not have to run always and
80 is triggered to start from TCP using tcp_timer_needed() */
81 {TCP_TMR_INTERVAL, HANDLER(tcp_tmr)},
82#endif /* LWIP_TCP */
83#if LWIP_IPV4
84#if IP_REASSEMBLY
85 {IP_TMR_INTERVAL, HANDLER(ip_reass_tmr)},
86#endif /* IP_REASSEMBLY */
87#if LWIP_ARP
88 {ARP_TMR_INTERVAL, HANDLER(etharp_tmr)},
89#endif /* LWIP_ARP */
90#if LWIP_DHCP
91 {DHCP_COARSE_TIMER_MSECS, HANDLER(dhcp_coarse_tmr)},
92 {DHCP_FINE_TIMER_MSECS, HANDLER(dhcp_fine_tmr)},
93#endif /* LWIP_DHCP */
94#if LWIP_ACD
95 {ACD_TMR_INTERVAL, HANDLER(acd_tmr)},
96#endif /* LWIP_ACD */
97#if LWIP_IGMP
98 {IGMP_TMR_INTERVAL, HANDLER(igmp_tmr)},
99#endif /* LWIP_IGMP */
100#endif /* LWIP_IPV4 */
101#if LWIP_DNS
102 {DNS_TMR_INTERVAL, HANDLER(dns_tmr)},
103#endif /* LWIP_DNS */
104#if LWIP_IPV6
105 {ND6_TMR_INTERVAL, HANDLER(nd6_tmr)},
106#if LWIP_IPV6_REASS
107 {IP6_REASS_TMR_INTERVAL, HANDLER(ip6_reass_tmr)},
108#endif /* LWIP_IPV6_REASS */
109#if LWIP_IPV6_MLD
110 {MLD6_TMR_INTERVAL, HANDLER(mld6_tmr)},
111#endif /* LWIP_IPV6_MLD */
112#if LWIP_IPV6_DHCP6
113 {DHCP6_TIMER_MSECS, HANDLER(dhcp6_tmr)},
114#endif /* LWIP_IPV6_DHCP6 */
115#endif /* LWIP_IPV6 */
116};
118
119#if LWIP_TIMERS && !LWIP_TIMERS_CUSTOM
120
122static struct sys_timeo *next_timeout;
123
124static u32_t current_timeout_due_time;
125
126#if LWIP_TESTMODE
127struct sys_timeo**
128sys_timeouts_get_next_timeout(void)
129{
130 return &next_timeout;
131}
132#endif
133
134#if LWIP_TCP
136static int tcpip_tcp_timer_active;
137
143static void
144tcpip_tcp_timer(void *arg)
145{
147
148 /* call TCP timer handler */
149 tcp_tmr();
150 /* timer still needed? */
151 if (tcp_active_pcbs || tcp_tw_pcbs) {
152 /* restart timer */
153 sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL);
154 } else {
155 /* disable timer */
156 tcpip_tcp_timer_active = 0;
157 }
158}
159
165void
167{
169
170 /* timer is off but needed again? */
171 if (!tcpip_tcp_timer_active && (tcp_active_pcbs || tcp_tw_pcbs)) {
172 /* enable and start timer */
173 tcpip_tcp_timer_active = 1;
174 sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL);
175 }
176}
177#endif /* LWIP_TCP */
178
179static void
180#if LWIP_DEBUG_TIMERNAMES
181sys_timeout_abs(u32_t abs_time, sys_timeout_handler handler, void *arg, const char *handler_name)
182#else /* LWIP_DEBUG_TIMERNAMES */
183sys_timeout_abs(u32_t abs_time, sys_timeout_handler handler, void *arg)
184#endif
185{
186 struct sys_timeo *timeout, *t;
187
188 timeout = (struct sys_timeo *)memp_malloc(MEMP_SYS_TIMEOUT);
189 if (timeout == NULL) {
190 LWIP_ASSERT("sys_timeout: timeout != NULL, pool MEMP_SYS_TIMEOUT is empty", timeout != NULL);
191 return;
192 }
193
194 timeout->next = NULL;
195 timeout->h = handler;
196 timeout->arg = arg;
197 timeout->time = abs_time;
198
199#if LWIP_DEBUG_TIMERNAMES
200 timeout->handler_name = handler_name;
201 LWIP_DEBUGF(TIMERS_DEBUG, ("sys_timeout: %p abs_time=%"U32_F" handler=%s arg=%p\n",
202 (void *)timeout, abs_time, handler_name, (void *)arg));
203#endif /* LWIP_DEBUG_TIMERNAMES */
204
205 if (next_timeout == NULL) {
206 next_timeout = timeout;
207 return;
208 }
209 if (TIME_LESS_THAN(timeout->time, next_timeout->time)) {
210 timeout->next = next_timeout;
211 next_timeout = timeout;
212 } else {
213 for (t = next_timeout; t != NULL; t = t->next) {
214 if ((t->next == NULL) || TIME_LESS_THAN(timeout->time, t->next->time)) {
215 timeout->next = t->next;
216 t->next = timeout;
217 break;
218 }
219 }
220 }
221}
222
228#if !LWIP_TESTMODE
229static
230#endif
231void
233{
234 u32_t now;
235 u32_t next_timeout_time;
236 const struct lwip_cyclic_timer *cyclic = (const struct lwip_cyclic_timer *)arg;
237
238#if LWIP_DEBUG_TIMERNAMES
239 LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: %s()\n", cyclic->handler_name));
240#endif
241 cyclic->handler();
242
243 now = sys_now();
244 next_timeout_time = (u32_t)(current_timeout_due_time + cyclic->interval_ms); /* overflow handled by TIME_LESS_THAN macro */
245 if (TIME_LESS_THAN(next_timeout_time, now)) {
246 /* timer would immediately expire again -> "overload" -> restart without any correction */
247#if LWIP_DEBUG_TIMERNAMES
248 sys_timeout_abs((u32_t)(now + cyclic->interval_ms), lwip_cyclic_timer, arg, cyclic->handler_name);
249#else
250 sys_timeout_abs((u32_t)(now + cyclic->interval_ms), lwip_cyclic_timer, arg);
251#endif
252
253 } else {
254 /* correct cyclic interval with handler execution delay and sys_check_timeouts jitter */
255#if LWIP_DEBUG_TIMERNAMES
256 sys_timeout_abs(next_timeout_time, lwip_cyclic_timer, arg, cyclic->handler_name);
257#else
258 sys_timeout_abs(next_timeout_time, lwip_cyclic_timer, arg);
259#endif
260 }
261}
262
264void sys_timeouts_init(void)
265{
266 size_t i;
267 /* tcp_tmr() at index 0 is started on demand */
268 for (i = (LWIP_TCP ? 1 : 0); i < LWIP_ARRAYSIZE(lwip_cyclic_timers); i++) {
269 /* we have to cast via size_t to get rid of const warning
270 (this is OK as cyclic_timer() casts back to const* */
272 }
273}
274
285#if LWIP_DEBUG_TIMERNAMES
286void
287sys_timeout_debug(u32_t msecs, sys_timeout_handler handler, void *arg, const char *handler_name)
288#else /* LWIP_DEBUG_TIMERNAMES */
289void
290sys_timeout(u32_t msecs, sys_timeout_handler handler, void *arg)
291#endif /* LWIP_DEBUG_TIMERNAMES */
292{
293 u32_t next_timeout_time;
294
296
297 LWIP_ASSERT("Timeout time too long, max is LWIP_UINT32_MAX/4 msecs", msecs <= (LWIP_UINT32_MAX / 4));
298
299 next_timeout_time = (u32_t)(sys_now() + msecs); /* overflow handled by TIME_LESS_THAN macro */
300
301#if LWIP_DEBUG_TIMERNAMES
302 sys_timeout_abs(next_timeout_time, handler, arg, handler_name);
303#else
304 sys_timeout_abs(next_timeout_time, handler, arg);
305#endif
306}
307
316void
317sys_untimeout(sys_timeout_handler handler, void *arg)
318{
319 struct sys_timeo *prev_t, *t;
320
322
323 if (next_timeout == NULL) {
324 return;
325 }
326
327 for (t = next_timeout, prev_t = NULL; t != NULL; prev_t = t, t = t->next) {
328 if ((t->h == handler) && (t->arg == arg)) {
329 /* We have a match */
330 /* Unlink from previous in list */
331 if (prev_t == NULL) {
332 next_timeout = t->next;
333 } else {
334 prev_t->next = t->next;
335 }
336 memp_free(MEMP_SYS_TIMEOUT, t);
337 return;
338 }
339 }
340 return;
341}
342
351void
352sys_check_timeouts(void)
353{
354 u32_t now;
355
357
358 /* Process only timers expired at the start of the function. */
359 now = sys_now();
360
361 do {
362 struct sys_timeo *tmptimeout;
363 sys_timeout_handler handler;
364 void *arg;
365
367
368 tmptimeout = next_timeout;
369 if (tmptimeout == NULL) {
370 return;
371 }
372
373 if (TIME_LESS_THAN(now, tmptimeout->time)) {
374 return;
375 }
376
377 /* Timeout has expired */
378 next_timeout = tmptimeout->next;
379 handler = tmptimeout->h;
380 arg = tmptimeout->arg;
381 current_timeout_due_time = tmptimeout->time;
382#if LWIP_DEBUG_TIMERNAMES
383 if (handler != NULL) {
384 LWIP_DEBUGF(TIMERS_DEBUG, ("sct calling h=%s t=%"U32_F" arg=%p\n",
385 tmptimeout->handler_name, sys_now() - tmptimeout->time, arg));
386 }
387#endif /* LWIP_DEBUG_TIMERNAMES */
388 memp_free(MEMP_SYS_TIMEOUT, tmptimeout);
389 if (handler != NULL) {
390 handler(arg);
391 }
393
394 /* Repeat until all expired timers have been called */
395 } while (1);
396}
397
403void
404sys_restart_timeouts(void)
405{
406 u32_t now;
407 u32_t base;
408 struct sys_timeo *t;
409
410 if (next_timeout == NULL) {
411 return;
412 }
413
414 now = sys_now();
415 base = next_timeout->time;
416
417 for (t = next_timeout; t != NULL; t = t->next) {
418 t->time = (t->time - base) + now;
419 }
420}
421
425u32_t
426sys_timeouts_sleeptime(void)
427{
428 u32_t now;
429
431
432 if (next_timeout == NULL) {
434 }
435 now = sys_now();
436 if (TIME_LESS_THAN(next_timeout->time, now)) {
437 return 0;
438 } else {
439 u32_t ret = (u32_t)(next_timeout->time - now);
440 LWIP_ASSERT("invalid sleeptime", ret <= LWIP_MAX_TIMEOUT);
441 return ret;
442 }
443}
444
445#else /* LWIP_TIMERS && !LWIP_TIMERS_CUSTOM */
446/* Satisfy the TCP code which calls this function */
447void
449{
450}
451#endif /* LWIP_TIMERS && !LWIP_TIMERS_CUSTOM */
#define LWIP_ARRAYSIZE(x)
Definition: def.h:69
#define NULL
Definition: types.h:112
UINT(* handler)(MSIPACKAGE *)
Definition: action.c:7512
#define U32_F
Definition: cc.h:22
#define LWIP_DEBUGF(debug, message)
Definition: debug.h:158
#define LWIP_ASSERT(message, assertion)
Definition: debug.h:116
time_t now
Definition: finger.c:65
GLdouble GLdouble t
Definition: gl.h:2047
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
uint32_t u32_t
Definition: arch.h:129
#define LWIP_UNUSED_ARG(x)
Definition: arch.h:373
#define LWIP_CONST_CAST(target_type, val)
Definition: arch.h:240
#define LWIP_UINT32_MAX
Definition: arch.h:207
#define TIMERS_DEBUG
Definition: opt.h:3434
#define LWIP_ASSERT_CORE_LOCKED()
Definition: opt.h:227
#define LWIP_TCP
Definition: opt.h:1263
#define LWIP_TCPIP_THREAD_ALIVE()
Definition: opt.h:1842
u32_t sys_now(void)
Definition: sys_arch.c:23
void * memp_malloc(memp_t type)
Definition: memp.c:337
void memp_free(memp_t type, void *mem)
Definition: memp.c:420
#define PBUF_CHECK_FREE_OOSEQ()
Definition: pbuf.h:269
struct define * next
Definition: compiler.c:65
lwip_cyclic_timer_handler handler
Definition: timeouts.h:72
u32_t interval_ms
Definition: timeouts.h:71
Definition: dhcpd.h:245
struct timeout * next
Definition: dhcpd.h:246
#define LWIP_MAX_TIMEOUT
Definition: timeouts.c:70
void tcp_timer_needed(void)
Definition: timeouts.c:448
const int lwip_num_cyclic_timers
Definition: timeouts.c:117
#define HANDLER(x)
Definition: timeouts.c:67
#define TIME_LESS_THAN(t, compare_to)
Definition: timeouts.c:73
const struct lwip_cyclic_timer lwip_cyclic_timers[]
Definition: timeouts.c:77
#define SYS_TIMEOUTS_SLEEPTIME_INFINITE
Definition: timeouts.h:62
int ret
void * arg
Definition: msvc.h:10