Work on bug #52748: the bug in timeouts.c - apply Douglas' patch for absolute timeouts with modification to avoid cyclic timer overload situation

This commit is contained in:
Dirk Ziegelmeier 2018-01-08 12:48:48 +01:00
parent 5eced48869
commit bb0ba64fb0

View File

@ -170,6 +170,50 @@ tcp_timer_needed(void)
} }
#endif /* LWIP_TCP */ #endif /* LWIP_TCP */
static void
#if LWIP_DEBUG_TIMERNAMES
sys_timeout_abs(u32_t abs_time, sys_timeout_handler handler, void *arg, const char *handler_name)
#else /* LWIP_DEBUG_TIMERNAMES */
sys_timeout_abs(u32_t abs_time, sys_timeout_handler handler, void *arg)
#endif
{
struct sys_timeo *timeout, *t;
timeout = (struct sys_timeo *)memp_malloc(MEMP_SYS_TIMEOUT);
if (timeout == NULL) {
LWIP_ASSERT("sys_timeout: timeout != NULL, pool MEMP_SYS_TIMEOUT is empty", timeout != NULL);
return;
}
timeout->next = NULL;
timeout->h = handler;
timeout->arg = arg;
timeout->time = abs_time;
#if LWIP_DEBUG_TIMERNAMES
timeout->handler_name = handler_name;
LWIP_DEBUGF(TIMERS_DEBUG, ("sys_timeout: %p abs_time=%"U32_F" handler=%s arg=%p\n",
(void *)timeout, abs_time, handler_name, (void *)arg));
#endif /* LWIP_DEBUG_TIMERNAMES */
if (next_timeout == NULL) {
next_timeout = timeout;
return;
}
if (TIME_LESS_THAN(timeout->time, next_timeout->time)) {
timeout->next = next_timeout;
next_timeout = timeout;
} else {
for (t = next_timeout; t != NULL; t = t->next) {
if ((t->next == NULL) || TIME_LESS_THAN(timeout->time, t->next->time)) {
timeout->next = t->next;
t->next = timeout;
break;
}
}
}
}
/** /**
* Timer callback function that calls cyclic->handler() and reschedules itself. * Timer callback function that calls cyclic->handler() and reschedules itself.
* *
@ -191,13 +235,22 @@ lwip_cyclic_timer(void *arg)
cyclic->handler(); cyclic->handler();
now = sys_now(); now = sys_now();
next_timeout_time = (u32_t)(current_timeout_due_time + cyclic->interval_ms); next_timeout_time = (u32_t)(current_timeout_due_time + cyclic->interval_ms); /* overflow handled by TIME_LESS_THAN macro */
if (TIME_LESS_THAN(next_timeout_time, now)) { if (TIME_LESS_THAN(next_timeout_time, now)) {
/* timer would immediately expire again -> "overload" -> restart without any correction */ /* timer would immediately expire again -> "overload" -> restart without any correction */
sys_timeout(cyclic->interval_ms, lwip_cyclic_timer, arg); #if LWIP_DEBUG_TIMERNAMES
sys_timeout_abs((u32_t)(now + cyclic->interval_ms), lwip_cyclic_timer, arg, cyclic->handler_name);
#else
sys_timeout_abs((u32_t)(now + cyclic->interval_ms), lwip_cyclic_timer, arg);
#endif
} else { } else {
/* correct cyclic interval with handler execution delay and sys_check_timeouts jitter */ /* correct cyclic interval with handler execution delay and sys_check_timeouts jitter */
sys_timeout((u32_t)(next_timeout_time - now), lwip_cyclic_timer, arg); #if LWIP_DEBUG_TIMERNAMES
sys_timeout_abs(next_timeout_time, lwip_cyclic_timer, arg, cyclic->handler_name);
#else
sys_timeout_abs(next_timeout_time, lwip_cyclic_timer, arg);
#endif
} }
} }
@ -231,45 +284,17 @@ void
sys_timeout(u32_t msecs, sys_timeout_handler handler, void *arg) sys_timeout(u32_t msecs, sys_timeout_handler handler, void *arg)
#endif /* LWIP_DEBUG_TIMERNAMES */ #endif /* LWIP_DEBUG_TIMERNAMES */
{ {
struct sys_timeo *timeout, *t; u32_t next_timeout_time;
u32_t now;
LWIP_ASSERT_CORE_LOCKED(); LWIP_ASSERT_CORE_LOCKED();
timeout = (struct sys_timeo *)memp_malloc(MEMP_SYS_TIMEOUT); next_timeout_time = (u32_t)(sys_now() + msecs); /* overflow handled by TIME_LESS_THAN macro */
if (timeout == NULL) {
LWIP_ASSERT("sys_timeout: timeout != NULL, pool MEMP_SYS_TIMEOUT is empty", timeout != NULL);
return;
}
now = sys_now();
timeout->next = NULL;
timeout->h = handler;
timeout->arg = arg;
timeout->time = (u32_t)(now + msecs); /* overflow handled by TIME_LESS_THAN macro */
#if LWIP_DEBUG_TIMERNAMES #if LWIP_DEBUG_TIMERNAMES
timeout->handler_name = handler_name; sys_timeout_abs(next_timeout_time, handler, arg, handler_name);
LWIP_DEBUGF(TIMERS_DEBUG, ("sys_timeout: %p msecs=%"U32_F" handler=%s arg=%p\n", #else
(void *)timeout, msecs, handler_name, (void *)arg)); sys_timeout_abs(next_timeout_time, handler, arg);
#endif /* LWIP_DEBUG_TIMERNAMES */ #endif
if (next_timeout == NULL) {
next_timeout = timeout;
return;
}
if (TIME_LESS_THAN(timeout->time, next_timeout->time)) {
timeout->next = next_timeout;
next_timeout = timeout;
} else {
for (t = next_timeout; t != NULL; t = t->next) {
if ((t->next == NULL) || TIME_LESS_THAN(timeout->time, t->next->time)) {
timeout->next = t->next;
t->next = timeout;
break;
}
}
}
} }
/** /**