added option LWIP_NETCONN_SEM_PER_THREAD to use a semaphore per thread instead of using one per netconn and per select call

This commit is contained in:
sg
2014-12-10 20:45:01 +01:00
parent 35729f0870
commit cacdbb5262
10 changed files with 187 additions and 48 deletions

View File

@@ -70,7 +70,7 @@ static void lwip_netconn_do_close_internal(struct netconn *conn);
#if LWIP_RAW
/**
* Receive callback function for RAW netconns.
* Doesn't 'eat' the packet, only references it and sends it to
* Doesn't 'eat' the packet, only copies it and sends it to
* conn->recvmbox
*
* @see raw.h (struct raw_pcb.recv) for parameters and return value
@@ -365,8 +365,9 @@ err_tcp(void *arg, err_t err)
old_state = conn->state;
conn->state = NETCONN_NONE;
/* Notify the user layer about a connection error. Used to signal
select. */
/* @todo: the type of NETCONN_EVT created should depend on 'old_state' */
/* Notify the user layer about a connection error. Used to signal select. */
API_EVENT(conn, NETCONN_EVT_ERROR, 0);
/* Try to release selects pending on 'read' or 'write', too.
They will get an error if they actually try to read or write. */
@@ -392,12 +393,15 @@ err_tcp(void *arg, err_t err)
SET_NONBLOCKING_CONNECT(conn, 0);
if (!was_nonblocking_connect) {
sys_sem_t* op_completed_sem;
/* set error return code */
LWIP_ASSERT("conn->current_msg != NULL", conn->current_msg != NULL);
conn->current_msg->err = err;
op_completed_sem = LWIP_API_MSG_SEM(conn->current_msg);
LWIP_ASSERT("inavlid op_completed_sem", op_completed_sem != SYS_SEM_NULL);
conn->current_msg = NULL;
/* wake up the waiting task */
sys_sem_signal(&conn->op_completed);
sys_sem_signal(op_completed_sem);
}
} else {
LWIP_ASSERT("conn->current_msg == NULL", conn->current_msg == NULL);
@@ -553,7 +557,7 @@ void
lwip_netconn_do_newconn(struct api_msg_msg *msg)
{
msg->err = ERR_OK;
if(msg->conn->pcb.tcp == NULL) {
if (msg->conn->pcb.tcp == NULL) {
pcb_new(msg);
}
/* Else? This "new" connection already has a PCB allocated. */
@@ -588,7 +592,7 @@ netconn_alloc(enum netconn_type t, netconn_callback callback)
conn->type = t;
conn->pcb.tcp = NULL;
/* If all sizes are the same, every compiler should optimize this switch to nothing, */
/* If all sizes are the same, every compiler should optimize this switch to nothing */
switch(NETCONNTYPE_GROUP(t)) {
#if LWIP_RAW
case NETCONN_RAW:
@@ -610,13 +614,15 @@ netconn_alloc(enum netconn_type t, netconn_callback callback)
goto free_and_return;
}
if (sys_sem_new(&conn->op_completed, 0) != ERR_OK) {
goto free_and_return;
}
if (sys_mbox_new(&conn->recvmbox, size) != ERR_OK) {
sys_sem_free(&conn->op_completed);
goto free_and_return;
}
#if !LWIP_NETCONN_SEM_PER_THREAD
if (sys_sem_new(&conn->op_completed, 0) != ERR_OK) {
sys_mbox_free(&conn->recvmbox);
goto free_and_return;
}
#endif
#if LWIP_TCP
sys_mbox_set_invalid(&conn->acceptmbox);
@@ -665,8 +671,10 @@ netconn_free(struct netconn *conn)
!sys_mbox_valid(&conn->acceptmbox));
#endif /* LWIP_TCP */
#if !LWIP_NETCONN_SEM_PER_THREAD
sys_sem_free(&conn->op_completed);
sys_sem_set_invalid(&conn->op_completed);
#endif
memp_free(MEMP_NETCONN, conn);
}
@@ -790,6 +798,7 @@ lwip_netconn_do_close_internal(struct netconn *conn)
}
if (err == ERR_OK) {
/* Closing succeeded */
sys_sem_t* op_completed_sem = LWIP_API_MSG_SEM(conn->current_msg);
conn->current_msg->err = ERR_OK;
conn->current_msg = NULL;
conn->state = NETCONN_NONE;
@@ -807,7 +816,7 @@ lwip_netconn_do_close_internal(struct netconn *conn)
API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0);
}
/* wake up the application task */
sys_sem_signal(&conn->op_completed);
sys_sem_signal(op_completed_sem);
} else {
/* Closing failed, restore some of the callbacks */
/* Closing of listen pcb will never fail! */
@@ -884,8 +893,8 @@ lwip_netconn_do_delconn(struct api_msg_msg *msg)
API_EVENT(msg->conn, NETCONN_EVT_RCVPLUS, 0);
API_EVENT(msg->conn, NETCONN_EVT_SENDPLUS, 0);
}
if (sys_sem_valid(&msg->conn->op_completed)) {
sys_sem_signal(&msg->conn->op_completed);
if (sys_sem_valid(LWIP_API_MSG_SEM(msg))) {
sys_sem_signal(LWIP_API_MSG_SEM(msg));
}
}
@@ -940,6 +949,7 @@ lwip_netconn_do_connected(void *arg, struct tcp_pcb *pcb, err_t err)
{
struct netconn *conn;
int was_blocking;
sys_sem_t* op_completed_sem = NULL;
LWIP_UNUSED_ARG(pcb);
@@ -955,12 +965,16 @@ lwip_netconn_do_connected(void *arg, struct tcp_pcb *pcb, err_t err)
if (conn->current_msg != NULL) {
conn->current_msg->err = err;
op_completed_sem = LWIP_API_MSG_SEM(conn->current_msg);
}
if ((NETCONNTYPE_GROUP(conn->type) == NETCONN_TCP) && (err == ERR_OK)) {
setup_tcp(conn);
}
was_blocking = !IN_NONBLOCKING_CONNECT(conn);
SET_NONBLOCKING_CONNECT(conn, 0);
LWIP_ASSERT("blocking connect state error",
(was_blocking && op_completed_sem != NULL) ||
(!was_blocking && op_completed_sem == NULL));
conn->current_msg = NULL;
conn->state = NETCONN_NONE;
if (!was_blocking) {
@@ -969,7 +983,7 @@ lwip_netconn_do_connected(void *arg, struct tcp_pcb *pcb, err_t err)
API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0);
if (was_blocking) {
sys_sem_signal(&conn->op_completed);
sys_sem_signal(op_completed_sem);
}
return ERR_OK;
}
@@ -990,7 +1004,7 @@ lwip_netconn_do_connect(struct api_msg_msg *msg)
msg->err = ERR_CLSD;
if (NETCONNTYPE_GROUP(msg->conn->type) == NETCONN_TCP) {
/* For TCP, netconn_connect() calls tcpip_apimsg(), so signal op_completed here. */
sys_sem_signal(&msg->conn->op_completed);
sys_sem_signal(LWIP_API_MSG_SEM(msg));
return;
}
} else {
@@ -1029,7 +1043,7 @@ lwip_netconn_do_connect(struct api_msg_msg *msg)
}
}
/* For TCP, netconn_connect() calls tcpip_apimsg(), so signal op_completed here. */
sys_sem_signal(&msg->conn->op_completed);
sys_sem_signal(LWIP_API_MSG_SEM(msg));
return;
#endif /* LWIP_TCP */
default:
@@ -1286,7 +1300,7 @@ lwip_netconn_do_writemore(struct netconn *conn)
if (available < len) {
/* don't try to write more than sendbuf */
len = available;
if (dontblock){
if (dontblock) {
if (!len) {
err = ERR_WOULDBLOCK;
goto err_mem;
@@ -1347,6 +1361,7 @@ err_mem:
if (write_finished) {
/* everything was written: set back connection state
and back to application task */
sys_sem_t* op_completed_sem = LWIP_API_MSG_SEM(conn->current_msg);
conn->current_msg->err = err;
conn->current_msg = NULL;
conn->state = NETCONN_NONE;
@@ -1354,12 +1369,13 @@ err_mem:
if ((conn->flags & NETCONN_FLAG_WRITE_DELAYED) != 0)
#endif
{
sys_sem_signal(&conn->op_completed);
sys_sem_signal(op_completed_sem);
}
}
#if LWIP_TCPIP_CORE_LOCKING
else
else {
return ERR_MEM;
}
#endif
return ERR_OK;
}
@@ -1395,9 +1411,9 @@ lwip_netconn_do_write(struct api_msg_msg *msg)
if (lwip_netconn_do_writemore(msg->conn) != ERR_OK) {
LWIP_ASSERT("state!", msg->conn->state == NETCONN_WRITE);
UNLOCK_TCPIP_CORE();
sys_arch_sem_wait(&msg->conn->op_completed, 0);
sys_arch_sem_wait(LWIP_API_MSG_SEM(msg), 0);
LOCK_TCPIP_CORE();
LWIP_ASSERT("state!", msg->conn->state == NETCONN_NONE);
LWIP_ASSERT("state!", msg->conn->state != NETCONN_WRITE);
}
#else /* LWIP_TCPIP_CORE_LOCKING */
lwip_netconn_do_writemore(msg->conn);
@@ -1484,8 +1500,9 @@ lwip_netconn_do_getaddr(struct api_msg_msg *msg)
}
/**
* Close a TCP pcb contained in a netconn
* Close or half-shutdown a TCP pcb contained in a netconn
* Called from netconn_close
* In contrast to closing sockets, the netconn is not deallocated.
*
* @param msg the api_msg_msg pointing to the connection
*/
@@ -1521,7 +1538,7 @@ lwip_netconn_do_close(struct api_msg_msg *msg)
{
msg->err = ERR_VAL;
}
sys_sem_signal(&msg->conn->op_completed);
sys_sem_signal(LWIP_API_MSG_SEM(msg));
}
#if LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD)