/** * Much like tcpip_apimsg, but calls the lower part of a netifapi_* * function. * * @param netifapimsg a struct containing the function to call and its parameters * @return error code given back by the function that was called */ err_t tcpip_netifapi(struct netifapi_msg* netifapimsg) { TCPIP_MSG_VAR_DECLARE(msg); if (sys_mbox_valid(&mbox)) { err_t err; TCPIP_MSG_VAR_ALLOC(msg); err = sys_sem_new(&netifapimsg->msg.sem, 0); if (err != ERR_OK) { netifapimsg->msg.err = err; return err; } TCPIP_MSG_VAR_REF(msg).type = TCPIP_MSG_NETIFAPI; TCPIP_MSG_VAR_REF(msg).msg.netifapimsg = netifapimsg; sys_mbox_post(&mbox, &TCPIP_MSG_VAR_REF(msg)); sys_sem_wait(&netifapimsg->msg.sem); sys_sem_free(&netifapimsg->msg.sem); TCPIP_MSG_VAR_FREE(msg); return netifapimsg->msg.err; } return ERR_VAL; }
/** * Call the lower part of a netconn_* function * This function is then running in the thread context * of tcpip_thread and has exclusive access to lwIP core code. * * @param apimsg a struct containing the function to call and its parameters * @return ERR_OK if the function was called, another err_t if not */ err_t tcpip_apimsg(struct api_msg *apimsg) { TCPIP_MSG_VAR_DECLARE(msg); #ifdef LWIP_DEBUG /* catch functions that don't set err */ apimsg->msg.err = ERR_VAL; #endif if (sys_mbox_valid(&mbox)) { TCPIP_MSG_VAR_ALLOC(msg); TCPIP_MSG_VAR_REF(msg).type = TCPIP_MSG_API; TCPIP_MSG_VAR_REF(msg).msg.apimsg = apimsg; #if LWIP_NETCONN_SEM_PER_THREAD apimsg->msg.op_completed_sem = LWIP_NETCONN_THREAD_SEM_GET(); LWIP_ASSERT("netconn semaphore not initialized", apimsg->msg.op_completed_sem != SYS_SEM_NULL); #endif sys_mbox_post(&mbox, &TCPIP_MSG_VAR_REF(msg)); sys_arch_sem_wait(LWIP_API_MSG_SEM(&apimsg->msg), 0); TCPIP_MSG_VAR_FREE(msg); return apimsg->msg.err; } return ERR_VAL; }
/** * Sends a message to TCPIP thread to call a function. Caller thread blocks on * on a provided semaphore, which ist NOT automatically signalled by TCPIP thread, * this has to be done by the user. * It is recommended to use LWIP_TCPIP_CORE_LOCKING since this is the way * with least runtime overhead. * * @param fn function to be called from TCPIP thread * @param apimsg argument to API function * @param sem semaphore to wait on * @return ERR_OK if the function was called, another err_t if not */ err_t tcpip_send_msg_wait_sem(tcpip_callback_fn fn, void *apimsg, sys_sem_t* sem) { #if LWIP_TCPIP_CORE_LOCKING LWIP_UNUSED_ARG(sem); LOCK_TCPIP_CORE(); fn(apimsg); UNLOCK_TCPIP_CORE(); return ERR_OK; #else /* LWIP_TCPIP_CORE_LOCKING */ TCPIP_MSG_VAR_DECLARE(msg); LWIP_ASSERT("semaphore not initialized", sys_sem_valid(sem)); LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(mbox)); TCPIP_MSG_VAR_ALLOC(msg); TCPIP_MSG_VAR_REF(msg).type = TCPIP_MSG_API; TCPIP_MSG_VAR_REF(msg).msg.api_msg.function = fn; TCPIP_MSG_VAR_REF(msg).msg.api_msg.msg = apimsg; sys_mbox_post(&mbox, &TCPIP_MSG_VAR_REF(msg)); sys_arch_sem_wait(sem, 0); TCPIP_MSG_VAR_FREE(msg); return ERR_OK; #endif /* LWIP_TCPIP_CORE_LOCKING */ }
/** * Synchronously calls function in TCPIP thread and waits for its completion. * It is recommended to use LWIP_TCPIP_CORE_LOCKING (preferred) or * LWIP_NETCONN_SEM_PER_THREAD. * If not, a semaphore is created and destroyed on every call which is usually * an expensive/slow operation. * @param fn Function to call * @param call Call parameters * @return Return value from tcpip_api_call_fn */ err_t tcpip_api_call(tcpip_api_call_fn fn, struct tcpip_api_call_data *call) { #if LWIP_TCPIP_CORE_LOCKING err_t err; LOCK_TCPIP_CORE(); err = fn(call); UNLOCK_TCPIP_CORE(); return err; #else /* LWIP_TCPIP_CORE_LOCKING */ TCPIP_MSG_VAR_DECLARE(msg); #if !LWIP_NETCONN_SEM_PER_THREAD err_t err = sys_sem_new(&call->sem, 0); if (err != ERR_OK) { return err; } #endif /* LWIP_NETCONN_SEM_PER_THREAD */ LWIP_ASSERT("Invalid mbox", sys_mbox_valid_val(mbox)); TCPIP_MSG_VAR_ALLOC(msg); TCPIP_MSG_VAR_REF(msg).type = TCPIP_MSG_API_CALL; TCPIP_MSG_VAR_REF(msg).msg.api_call.arg = call; TCPIP_MSG_VAR_REF(msg).msg.api_call.function = fn; #if LWIP_NETCONN_SEM_PER_THREAD TCPIP_MSG_VAR_REF(msg).msg.api_call.sem = LWIP_NETCONN_THREAD_SEM_GET(); #else /* LWIP_NETCONN_SEM_PER_THREAD */ TCPIP_MSG_VAR_REF(msg).msg.api_call.sem = &call->sem; #endif /* LWIP_NETCONN_SEM_PER_THREAD */ sys_mbox_post(&mbox, &TCPIP_MSG_VAR_REF(msg)); sys_arch_sem_wait(TCPIP_MSG_VAR_REF(msg).msg.api_call.sem, 0); TCPIP_MSG_VAR_FREE(msg); #if !LWIP_NETCONN_SEM_PER_THREAD sys_sem_free(&call->sem); #endif /* LWIP_NETCONN_SEM_PER_THREAD */ return call->err; #endif /* LWIP_TCPIP_CORE_LOCKING */ }