void sys_untimeout(sys_timeout_handler h, void *arg) { struct sys_timeouts *timeouts; struct sys_timeout *prev_t, *t; timeouts = sys_arch_timeouts(); if (timeouts->next == NULL) return; for (t = timeouts->next, prev_t = NULL; t != NULL; prev_t = t, t = t->next) { if ((t->h == h) && (t->arg == arg)) { /* We have a match */ /* Unlink from previous in list */ if (prev_t == NULL) timeouts->next = t->next; else prev_t->next = t->next; /* If not the last one, add time of this one back to next */ if (t->next != NULL) t->next->time += t->time; memp_free(MEMP_SYS_TIMEOUT, t); return; } } return; }
void sys_sem_wait(sys_sem_t sem) { u32_t time; struct sys_timeouts *timeouts; struct sys_timeout *tmptimeout; sys_timeout_handler h; void *arg; /* while (sys_arch_sem_wait(sem, 1000) == 0); return;*/ again: timeouts = sys_arch_timeouts(); if (!timeouts || !timeouts->next) { sys_arch_sem_wait(sem, 0); } else { if (timeouts->next->time > 0) { time = sys_arch_sem_wait(sem, timeouts->next->time); } else { time = SYS_ARCH_TIMEOUT; } if (time == 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 = timeouts->next; timeouts->next = tmptimeout->next; h = tmptimeout->h; arg = tmptimeout->arg; memp_free(MEMP_SYS_TIMEOUT, tmptimeout); if (h != NULL) { LWIP_DEBUGF(SYS_DEBUG, ("ssw h=%p(%p)\n", (void *)h, (void *)arg)); h(arg); } /* 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 <= timeouts->next->time) { timeouts->next->time -= time; } else { timeouts->next->time = 0; } } } }
/*-----------------------------------------------------------------------------------*/ void sys_sem_wait(sys_sem_t sem) { uint16_t time; struct sys_timeouts *timeouts; struct sys_timeout *tmptimeout; sys_timeout_handler h; void *arg; assert(sem); /* while(sys_arch_sem_wait(sem, 1000) == 0); return;*/ again: timeouts = sys_arch_timeouts(); if(timeouts->next == NULL) { sys_arch_sem_wait(sem, 0); } else { if(timeouts->next->time > 0) { time = sys_arch_sem_wait(sem, timeouts->next->time); } else { time = 0; } if(time == 0) { /* If time == 0, 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 = timeouts->next; timeouts->next = tmptimeout->next; h = tmptimeout->h; arg = tmptimeout->arg; memp_free(MEMP_SYS_TIMEOUT, tmptimeout); h(arg); /* We try again to fetch a message from the mbox. */ goto again; } else { /* If time > 0, a message was received before the timeout occured. The time variable is set to the number of microseconds we waited for the message. */ if(time <= timeouts->next->time) { timeouts->next->time -= time; } else { timeouts->next->time = 0; } } } }
/** * Wait (forever) for a message to arrive in an mbox. * While waiting, timeouts (for this thread) are processed. * * @param mbox the mbox to fetch the message from * @param msg the place to store the message */ void sys_mbox_fetch(sys_mbox_t mbox, void **msg) { u32_t time_needed; struct sys_timeouts *timeouts; struct sys_timeo *tmptimeout; sys_timeout_handler h; void *arg; again: timeouts = sys_arch_timeouts(); if (!timeouts || !timeouts->next) { UNLOCK_TCPIP_CORE(); time_needed = sys_arch_mbox_fetch(mbox, msg, 0); LOCK_TCPIP_CORE(); } else { if (timeouts->next->time > 0) { UNLOCK_TCPIP_CORE(); time_needed = sys_arch_mbox_fetch(mbox, msg, timeouts->next->time); LOCK_TCPIP_CORE(); } 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 = timeouts->next; timeouts->next = tmptimeout->next; h = tmptimeout->h; arg = tmptimeout->arg; memp_free(MEMP_SYS_TIMEOUT, tmptimeout); if (h != NULL) { LWIP_DEBUGF(SYS_DEBUG, ("smf calling h=%p(%p)\r\n", *(void**)&h, arg)); h(arg); } /* 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 < timeouts->next->time) { timeouts->next->time -= time_needed; } else { timeouts->next->time = 0; } } } }
/** * Create a one-shot timer (aka timeout). Timeouts are processed in the * following cases: * - while waiting for a message using sys_mbox_fetch() * - while waiting for a semaphore using sys_sem_wait() or sys_sem_wait_timeout() * - while sleeping using the inbuilt sys_msleep() * * @param msecs time in milliseconds after that the timer should expire * @param h callback function to call when msecs have elapsed * @param arg argument to pass to the callback function */ void sys_timeout(u32_t msecs, sys_timeout_handler h, void *arg) { struct sys_timeouts *timeouts; struct sys_timeo *timeout, *t; timeout = memp_malloc(MEMP_SYS_TIMEOUT); if (timeout == NULL) { LWIP_ASSERT("sys_timeout: timeout != NULL", timeout != NULL); return; } timeout->next = NULL; timeout->h = h; timeout->arg = arg; timeout->time = msecs; timeouts = sys_arch_timeouts(); LWIP_DEBUGF(SYS_DEBUG, ("sys_timeout: %p msecs=%"U32_F" h=%p arg=%p\r\n", (void *)timeout, msecs, *(void**)&h, (void *)arg)); if (timeouts == NULL) { LWIP_ASSERT("sys_timeout: timeouts != NULL", timeouts != NULL); return; } if (timeouts->next == NULL) { timeouts->next = timeout; return; } if (timeouts->next->time > msecs) { timeouts->next->time -= msecs; timeout->next = timeouts->next; timeouts->next = timeout; } else { for(t = timeouts->next; t != NULL; t = t->next) { timeout->time -= t->time; if (t->next == NULL || t->next->time > timeout->time) { if (t->next != NULL) { t->next->time -= timeout->time; } timeout->next = t->next; t->next = timeout; break; } } } }
/*-----------------------------------------------------------------------------------*/ void sys_timeout(uint16_t msecs, sys_timeout_handler h, void *arg) { struct sys_timeouts *timeouts; struct sys_timeout *timeout, *t; timeout = (struct sys_timeout*)memp_malloc(MEMP_SYS_TIMEOUT); if(timeout == NULL) { return; } timeout->next = NULL; timeout->h = h; timeout->arg = arg; timeout->time = msecs; timeouts = sys_arch_timeouts(); if(timeouts->next == NULL) { timeouts->next = timeout; return; } if(timeouts->next->time > msecs) { timeouts->next->time -= msecs; timeout->next = timeouts->next; timeouts->next = timeout; } else { for(t = timeouts->next; t != NULL; t = t->next) { timeout->time -= t->time; if(t->next == NULL || t->next->time > timeout->time) { if(t->next != NULL) { t->next->time -= timeout->time; } timeout->next = t->next; t->next = timeout; break; } } } }