/** * Wait (forever) for a message to arrive in an mbox. * While waiting, timeouts are processed. * * @param mbox the mbox to fetch the message from * @param msg the place to store the message */ void sys_timeouts_mbox_fetch_p(u8 timeo_assigned, sys_mbox_t mbox, void **msg) { u32_t time_needed; struct sys_timeo *tmptimeout; sys_timeout_handler handler; void *arg; struct sys_timeo **timeo = &next_timeout[timeo_assigned]; again: if (!(*timeo)) { time_needed = sys_arch_mbox_fetch(mbox, msg, 0); } else { if ((*timeo)->time > 0) { time_needed = sys_arch_mbox_fetch(mbox, msg, (*timeo)->time); } else { time_needed = SYS_ARCH_TIMEOUT; } if (time_needed == SYS_ARCH_TIMEOUT) { /* If time == SYS_ARCH_TIMEOUT, a timeout occured before a message could be fetched. We should now call the timeout handler and deallocate the memory allocated for the timeout. */ tmptimeout = *timeo; *timeo = tmptimeout->next; handler = tmptimeout->h; arg = tmptimeout->arg; #if LWIP_DEBUG_TIMERNAMES if (handler != NULL) { LWIP_DEBUGF(TIMERS_DEBUG, ("stmf calling h=%s arg=%p\n", tmptimeout->handler_name, arg)); } #endif /* LWIP_DEBUG_TIMERNAMES */ memp_free(MEMP_SYS_TIMEOUT, tmptimeout); if (handler != NULL) { /* For LWIP_TCPIP_CORE_LOCKING, lock the core before calling the timeout handler function. */ LOCK_TCPIP_CORE(); handler(arg); UNLOCK_TCPIP_CORE(); } LWIP_TCPIP_THREAD_ALIVE(); /* We try again to fetch a message from the mbox. */ goto again; } else { /* If time != SYS_ARCH_TIMEOUT, a message was received before the timeout occured. The time variable is set to the number of milliseconds we waited for the message. */ if (time_needed < (*timeo)->time) { (*timeo)->time -= time_needed; } else { (*timeo)->time = 0; } } } }
static #endif /* !NO_SYS */ void sys_check_timeouts(void) { if (next_timeout) { struct sys_timeo *tmptimeout; u32_t diff; sys_timeout_handler handler; void *arg; u8_t had_one; u32_t now; now = sys_now(); /* this cares for wraparounds */ diff = now - timeouts_last_time; do { PBUF_CHECK_FREE_OOSEQ(); had_one = 0; tmptimeout = next_timeout; if (tmptimeout && (tmptimeout->time <= diff)) { /* timeout has expired */ had_one = 1; timeouts_last_time += tmptimeout->time; diff -= tmptimeout->time; next_timeout = tmptimeout->next; handler = tmptimeout->h; arg = tmptimeout->arg; #if LWIP_DEBUG_TIMERNAMES if (handler != NULL) { LWIP_DEBUGF(TIMERS_DEBUG, ("sct calling h=%s arg=%p\n", tmptimeout->handler_name, arg)); } #endif /* LWIP_DEBUG_TIMERNAMES */ memp_free(MEMP_SYS_TIMEOUT, tmptimeout); if (handler != NULL) { #if !NO_SYS /* For LWIP_TCPIP_CORE_LOCKING, lock the core before calling the timeout handler function. */ LOCK_TCPIP_CORE(); #endif /* !NO_SYS */ handler(arg); #if !NO_SYS UNLOCK_TCPIP_CORE(); #endif /* !NO_SYS */ } LWIP_TCPIP_THREAD_ALIVE(); } /* repeat until all expired timers have been called */ } while (had_one); } }
/** * @ingroup lwip_nosys * Handle timeouts for NO_SYS==1 (i.e. without using * tcpip_thread/sys_timeouts_mbox_fetch(). Uses sys_now() to call timeout * handler functions when timeouts expire. * * Must be called periodically from your main loop. */ void sys_check_timeouts(void) { u32_t now; LWIP_ASSERT_CORE_LOCKED(); /* Process only timers expired at the start of the function. */ now = sys_now(); do { struct sys_timeo *tmptimeout; sys_timeout_handler handler; void *arg; PBUF_CHECK_FREE_OOSEQ(); tmptimeout = next_timeout; if (tmptimeout == NULL) { return; } if (TIME_LESS_THAN(now, tmptimeout->time)) { return; } /* Timeout has expired */ next_timeout = tmptimeout->next; handler = tmptimeout->h; arg = tmptimeout->arg; current_timeout_due_time = tmptimeout->time; #if LWIP_DEBUG_TIMERNAMES if (handler != NULL) { LWIP_DEBUGF(TIMERS_DEBUG, ("sct calling h=%s t=%"U32_F" arg=%p\n", tmptimeout->handler_name, sys_now() - tmptimeout->time, arg)); } #endif /* LWIP_DEBUG_TIMERNAMES */ memp_free(MEMP_SYS_TIMEOUT, tmptimeout); if (handler != NULL) { handler(arg); } LWIP_TCPIP_THREAD_ALIVE(); /* Repeat until all expired timers have been called */ } while (1); }
/** * The main lwIP thread. This thread has exclusive access to lwIP core functions * (unless access to them is not locked). Other threads communicate with this * thread using message boxes. * * It also starts all the timers to make sure they are running in the right * thread context. * * @param arg unused argument */ static void tcpip_thread(void *arg) { struct tcpip_msg *msg; LWIP_UNUSED_ARG(arg); if (tcpip_init_done != NULL) { tcpip_init_done(tcpip_init_done_arg); } LOCK_TCPIP_CORE(); while (1) { /* MAIN Loop */ UNLOCK_TCPIP_CORE(); LWIP_TCPIP_THREAD_ALIVE(); /* wait for a message, timeouts are processed while waiting */ sys_timeouts_mbox_fetch(&mbox, (void **)&msg); LOCK_TCPIP_CORE(); switch (msg->type) { #if LWIP_NETCONN case TCPIP_MSG_API: LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: API message %p\n", (void *)msg)); msg->msg.apimsg->function(&(msg->msg.apimsg->msg)); break; #endif /* LWIP_NETCONN */ #if !LWIP_TCPIP_CORE_LOCKING_INPUT case TCPIP_MSG_INPKT: LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: PACKET %p\n", (void *)msg)); #if LWIP_ETHERNET if (msg->msg.inp.netif->flags & (NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET)) { ethernet_input(msg->msg.inp.p, msg->msg.inp.netif); } else #endif /* LWIP_ETHERNET */ { ip_input(msg->msg.inp.p, msg->msg.inp.netif); } memp_free(MEMP_TCPIP_MSG_INPKT, msg); break; #endif /* LWIP_TCPIP_CORE_LOCKING_INPUT */ #if LWIP_NETIF_API case TCPIP_MSG_NETIFAPI: LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: Netif API message %p\n", (void *)msg)); msg->msg.netifapimsg->function(&(msg->msg.netifapimsg->msg)); break; #endif /* LWIP_NETIF_API */ case TCPIP_MSG_CALLBACK: LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: CALLBACK %p\n", (void *)msg)); msg->msg.cb.function(msg->msg.cb.ctx); memp_free(MEMP_TCPIP_MSG_API, msg); break; #if LWIP_TCPIP_TIMEOUT case TCPIP_MSG_TIMEOUT: LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: TIMEOUT %p\n", (void *)msg)); sys_timeout(msg->msg.tmo.msecs, msg->msg.tmo.h, msg->msg.tmo.arg); memp_free(MEMP_TCPIP_MSG_API, msg); break; case TCPIP_MSG_UNTIMEOUT: LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: UNTIMEOUT %p\n", (void *)msg)); sys_untimeout(msg->msg.tmo.h, msg->msg.tmo.arg); memp_free(MEMP_TCPIP_MSG_API, msg); break; #endif /* LWIP_TCPIP_TIMEOUT */ default: LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: invalid message: %d\n", msg->type)); LWIP_ASSERT("tcpip_thread: invalid message", 0); break; } } }
/** * Wait (forever) for a message to arrive in an mbox. * While waiting, timeouts are processed. * * @param mbox the mbox to fetch the message from * @param msg the place to store the message */ void sys_timeouts_mbox_fetch(sys_mbox_t *mbox, void **msg) { printf("sys_timeouts_mbox_fetch()\n"); u32_t time_needed; struct sys_timeo *tmptimeout; sys_timeout_handler handler; void *arg; again: if (!next_timeout) { printf("No Timeout, sys_arch_mbox_fetch(mbox, msg, 0)\n"); time_needed = sys_arch_mbox_fetch(mbox, msg, 0); } else { if (next_timeout->time > 0) { //printf("Have timeout, fetching with timeout of %i\n", next_timeout->time); time_needed = sys_arch_mbox_fetch(mbox, msg, next_timeout->time); } else { //printf("No time! timing out!\n"); time_needed = SYS_ARCH_TIMEOUT; } //printf("time_needed: %i (timeout=%i)\n", time_needed, SYS_ARCH_TIMEOUT); if (time_needed == SYS_ARCH_TIMEOUT) { /* If time == SYS_ARCH_TIMEOUT, a timeout occured before a message could be fetched. We should now call the timeout handler and deallocate the memory allocated for the timeout. */ tmptimeout = next_timeout; next_timeout = tmptimeout->next; handler = tmptimeout->h; arg = tmptimeout->arg; #if LWIP_DEBUG_TIMERNAMES if (handler != NULL) { LWIP_DEBUGF(TIMERS_DEBUG, ("stmf calling h=%s arg=%p\n", tmptimeout->handler_name, arg)); } #endif /* LWIP_DEBUG_TIMERNAMES */ memp_free(MEMP_SYS_TIMEOUT, tmptimeout); if (handler != NULL) { /* For LWIP_TCPIP_CORE_LOCKING, lock the core before calling the timeout handler function. */ LOCK_TCPIP_CORE(); handler(arg); UNLOCK_TCPIP_CORE(); } LWIP_TCPIP_THREAD_ALIVE(); /* We try again to fetch a message from the mbox. */ //printf("Starting over, we didnt get a message\n"); goto again; } else { /* If time != SYS_ARCH_TIMEOUT, a message was received before the timeout occured. The time variable is set to the number of milliseconds we waited for the message. */ if (time_needed < next_timeout->time) { next_timeout->time -= time_needed; } else { next_timeout->time = 0; } } } }
/** * The main lwIP thread. This thread has exclusive access to lwIP core functions * (unless access to them is not locked). Other threads communicate with this * thread using message boxes. * * It also starts all the timers to make sure they are running in the right * thread context. * * @param arg unused argument */ static void tcpip_thread(void *arg) { struct tcpip_msg *msg; LWIP_UNUSED_ARG(arg); if (tcpip_init_done != NULL) { tcpip_init_done(tcpip_init_done_arg); } LOCK_TCPIP_CORE(); while (1) { /* MAIN Loop */ UNLOCK_TCPIP_CORE(); LWIP_TCPIP_THREAD_ALIVE(); /* wait for a message, timeouts are processed while waiting */ TCPIP_MBOX_FETCH(&mbox, (void **)&msg); LOCK_TCPIP_CORE(); if (msg == NULL) { LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: invalid message: NULL\n")); LWIP_ASSERT("tcpip_thread: invalid message", 0); continue; } switch (msg->type) { #if !LWIP_TCPIP_CORE_LOCKING case TCPIP_MSG_API: LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: API message %p\n", (void *)msg)); msg->msg.api_msg.function(msg->msg.api_msg.msg); break; case TCPIP_MSG_API_CALL: LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: API CALL message %p\n", (void *)msg)); msg->msg.api_call.arg->err = msg->msg.api_call.function(msg->msg.api_call.arg); sys_sem_signal(msg->msg.api_call.sem); break; #endif /* !LWIP_TCPIP_CORE_LOCKING */ #if !LWIP_TCPIP_CORE_LOCKING_INPUT case TCPIP_MSG_INPKT: LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: PACKET %p\n", (void *)msg)); msg->msg.inp.input_fn(msg->msg.inp.p, msg->msg.inp.netif); memp_free(MEMP_TCPIP_MSG_INPKT, msg); break; #endif /* !LWIP_TCPIP_CORE_LOCKING_INPUT */ #if LWIP_TCPIP_TIMEOUT && LWIP_TIMERS case TCPIP_MSG_TIMEOUT: LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: TIMEOUT %p\n", (void *)msg)); sys_timeout(msg->msg.tmo.msecs, msg->msg.tmo.h, msg->msg.tmo.arg); memp_free(MEMP_TCPIP_MSG_API, msg); break; case TCPIP_MSG_UNTIMEOUT: LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: UNTIMEOUT %p\n", (void *)msg)); sys_untimeout(msg->msg.tmo.h, msg->msg.tmo.arg); memp_free(MEMP_TCPIP_MSG_API, msg); break; #endif /* LWIP_TCPIP_TIMEOUT && LWIP_TIMERS */ case TCPIP_MSG_CALLBACK: LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: CALLBACK %p\n", (void *)msg)); msg->msg.cb.function(msg->msg.cb.ctx); memp_free(MEMP_TCPIP_MSG_API, msg); break; case TCPIP_MSG_CALLBACK_STATIC: LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: CALLBACK_STATIC %p\n", (void *)msg)); msg->msg.cb.function(msg->msg.cb.ctx); break; #ifdef LWIP_NETIF_DRV case TCPIP_MSG_DRV: LWIP_DEBUGF(NETIF_DEBUG, ("tcpip_thread: DRV %p\n", (void *)msg)); msg->msg.drv.drv_fn(msg->msg.drv.netif, msg->msg.drv.event); memp_free(MEMP_NETIF_DRV_MSG, msg); break; #endif default: LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_thread: invalid message: %d\n", msg->type)); LWIP_ASSERT("tcpip_thread: invalid message", 0); break; } } }