SOME STATISTICS ABOUT API LAYERS: CURRENT CVS: Statistics: a lwip_sendto take ~0.204ms, the udp_sendtto part ~0.074ms/0.204ms SOLUTION1: "always use netconn_sendto, but use a global mutex" Statistics: a lwip_sendto take ~0.117ms, the udp_sendtto part ~0.074ms/0.117ms //sys.c void sys_mbox_fetch(sys_mbox_t mbox, void **msg) { u32_t time; struct sys_timeouts *timeouts; struct sys_timeo *tmptimeout; sys_timeout_handler h; void *arg; again: timeouts = sys_arch_timeouts(); if (!timeouts || !timeouts->next) { sys_sem_signal(lock_tcpip);//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< HERE time = sys_arch_mbox_fetch(mbox, msg, 0); sys_sem_wait(lock_tcpip);//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< HERE } else { if (timeouts->next->time > 0) { sys_sem_signal(lock_tcpip);//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< HERE time = sys_arch_mbox_fetch(mbox, msg, timeouts->next->time); sys_sem_wait(lock_tcpip);//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< HERE } 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, ("smf calling 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; } } } } //tcpip.c // Part from tcpip_thread() sys_sem_wait(lock_tcpip);//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< HERE while (1) { /* MAIN Loop */ sys_mbox_fetch(mbox, (void *)&msg); switch (msg->type) { /*...*/ default: break; } } } err_t tcpip_apimsg(struct api_msg *apimsg) { struct tcpip_msg msg; sys_sem_wait(lock_tcpip);//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< HERE apimsg->function(&(apimsg->msg)); sys_sem_signal(lock_tcpip);//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< HERE return ERR_OK; } //api_msg.c suppress some "sys_mbox_post(msg->conn->mbox, NULL);" - WARNING, do_connect was not patch for these tests... SOLUTION2: SOLUTION1 patchs+"directly use udp_sendto, and the global mutex" Statistics: a lwip_sendto take ~0.076ms, the udp_sendtto part ~0.074ms/0.076ms //sockets.c #define get_socket(s) ((struct lwip_socket *)(s)) In "lwip_sockets()", return value is change to: return (int)(sockets+i); /* (sockets+i) can never give -1 - on my hardware */ Most of "if (!sock) return -1;" are replaced by LWIP_ASSERT (like for last changes in api_lib.c). And... int lwip_sendto(int s, const void *data, int size, unsigned int flags, struct sockaddr *to, socklen_t tolen) { struct lwip_socket *sock; struct pbuf* p; int err; sock = get_socket(s); if (sock->conn->type==NETCONN_TCP) { #if LWIP_TCP return lwip_send(s, data, size, flags); #else sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1; #endif /* LWIP_TCP */ } LWIP_ASSERT("lwip_sendto: invalid address", (((to==NULL) && (tolen==0)) || ((tolen == sizeof(struct sockaddr_in)) && ((((struct sockaddr_in *)to)->sin_family) == AF_INET)))); /* not we can replace this call by a local variable, and remove the next pbuf_free */ p = pbuf_alloc(PBUF_TRANSPORT, 0, PBUF_REF); if (p == NULL) { return ERR_MEM; } p->payload = (void*)data; p->len = p->tot_len = size; sys_sem_wait(lock_tcpip); err = sock->conn->err = udp_sendto(sock->conn->pcb.udp, p, ((struct sockaddr_in *)to)->sin_addr.s_addr, ntohs(((struct sockaddr_in *)to)->sin_port)); sys_sem_signal(lock_tcpip); pbuf_free(p); sock_set_errno(sock, err_to_errno(err)); return (err==ERR_OK?size:-1); }