diff --git a/CHANGELOG b/CHANGELOG index 3eb037ae..4b76efd5 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -19,6 +19,13 @@ HISTORY ++ New features: + 2010-02-12: Simon Goldschmidt + * sys layer: task #10139 (Prefer statically allocated memory): converted + mbox and semaphore functions to take pointers to sys_mbox_t/sys_sem_t; + converted sys_mbox_new/sys_sem_new to take pointers and return err_t; + task #7212: Add Mutex concept in sys_arch (define LWIP_COMPAT_MUTEX + to let sys.h use binary semaphores instead of mutexes - as before) + 2010-02-09: Simon Goldschmidt (Simon Kallweit) * timers.c/.h: Added function sys_restart_timeouts() from patch #7085 (Restart system timeout handling) diff --git a/src/api/api_lib.c b/src/api/api_lib.c index 861ee1bd..6b053cc8 100644 --- a/src/api/api_lib.c +++ b/src/api/api_lib.c @@ -77,11 +77,11 @@ netconn_new_with_proto_and_callback(enum netconn_type t, u8_t proto, netconn_cal msg.msg.conn = conn; if (TCPIP_APIMSG(&msg) != ERR_OK) { LWIP_ASSERT("freeing conn without freeing pcb", conn->pcb.tcp == NULL); - LWIP_ASSERT("conn has no op_completed", conn->op_completed != SYS_SEM_NULL); - LWIP_ASSERT("conn has no recvmbox", conn->recvmbox != SYS_MBOX_NULL); - LWIP_ASSERT("conn->acceptmbox shouldn't exist", conn->acceptmbox == SYS_MBOX_NULL); - sys_sem_free(conn->op_completed); - sys_mbox_free(conn->recvmbox); + LWIP_ASSERT("conn has no op_completed", sys_sem_valid(&conn->op_completed)); + LWIP_ASSERT("conn has no recvmbox", sys_mbox_valid(&conn->recvmbox)); + LWIP_ASSERT("conn->acceptmbox shouldn't exist", !sys_mbox_valid(&conn->acceptmbox)); + sys_sem_free(&conn->op_completed); + sys_mbox_free(&conn->recvmbox); memp_free(MEMP_NETCONN, conn); return NULL; } @@ -277,7 +277,7 @@ netconn_accept(struct netconn *conn, struct netconn **new_conn) LWIP_ERROR("netconn_accept: invalid pointer", (new_conn != NULL), return ERR_ARG;); *new_conn = NULL; LWIP_ERROR("netconn_accept: invalid conn", (conn != NULL), return ERR_ARG;); - LWIP_ERROR("netconn_accept: invalid acceptmbox", (conn->acceptmbox != SYS_MBOX_NULL), return ERR_ARG;); + LWIP_ERROR("netconn_accept: invalid acceptmbox", sys_mbox_valid(&conn->acceptmbox), return ERR_ARG;); err = conn->last_err; if (ERR_IS_FATAL(err)) { @@ -287,12 +287,12 @@ netconn_accept(struct netconn *conn, struct netconn **new_conn) } #if LWIP_SO_RCVTIMEO - if (sys_arch_mbox_fetch(conn->acceptmbox, (void **)&newconn, conn->recv_timeout) == SYS_ARCH_TIMEOUT) { + if (sys_arch_mbox_fetch(&conn->acceptmbox, (void **)&newconn, conn->recv_timeout) == SYS_ARCH_TIMEOUT) { NETCONN_SET_SAFE_ERR(conn, ERR_TIMEOUT); return ERR_TIMEOUT; } #else - sys_arch_mbox_fetch(conn->acceptmbox, (void **)&newconn, 0); + sys_arch_mbox_fetch(&conn->acceptmbox, (void **)&newconn, 0); #endif /* LWIP_SO_RCVTIMEO*/ /* Register event with callback */ API_EVENT(conn, NETCONN_EVT_RCVMINUS, 0); @@ -335,12 +335,14 @@ netconn_recv(struct netconn *conn, struct netbuf **new_buf) LWIP_ERROR("netconn_recv: invalid pointer", (new_buf != NULL), return ERR_ARG;); *new_buf = NULL; LWIP_ERROR("netconn_recv: invalid conn", (conn != NULL), return ERR_ARG;); - LWIP_ERROR("netconn_accept: invalid recvmbox", (conn->recvmbox != SYS_MBOX_NULL), return ERR_CONN;); + LWIP_ERROR("netconn_accept: invalid recvmbox", sys_mbox_valid(&conn->recvmbox), return ERR_CONN;); err = conn->last_err; if (ERR_IS_FATAL(err)) { /* don't recv on fatal errors: this might block the application task waiting on recvmbox forever! */ + /* @todo: this does not allow us to fetch data that has been put into recvmbox + before the fatal error occurred - is that a problem? */ return err; } @@ -355,13 +357,13 @@ netconn_recv(struct netconn *conn, struct netbuf **new_buf) } #if LWIP_SO_RCVTIMEO - if (sys_arch_mbox_fetch(conn->recvmbox, (void **)&p, conn->recv_timeout)==SYS_ARCH_TIMEOUT) { + if (sys_arch_mbox_fetch(&conn->recvmbox, (void **)&p, conn->recv_timeout)==SYS_ARCH_TIMEOUT) { memp_free(MEMP_NETBUF, buf); NETCONN_SET_SAFE_ERR(conn, ERR_TIMEOUT); return ERR_TIMEOUT; } #else - sys_arch_mbox_fetch(conn->recvmbox, (void **)&p, 0); + sys_arch_mbox_fetch(&conn->recvmbox, (void **)&p, 0); #endif /* LWIP_SO_RCVTIMEO*/ if (p != NULL) { @@ -406,12 +408,12 @@ netconn_recv(struct netconn *conn, struct netbuf **new_buf) } else { #if (LWIP_UDP || LWIP_RAW) #if LWIP_SO_RCVTIMEO - if (sys_arch_mbox_fetch(conn->recvmbox, (void **)&buf, conn->recv_timeout)==SYS_ARCH_TIMEOUT) { + if (sys_arch_mbox_fetch(&conn->recvmbox, (void **)&buf, conn->recv_timeout)==SYS_ARCH_TIMEOUT) { NETCONN_SET_SAFE_ERR(conn, ERR_TIMEOUT); return ERR_TIMEOUT; } #else - sys_arch_mbox_fetch(conn->recvmbox, (void **)&buf, 0); + sys_arch_mbox_fetch(&conn->recvmbox, (void **)&buf, 0); #endif /* LWIP_SO_RCVTIMEO*/ LWIP_ASSERT("buf != NULL", buf != NULL); diff --git a/src/api/api_msg.c b/src/api/api_msg.c index 3acee1ca..4e394a71 100644 --- a/src/api/api_msg.c +++ b/src/api/api_msg.c @@ -90,7 +90,7 @@ recv_raw(void *arg, struct raw_pcb *pcb, struct pbuf *p, #if LWIP_SO_RCVBUF SYS_ARCH_GET(conn->recv_avail, recv_avail); - if ((conn != NULL) && (conn->recvmbox != SYS_MBOX_NULL) && + if ((conn != NULL) && sys_mbox_valid(&conn->recvmbox) && ((recv_avail + (int)(p->tot_len)) <= conn->recv_bufsize)) { #else /* LWIP_SO_RCVBUF */ if ((conn != NULL) && (conn->recvmbox != SYS_MBOX_NULL)) { @@ -118,7 +118,7 @@ recv_raw(void *arg, struct raw_pcb *pcb, struct pbuf *p, buf->port = pcb->protocol; len = q->tot_len; - if (sys_mbox_trypost(conn->recvmbox, buf) != ERR_OK) { + if (sys_mbox_trypost(&conn->recvmbox, buf) != ERR_OK) { netbuf_delete(buf); return 0; } else { @@ -159,7 +159,7 @@ recv_udp(void *arg, struct udp_pcb *pcb, struct pbuf *p, #if LWIP_SO_RCVBUF SYS_ARCH_GET(conn->recv_avail, recv_avail); - if ((conn == NULL) || (conn->recvmbox == SYS_MBOX_NULL) || + if ((conn == NULL) || !sys_mbox_valid(&conn->recvmbox) || ((recv_avail + (int)(p->tot_len)) > conn->recv_bufsize)) { #else /* LWIP_SO_RCVBUF */ if ((conn == NULL) || (conn->recvmbox == SYS_MBOX_NULL)) { @@ -189,7 +189,7 @@ recv_udp(void *arg, struct udp_pcb *pcb, struct pbuf *p, } len = p->tot_len; - if (sys_mbox_trypost(conn->recvmbox, buf) != ERR_OK) { + if (sys_mbox_trypost(&conn->recvmbox, buf) != ERR_OK) { netbuf_delete(buf); return; } else { @@ -222,7 +222,7 @@ recv_tcp(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) if (conn == NULL) { return ERR_VAL; } - if (conn->recvmbox == SYS_MBOX_NULL) { + if (!sys_mbox_valid(&conn->recvmbox)) { /* recvmbox already deleted */ if (p != NULL) { tcp_recved(pcb, p->tot_len); @@ -243,7 +243,7 @@ recv_tcp(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) len = 0; } - if (sys_mbox_trypost(conn->recvmbox, p) != ERR_OK) { + if (sys_mbox_trypost(&conn->recvmbox, p) != ERR_OK) { /* don't deallocate p: it is presented to us later again from tcp_fasttmr! */ return ERR_MEM; } else { @@ -354,14 +354,14 @@ err_tcp(void *arg, err_t err) API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0); /* pass NULL-message to recvmbox to wake up pending recv */ - if (conn->recvmbox != SYS_MBOX_NULL) { + if (sys_mbox_valid(&conn->recvmbox)) { /* use trypost to prevent deadlock */ - sys_mbox_trypost(conn->recvmbox, NULL); + sys_mbox_trypost(&conn->recvmbox, NULL); } /* pass NULL-message to acceptmbox to wake up pending accept */ - if (conn->acceptmbox != SYS_MBOX_NULL) { + if (sys_mbox_valid(&conn->acceptmbox)) { /* use trypost to preven deadlock */ - sys_mbox_trypost(conn->acceptmbox, NULL); + sys_mbox_trypost(&conn->acceptmbox, NULL); } if ((old_state == NETCONN_WRITE) || (old_state == NETCONN_CLOSE) || @@ -377,7 +377,7 @@ err_tcp(void *arg, err_t err) conn->current_msg->err = err; conn->current_msg = NULL; /* wake up the waiting task */ - sys_sem_signal(conn->op_completed); + sys_sem_signal(&conn->op_completed); } } else { LWIP_ASSERT("conn->current_msg == NULL", conn->current_msg == NULL); @@ -422,7 +422,7 @@ accept_function(void *arg, struct tcp_pcb *newpcb, err_t err) #endif /* API_MSG_DEBUG */ conn = (struct netconn *)arg; - if (conn->acceptmbox == SYS_MBOX_NULL) { + if (!sys_mbox_valid(&conn->acceptmbox)) { LWIP_DEBUGF(API_MSG_DEBUG, ("accept_function: acceptmbox already deleted\n")); return ERR_VAL; } @@ -439,13 +439,13 @@ accept_function(void *arg, struct tcp_pcb *newpcb, err_t err) to the application thread */ newconn->last_err = err; - if (sys_mbox_trypost(conn->acceptmbox, newconn) != ERR_OK) { + if (sys_mbox_trypost(&conn->acceptmbox, newconn) != ERR_OK) { /* When returning != ERR_OK, the pcb is aborted in tcp_process(), so do nothing here! */ newconn->pcb.tcp = NULL; /* no need to drain since we know the recvmbox is empty. */ - sys_mbox_free(newconn->recvmbox); - newconn->recvmbox = SYS_MBOX_NULL; + sys_mbox_free(&newconn->recvmbox); + sys_mbox_set_invalid(&newconn->recvmbox); netconn_free(newconn); return ERR_MEM; } else { @@ -587,20 +587,20 @@ netconn_alloc(enum netconn_type t, netconn_callback callback) } #endif - if ((conn->op_completed = sys_sem_new(0)) == SYS_SEM_NULL) { + if (sys_sem_new(&conn->op_completed, 0) != ERR_OK) { memp_free(MEMP_NETCONN, conn); return NULL; } - if ((conn->recvmbox = sys_mbox_new(size)) == SYS_MBOX_NULL) { - sys_sem_free(conn->op_completed); + if (sys_mbox_new(&conn->recvmbox, size) != ERR_OK) { + sys_sem_free(&conn->op_completed); memp_free(MEMP_NETCONN, conn); return NULL; } - conn->acceptmbox = SYS_MBOX_NULL; + sys_mbox_set_invalid(&conn->acceptmbox); conn->state = NETCONN_NONE; - /* initialize socket to -1 since 0 is a valid socket */ #if LWIP_SOCKET + /* initialize socket to -1 since 0 is a valid socket */ conn->socket = -1; #endif /* LWIP_SOCKET */ conn->callback = callback; @@ -608,9 +608,6 @@ netconn_alloc(enum netconn_type t, netconn_callback callback) #if LWIP_TCP conn->current_msg = NULL; conn->write_offset = 0; -#if LWIP_TCPIP_CORE_LOCKING - conn->write_delayed = 0; -#endif /* LWIP_TCPIP_CORE_LOCKING */ #endif /* LWIP_TCP */ #if LWIP_SO_RCVTIMEO conn->recv_timeout = 0; @@ -633,12 +630,12 @@ netconn_free(struct netconn *conn) { LWIP_ASSERT("PCB must be deallocated outside this function", conn->pcb.tcp == NULL); LWIP_ASSERT("recvmbox must be deallocated before calling this function", - conn->recvmbox == SYS_MBOX_NULL); + !sys_mbox_valid(&conn->recvmbox)); LWIP_ASSERT("acceptmbox must be deallocated before calling this function", - conn->acceptmbox == SYS_MBOX_NULL); + !sys_mbox_valid(&conn->acceptmbox)); - sys_sem_free(conn->op_completed); - conn->op_completed = SYS_SEM_NULL; + sys_sem_free(&conn->op_completed); + sys_sem_set_invalid(&conn->op_completed); memp_free(MEMP_NETCONN, conn); } @@ -656,13 +653,12 @@ netconn_drain(struct netconn *conn) { void *mem; struct pbuf *p; - sys_mbox_t mbox; + + /* This runs in tcpip_thread, so we don't need to lock against rx packets */ /* Delete and drain the recvmbox. */ - mbox = conn->recvmbox; - conn->recvmbox = SYS_MBOX_NULL; - if (mbox != SYS_MBOX_NULL) { - while (sys_mbox_tryfetch(mbox, &mem) != SYS_MBOX_EMPTY) { + if (sys_mbox_valid(&conn->recvmbox)) { + while (sys_mbox_tryfetch(&conn->recvmbox, &mem) != SYS_MBOX_EMPTY) { if (conn->type == NETCONN_TCP) { if(mem != NULL) { p = (struct pbuf*)mem; @@ -676,14 +672,13 @@ netconn_drain(struct netconn *conn) netbuf_delete((struct netbuf *)mem); } } - sys_mbox_free(mbox); + sys_mbox_free(&conn->recvmbox); + sys_mbox_set_invalid(&conn->recvmbox); } /* Delete and drain the acceptmbox. */ - mbox = conn->acceptmbox; - conn->acceptmbox = SYS_MBOX_NULL; - if (mbox != SYS_MBOX_NULL) { - while (sys_mbox_tryfetch(mbox, &mem) != SYS_MBOX_EMPTY) { + if (sys_mbox_valid(&conn->acceptmbox)) { + while (sys_mbox_tryfetch(&conn->acceptmbox, &mem) != SYS_MBOX_EMPTY) { /* Only tcp pcbs have an acceptmbox, so no need to check conn->type */ /* pcb might be set to NULL already by err_tcp() */ if (conn->pcb.tcp != NULL) { @@ -691,7 +686,8 @@ netconn_drain(struct netconn *conn) } netconn_delete((struct netconn *)mem); } - sys_mbox_free(mbox); + sys_mbox_free(&conn->acceptmbox); + sys_mbox_set_invalid(&conn->acceptmbox); } } @@ -741,7 +737,7 @@ do_close_internal(struct netconn *conn) API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0); API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0); /* wake up the application task */ - sys_sem_signal(conn->op_completed); + sys_sem_signal(&conn->op_completed); } else { /* Closing failed, restore some of the callbacks */ /* Closing of listen pcb will never fail! */ @@ -811,8 +807,8 @@ do_delconn(struct api_msg_msg *msg) API_EVENT(msg->conn, NETCONN_EVT_RCVPLUS, 0); API_EVENT(msg->conn, NETCONN_EVT_SENDPLUS, 0); } - if (msg->conn->op_completed != SYS_SEM_NULL) { - sys_sem_signal(msg->conn->op_completed); + if (sys_sem_valid(&msg->conn->op_completed)) { + sys_sem_signal(&msg->conn->op_completed); } } @@ -901,7 +897,7 @@ 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(&conn->op_completed); } return ERR_OK; } @@ -962,7 +958,7 @@ do_connect(struct api_msg_msg *msg) break; } } - sys_sem_signal(msg->conn->op_completed); + sys_sem_signal(&msg->conn->op_completed); } /** @@ -1014,16 +1010,14 @@ do_listen(struct api_msg_msg *msg) msg->err = ERR_MEM; } else { /* delete the recvmbox and allocate the acceptmbox */ - if (msg->conn->recvmbox != SYS_MBOX_NULL) { + if (sys_mbox_valid(&msg->conn->recvmbox)) { /** @todo: should we drain the recvmbox here? */ - sys_mbox_free(msg->conn->recvmbox); - msg->conn->recvmbox = SYS_MBOX_NULL; + sys_mbox_free(&msg->conn->recvmbox); + sys_mbox_set_invalid(&msg->conn->recvmbox); } msg->err = ERR_OK; - if (msg->conn->acceptmbox == SYS_MBOX_NULL) { - if ((msg->conn->acceptmbox = sys_mbox_new(DEFAULT_ACCEPTMBOX_SIZE)) == SYS_MBOX_NULL) { - msg->err = ERR_MEM; - } + if (!sys_mbox_valid(&msg->conn->acceptmbox)) { + msg->err = sys_mbox_new(&msg->conn->acceptmbox, DEFAULT_ACCEPTMBOX_SIZE); } if (msg->err == ERR_OK) { msg->conn->state = NETCONN_LISTEN; @@ -1150,7 +1144,7 @@ do_writemore(struct netconn *conn) if (diff > 0xffffUL) { /* max_u16_t */ len = 0xffff; #if LWIP_TCPIP_CORE_LOCKING - conn->write_delayed = 1; + conn->flags |= NETCONN_FLAG_WRITE_DELAYED; #endif } else { len = (u16_t)diff; @@ -1160,7 +1154,7 @@ do_writemore(struct netconn *conn) /* don't try to write more than sendbuf */ len = available; #if LWIP_TCPIP_CORE_LOCKING - conn->write_delayed = 1; + conn->flags |= NETCONN_FLAG_WRITE_DELAYED; #endif } @@ -1193,7 +1187,7 @@ do_writemore(struct netconn *conn) tcp_output(conn->pcb.tcp); #if LWIP_TCPIP_CORE_LOCKING - conn->write_delayed = 1; + conn->flags |= NETCONN_FLAG_WRITE_DELAYED; #endif } else { /* On errors != ERR_MEM, we don't try writing any more but return @@ -1208,10 +1202,10 @@ do_writemore(struct netconn *conn) conn->current_msg = NULL; conn->state = NETCONN_NONE; #if LWIP_TCPIP_CORE_LOCKING - if (conn->write_delayed != 0) + if ((conn->flags & NETCONN_FLAG_WRITE_DELAYED) != 0) #endif { - sys_sem_signal(conn->op_completed); + sys_sem_signal(&conn->op_completed); } } #if LWIP_TCPIP_CORE_LOCKING @@ -1247,11 +1241,11 @@ do_write(struct api_msg_msg *msg) msg->conn->current_msg = msg; msg->conn->write_offset = 0; #if LWIP_TCPIP_CORE_LOCKING - msg->conn->write_delayed = 0; + msg->conn->flags &= ~NETCONN_FLAG_WRITE_DELAYED; if (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(&msg->conn->op_completed, 0); LOCK_TCPIP_CORE(); LWIP_ASSERT("state!", msg->conn->state == NETCONN_NONE); } @@ -1355,7 +1349,7 @@ do_close(struct api_msg_msg *msg) { msg->err = ERR_VAL; } - sys_sem_signal(msg->conn->op_completed); + sys_sem_signal(&msg->conn->op_completed); } #if LWIP_IGMP diff --git a/src/api/sockets.c b/src/api/sockets.c index e427bd2b..5f145eda 100644 --- a/src/api/sockets.c +++ b/src/api/sockets.c @@ -118,7 +118,7 @@ static struct lwip_socket sockets[NUM_SOCKETS]; static struct lwip_select_cb *select_cb_list; /** Semaphore protecting select_cb_list */ -static sys_sem_t selectsem; +static sys_mutex_t select_lock; /** Table to quickly map an lwIP error (err_t) to a socket error * by using -err as an index */ @@ -172,7 +172,9 @@ static void lwip_setsockopt_internal(void *arg); void lwip_socket_init(void) { - selectsem = sys_sem_new(1); + if(sys_mutex_new(&select_lock) != ERR_OK) { + LWIP_ASSERT("failed to create select_lock", 0); + } } /** @@ -944,6 +946,7 @@ lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, u32_t msectimeout; struct lwip_select_cb select_cb; struct lwip_select_cb *p_selcb; + err_t err; LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select(%d, %p, %p, %p, tvsec=%ld tvusec=%ld)\n", maxfdp1, (void *)readset, (void *) writeset, (void *) exceptset, @@ -957,7 +960,7 @@ lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, select_cb.sem_signalled = 0; /* Protect ourselves searching through the list */ - sys_sem_wait(selectsem); + sys_mutex_lock(&select_lock); if (readset) lreadset = *readset; @@ -979,7 +982,7 @@ lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, /* If we don't have any current events, then suspend if we are supposed to */ if (!nready) { if (timeout && timeout->tv_sec == 0 && timeout->tv_usec == 0) { - sys_sem_signal(selectsem); + sys_mutex_unlock(&select_lock); if (readset) FD_ZERO(readset); if (writeset) @@ -998,14 +1001,20 @@ lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, * list is only valid while we are in this function, so it's ok * to use local variables */ - select_cb.sem = sys_sem_new(0); + err = sys_sem_new(&select_cb.sem, 0); + if (err != ERR_OK) { + /* failed to create semaphore */ + sys_mutex_unlock(&select_lock); + set_errno(ENOMEM); + return -1; + } /* Note that we are still protected */ /* Put this select_cb on top of list */ select_cb.next = select_cb_list; select_cb_list = &select_cb; /* Now we can safely unprotect */ - sys_sem_signal(selectsem); + sys_mutex_unlock(&select_lock); /* Now just wait to be woken */ if (timeout == 0) @@ -1017,23 +1026,24 @@ lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, msectimeout = 1; } - waitres = sys_arch_sem_wait(select_cb.sem, msectimeout); + waitres = sys_arch_sem_wait(&select_cb.sem, msectimeout); /* Take us off the list */ - sys_sem_wait(selectsem); - if (select_cb_list == &select_cb) + sys_mutex_lock(&select_lock); + if (select_cb_list == &select_cb) { select_cb_list = select_cb.next; - else + } else { for (p_selcb = select_cb_list; p_selcb; p_selcb = p_selcb->next) { if (p_selcb->next == &select_cb) { p_selcb->next = select_cb.next; break; } } + } - sys_sem_signal(selectsem); + sys_mutex_unlock(&select_lock); - sys_sem_free(select_cb.sem); + sys_sem_free(&select_cb.sem); if (waitres == SYS_ARCH_TIMEOUT) { /* Timeout */ if (readset) @@ -1064,8 +1074,9 @@ lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, /* See what's set */ nready = lwip_selscan(maxfdp1, &lreadset, &lwriteset, &lexceptset); - } else - sys_sem_signal(selectsem); + } else { + sys_mutex_unlock(&select_lock); + } if (readset) *readset = lreadset; @@ -1123,7 +1134,7 @@ event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len) return; } - sys_sem_wait(selectsem); + sys_mutex_lock(&select_lock); /* Set event as required */ switch (evt) { case NETCONN_EVT_RCVPLUS: @@ -1145,17 +1156,17 @@ event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len) LWIP_ASSERT("unknown event", 0); break; } - sys_sem_signal(selectsem); + sys_mutex_unlock(&select_lock); /* Now decide if anyone is waiting for this socket */ /* NOTE: This code is written this way to protect the select link list - but to avoid a deadlock situation by releasing selectsem before + but to avoid a deadlock situation by releasing select_lock before signalling for the select. This means we need to go through the list multiple times ONLY IF a select was actually waiting. We go through the list the number of waiting select calls + 1. This list is expected to be small. */ while (1) { - sys_sem_wait(selectsem); + sys_mutex_lock(&select_lock); for (scb = select_cb_list; scb; scb = scb->next) { if (scb->sem_signalled == 0) { /* Test this select call for our socket */ @@ -1172,10 +1183,10 @@ event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len) } if (scb) { scb->sem_signalled = 1; - sys_sem_signal(scb->sem); - sys_sem_signal(selectsem); + sys_sem_signal(&scb->sem); + sys_mutex_unlock(&select_lock); } else { - sys_sem_signal(selectsem); + sys_mutex_unlock(&select_lock); break; } } @@ -1415,7 +1426,7 @@ lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen) data.optlen = optlen; data.err = err; tcpip_callback(lwip_getsockopt_internal, &data); - sys_arch_sem_wait(sock->conn->op_completed, 0); + sys_arch_sem_wait(&sock->conn->op_completed, 0); /* maybe lwip_getsockopt_internal has changed err */ err = data.err; @@ -1600,7 +1611,7 @@ lwip_getsockopt_internal(void *arg) break; #endif /* LWIP_UDP */ } /* switch (level) */ - sys_sem_signal(sock->conn->op_completed); + sys_sem_signal(&sock->conn->op_completed); } int @@ -1790,7 +1801,7 @@ lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t opt data.optlen = &optlen; data.err = err; tcpip_callback(lwip_setsockopt_internal, &data); - sys_arch_sem_wait(sock->conn->op_completed, 0); + sys_arch_sem_wait(&sock->conn->op_completed, 0); /* maybe lwip_setsockopt_internal has changed err */ err = data.err; @@ -1978,7 +1989,7 @@ lwip_setsockopt_internal(void *arg) break; #endif /* LWIP_UDP */ } /* switch (level) */ - sys_sem_signal(sock->conn->op_completed); + sys_sem_signal(&sock->conn->op_completed); } int @@ -2000,8 +2011,9 @@ lwip_ioctl(int s, long cmd, void *argp) } SYS_ARCH_GET(sock->conn->recv_avail, recv_avail); - if (recv_avail < 0) + if (recv_avail < 0) { recv_avail = 0; + } *((u16_t*)argp) = (u16_t)recv_avail; /* Check if there is data left from the last recv operation. /maq 041215 */ diff --git a/src/api/tcpip.c b/src/api/tcpip.c index 78531beb..0abb0072 100644 --- a/src/api/tcpip.c +++ b/src/api/tcpip.c @@ -52,11 +52,11 @@ /* global variables */ static tcpip_init_done_fn tcpip_init_done; static void *tcpip_init_done_arg; -static sys_mbox_t mbox = SYS_MBOX_NULL; +static sys_mbox_t mbox; #if LWIP_TCPIP_CORE_LOCKING /** The global semaphore to lock the stack. */ -sys_sem_t lock_tcpip_core; +sys_mutex_t lock_tcpip_core; #endif /* LWIP_TCPIP_CORE_LOCKING */ @@ -84,7 +84,7 @@ tcpip_thread(void *arg) while (1) { /* MAIN Loop */ UNLOCK_TCPIP_CORE(); /* wait for a message, timeouts are processed while waiting */ - sys_timeouts_mbox_fetch(mbox, (void **)&msg); + sys_timeouts_mbox_fetch(&mbox, (void **)&msg); LOCK_TCPIP_CORE(); switch (msg->type) { #if LWIP_NETCONN @@ -148,7 +148,7 @@ tcpip_input(struct pbuf *p, struct netif *inp) { struct tcpip_msg *msg; - if (mbox != SYS_MBOX_NULL) { + if (sys_mbox_valid(&mbox)) { msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_INPKT); if (msg == NULL) { return ERR_MEM; @@ -157,7 +157,7 @@ tcpip_input(struct pbuf *p, struct netif *inp) msg->type = TCPIP_MSG_INPKT; msg->msg.inp.p = p; msg->msg.inp.netif = inp; - if (sys_mbox_trypost(mbox, msg) != ERR_OK) { + if (sys_mbox_trypost(&mbox, msg) != ERR_OK) { memp_free(MEMP_TCPIP_MSG_INPKT, msg); return ERR_MEM; } @@ -182,7 +182,7 @@ tcpip_callback_with_block(tcpip_callback_fn function, void *ctx, u8_t block) { struct tcpip_msg *msg; - if (mbox != SYS_MBOX_NULL) { + if (sys_mbox_valid(&mbox)) { msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API); if (msg == NULL) { return ERR_MEM; @@ -192,9 +192,9 @@ tcpip_callback_with_block(tcpip_callback_fn function, void *ctx, u8_t block) msg->msg.cb.function = function; msg->msg.cb.ctx = ctx; if (block) { - sys_mbox_post(mbox, msg); + sys_mbox_post(&mbox, msg); } else { - if (sys_mbox_trypost(mbox, msg) != ERR_OK) { + if (sys_mbox_trypost(&mbox, msg) != ERR_OK) { memp_free(MEMP_TCPIP_MSG_API, msg); return ERR_MEM; } @@ -217,7 +217,7 @@ tcpip_timeout(u32_t msecs, sys_timeout_handler h, void *arg) { struct tcpip_msg *msg; - if (mbox != SYS_MBOX_NULL) { + if (sys_mbox_valid(&mbox)) { msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API); if (msg == NULL) { return ERR_MEM; @@ -227,7 +227,7 @@ tcpip_timeout(u32_t msecs, sys_timeout_handler h, void *arg) msg->msg.tmo.msecs = msecs; msg->msg.tmo.h = h; msg->msg.tmo.arg = arg; - sys_mbox_post(mbox, msg); + sys_mbox_post(&mbox, msg); return ERR_OK; } return ERR_VAL; @@ -246,7 +246,7 @@ tcpip_untimeout(sys_timeout_handler h, void *arg) { struct tcpip_msg *msg; - if (mbox != SYS_MBOX_NULL) { + if (sys_mbox_valid(&mbox)) { msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API); if (msg == NULL) { return ERR_MEM; @@ -255,7 +255,7 @@ tcpip_untimeout(sys_timeout_handler h, void *arg) msg->type = TCPIP_MSG_UNTIMEOUT; msg->msg.tmo.h = h; msg->msg.tmo.arg = arg; - sys_mbox_post(mbox, msg); + sys_mbox_post(&mbox, msg); return ERR_OK; } return ERR_VAL; @@ -279,11 +279,11 @@ tcpip_apimsg(struct api_msg *apimsg) apimsg->msg.err = ERR_VAL; #endif - if (mbox != SYS_MBOX_NULL) { + if (sys_mbox_valid(&mbox)) { msg.type = TCPIP_MSG_API; msg.msg.apimsg = apimsg; - sys_mbox_post(mbox, &msg); - sys_arch_sem_wait(apimsg->msg.conn->op_completed, 0); + sys_mbox_post(&mbox, &msg); + sys_arch_sem_wait(&apimsg->msg.conn->op_completed, 0); return apimsg->msg.err; } return ERR_VAL; @@ -329,18 +329,18 @@ tcpip_netifapi(struct netifapi_msg* netifapimsg) { struct tcpip_msg msg; - if (mbox != SYS_MBOX_NULL) { - netifapimsg->msg.sem = sys_sem_new(0); - if (netifapimsg->msg.sem == SYS_SEM_NULL) { - netifapimsg->msg.err = ERR_MEM; - return netifapimsg->msg.err; + if (sys_mbox_valid(&mbox)) { + err_t err = sys_sem_new(&netifapimsg->msg.sem, 0); + if (err != ERR_OK) { + netifapimsg->msg.err = err; + return err; } msg.type = TCPIP_MSG_NETIFAPI; msg.msg.netifapimsg = netifapimsg; - sys_mbox_post(mbox, &msg); - sys_sem_wait(netifapimsg->msg.sem); - sys_sem_free(netifapimsg->msg.sem); + sys_mbox_post(&mbox, &msg); + sys_sem_wait(&netifapimsg->msg.sem); + sys_sem_free(&netifapimsg->msg.sem); return netifapimsg->msg.err; } return ERR_VAL; @@ -380,9 +380,13 @@ tcpip_init(tcpip_init_done_fn initfunc, void *arg) tcpip_init_done = initfunc; tcpip_init_done_arg = arg; - mbox = sys_mbox_new(TCPIP_MBOX_SIZE); + if(sys_mbox_new(&mbox, TCPIP_MBOX_SIZE) != ERR_OK) { + LWIP_ASSERT("failed to create tcpip_thread mbox", 0); + } #if LWIP_TCPIP_CORE_LOCKING - lock_tcpip_core = sys_sem_new(1); + if(sys_mutex_new(&lock_tcpip_core) != ERR_OK) { + LWIP_ASSERT("failed to create lock_tcpip_core", 0); + } #endif /* LWIP_TCPIP_CORE_LOCKING */ sys_thread_new(TCPIP_THREAD_NAME, tcpip_thread, NULL, TCPIP_THREAD_STACKSIZE, TCPIP_THREAD_PRIO); diff --git a/src/core/mem.c b/src/core/mem.c index a0f5d26e..004343d7 100644 --- a/src/core/mem.c +++ b/src/core/mem.c @@ -189,7 +189,7 @@ static struct mem *ram_end; static struct mem *lfree; /** concurrent access protection */ -static sys_sem_t mem_sem; +static sys_mutex_t mem_mutex; #if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT @@ -207,8 +207,8 @@ static volatile u8_t mem_free_count; /* Protect the heap only by using a semaphore */ #define LWIP_MEM_FREE_DECL_PROTECT() -#define LWIP_MEM_FREE_PROTECT() sys_arch_sem_wait(mem_sem, 0) -#define LWIP_MEM_FREE_UNPROTECT() sys_sem_signal(mem_sem) +#define LWIP_MEM_FREE_PROTECT() sys_mutex_lock(&mem_mutex) +#define LWIP_MEM_FREE_UNPROTECT() sys_mutex_unlock(&mem_mutex) /* mem_malloc is protected using semaphore AND LWIP_MEM_ALLOC_PROTECT */ #define LWIP_MEM_ALLOC_DECL_PROTECT() #define LWIP_MEM_ALLOC_PROTECT() @@ -287,7 +287,9 @@ mem_init(void) ram_end->next = MEM_SIZE_ALIGNED; ram_end->prev = MEM_SIZE_ALIGNED; - mem_sem = sys_sem_new(1); + if(sys_mutex_new(&mem_mutex) != ERR_OK) { + LWIP_ASSERT("failed to create mem_mutex", 0); + } /* initialize the lowest-free pointer to the start of the heap */ lfree = (struct mem *)ram; @@ -514,7 +516,7 @@ mem_malloc(mem_size_t size) } /* protect the heap from concurrent access */ - sys_arch_sem_wait(mem_sem, 0); + sys_mutex_lock(&mem_mutex); LWIP_MEM_ALLOC_PROTECT(); #if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT /* run as long as a mem_free disturbed mem_malloc */ @@ -592,7 +594,7 @@ mem_malloc(mem_size_t size) LWIP_ASSERT("mem_malloc: !lfree->used", ((lfree == ram_end) || (!lfree->used))); } LWIP_MEM_ALLOC_UNPROTECT(); - sys_sem_signal(mem_sem); + sys_mutex_unlock(&mem_mutex); LWIP_ASSERT("mem_malloc: allocated memory not above ram_end.", (mem_ptr_t)mem + SIZEOF_STRUCT_MEM + size <= (mem_ptr_t)ram_end); LWIP_ASSERT("mem_malloc: allocated memory properly aligned.", @@ -610,7 +612,7 @@ mem_malloc(mem_size_t size) LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("mem_malloc: could not allocate %"S16_F" bytes\n", (s16_t)size)); MEM_STATS_INC(err); LWIP_MEM_ALLOC_UNPROTECT(); - sys_sem_signal(mem_sem); + sys_mutex_unlock(&mem_mutex); return NULL; } diff --git a/src/core/sys.c b/src/core/sys.c index 4d44d1bf..d3a77deb 100644 --- a/src/core/sys.c +++ b/src/core/sys.c @@ -54,9 +54,12 @@ void sys_msleep(u32_t ms) { if (ms > 0) { - sys_sem_t delaysem = sys_sem_new(0); - sys_arch_sem_wait(delaysem, ms); - sys_sem_free(delaysem); + sys_sem_t delaysem; + err_t err = sys_sem_new(&delaysem, 0); + if (err == ERR_OK) { + sys_arch_sem_wait(&delaysem, ms); + sys_sem_free(&delaysem); + } } } diff --git a/src/core/timers.c b/src/core/timers.c index 1c52f9db..606dbf77 100644 --- a/src/core/timers.c +++ b/src/core/timers.c @@ -423,7 +423,7 @@ sys_restart_timeouts(void) * @param msg the place to store the message */ void -sys_timeouts_mbox_fetch(sys_mbox_t mbox, void **msg) +sys_timeouts_mbox_fetch(sys_mbox_t *mbox, void **msg) { u32_t time_needed; struct sys_timeo *tmptimeout; diff --git a/src/include/lwip/sys.h b/src/include/lwip/sys.h index b41cc58f..0678b748 100644 --- a/src/include/lwip/sys.h +++ b/src/include/lwip/sys.h @@ -80,26 +80,74 @@ typedef void (*lwip_thread_fn)(void *arg); /* Function prototypes for functions to be implemented by platform ports (in sys_arch.c) */ +/* Mutex functions: */ + +/** Define LWIP_COMPAT_MUTEX if the port has no mutexes and binary semaphores + should be used instead */ +#if LWIP_COMPAT_MUTEX +/* for old ports that don't have mutexes: define them to binary semaphores */ +#define sys_mutex_t sys_sem_t +#define sys_mutex_new(mutex) sys_sem_new(mutex, 1) +#define sys_mutex_lock(mutex) sys_sem_wait(mutex) +#define sys_mutex_unlock(mutex) sys_sem_signal(mutex) +#define sys_mutex_free(mutex) sys_sem_free(mutex) +#define sys_mutex_valid(mutex) sys_sem_valid(mutex) +#define sys_mutex_set_invalid(mutex) sys_sem_set_invalid(mutex) + +#else /* LWIP_HAVE_MUTEX */ + +/** Create a new mutex + * @param mutex pointer to the mutex to create + * @return a new +err_t sys_mutex_new(sys_mutex_t *mutex); +/** Lock a mutex + * @param mutex the mutex to lock */ +void sys_mutex_lock(sys_mutex_t *mutex); +/** Unlock a mutex + * @param mutex the mutex to unlock */ +void sys_mutex_unlock(sys_mutex_t *mutex); +/** Delete a semaphore + * @param mutex the mutex to delete */ +void sys_mutex_free(sys_mutex_t *mutex); +#ifndef sys_mutex_valid +/** Check if a mutex is valid/allocated: return 1 for valid, 0 for invalid */ +int sys_mutex_valid(sys_mutex_t *mutex); +#endif +#ifndef sys_mutex_set_invalid +/** Set a mutex invalid so that sys_mutex_valid returns 0 */ +void sys_mutex_set_invalid(sys_mutex_t *mutex); +#endif +#endif /* LWIP_HAVE_MUTEX */ + /* Semaphore functions: */ /** Create a new semaphore + * @param sem pointer to the semaphore to create * @param count initial count of the semaphore - * @return a new semaphore */ -sys_sem_t sys_sem_new(u8_t count); + * @return ERR_OK if successful, another err_t otherwise */ +err_t sys_sem_new(sys_sem_t *sem, u8_t count); /** Signals a semaphore * @param sem the semaphore to signal */ -void sys_sem_signal(sys_sem_t sem); +void sys_sem_signal(sys_sem_t *sem); /** Wait for a semaphore for the specified timeout * @param sem the semaphore to wait for * @param timeout timeout in miliseconds to wait (0 = wait forever) * @return time (in miliseconds) waited for the semaphore * or SYS_ARCH_TIMEOUT on timeout */ -u32_t sys_arch_sem_wait(sys_sem_t sem, u32_t timeout); +u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout); /** Delete a semaphore * @param sem semaphore to delete */ -void sys_sem_free(sys_sem_t sem); +void sys_sem_free(sys_sem_t *sem); /** Wait for a semaphore - forever/no timeout */ #define sys_sem_wait(sem) sys_arch_sem_wait(sem, 0) +#ifndef sys_sem_valid +/** Check if a sempahore is valid/allocated: return 1 for valid, 0 for invalid */ +int sys_sem_valid(sys_sem_t *sem); +#endif +#ifndef sys_sem_set_invalid +/** Set a semaphore invalid so that sys_sem_valid returns 0 */ +void sys_sem_set_invalid(sys_sem_t *sem); +#endif /* Time functions. */ #ifndef sys_msleep @@ -109,18 +157,19 @@ void sys_msleep(u32_t ms); /* only has a (close to) 1 jiffy resolution. */ /* Mailbox functions. */ /** Create a new mbox of specified size + * @param mbox pointer to the mbox to create * @param size (miminum) number of messages in this mbox - * @return a new mbox */ -sys_mbox_t sys_mbox_new(int size); + * @return ERR_OK if successful, another err_t otherwise */ +err_t sys_mbox_new(sys_mbox_t *mbox, int size); /** Post a message to an mbox - may not fail * -> blocks if full, only used from tasks not from ISR * @param mbox mbox to posts the message * @param msg message to post (ATTENTION: can be NULL) */ -void sys_mbox_post(sys_mbox_t mbox, void *msg); +void sys_mbox_post(sys_mbox_t *mbox, void *msg); /** Try to post a message to an mbox - may fail if full or ISR * @param mbox mbox to posts the message * @param msg message to post (ATTENTION: can be NULL) */ -err_t sys_mbox_trypost(sys_mbox_t mbox, void *msg); +err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg); /** Wait for a new message to arrive in the mbox * @param mbox mbox to get a message from * @param msg pointer where the message is stored @@ -128,7 +177,7 @@ err_t sys_mbox_trypost(sys_mbox_t mbox, void *msg); * @return time (in miliseconds) waited for a message, may be 0 if not waited or SYS_ARCH_TIMEOUT on timeout * The returned time has to be accurate to prevent timer jitter! */ -u32_t sys_arch_mbox_fetch(sys_mbox_t mbox, void **msg, u32_t timeout); +u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout); /* Allow port to override with a macro, e.g. special timout for sys_arch_mbox_fetch() */ #ifndef sys_arch_mbox_tryfetch /** Wait for a new message to arrive in the mbox @@ -137,14 +186,22 @@ u32_t sys_arch_mbox_fetch(sys_mbox_t mbox, void **msg, u32_t timeout); * @param timeout maximum time (in miliseconds) to wait for a message * @return 0 (miliseconds) if a message has been received * or SYS_MBOX_EMPTY if the mailbox is empty */ -u32_t sys_arch_mbox_tryfetch(sys_mbox_t mbox, void **msg); +u32_t sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg); #endif /** For now, we map straight to sys_arch implementation. */ #define sys_mbox_tryfetch(mbox, msg) sys_arch_mbox_tryfetch(mbox, msg) /** Delete an mbox * @param mbox mbox to delete */ -void sys_mbox_free(sys_mbox_t mbox); +void sys_mbox_free(sys_mbox_t *mbox); #define sys_mbox_fetch(mbox, msg) sys_arch_mbox_fetch(mbox, msg, 0) +#ifndef sys_mbox_valid +/** Check if an mbox is valid/allocated: return 1 for valid, 0 for invalid */ +int sys_mbox_valid(sys_mbox_t *mbox); +#endif +#ifndef sys_mbox_set_invalid +/** Set an mbox invalid so that sys_mbox_valid returns 0 */ +void sys_mbox_set_invalid(sys_mbox_t *mbox); +#endif /** The only thread function: * Creates a new thread diff --git a/src/include/lwip/tcpip.h b/src/include/lwip/tcpip.h index 69b0ec41..48418746 100644 --- a/src/include/lwip/tcpip.h +++ b/src/include/lwip/tcpip.h @@ -50,9 +50,9 @@ extern "C" { #if LWIP_TCPIP_CORE_LOCKING /** The global semaphore to lock the stack. */ -extern sys_sem_t lock_tcpip_core; -#define LOCK_TCPIP_CORE() sys_sem_wait(lock_tcpip_core) -#define UNLOCK_TCPIP_CORE() sys_sem_signal(lock_tcpip_core) +extern sys_mutex_t lock_tcpip_core; +#define LOCK_TCPIP_CORE() sys_mutex_lock(&lock_tcpip_core) +#define UNLOCK_TCPIP_CORE() sys_mutex_unlock(&lock_tcpip_core) #define TCPIP_APIMSG(m) tcpip_apimsg_lock(m) #define TCPIP_APIMSG_ACK(m) #define TCPIP_NETIFAPI(m) tcpip_netifapi_lock(m) @@ -61,9 +61,9 @@ extern sys_sem_t lock_tcpip_core; #define LOCK_TCPIP_CORE() #define UNLOCK_TCPIP_CORE() #define TCPIP_APIMSG(m) tcpip_apimsg(m) -#define TCPIP_APIMSG_ACK(m) sys_sem_signal(m->conn->op_completed) +#define TCPIP_APIMSG_ACK(m) sys_sem_signal(&m->conn->op_completed) #define TCPIP_NETIFAPI(m) tcpip_netifapi(m) -#define TCPIP_NETIFAPI_ACK(m) sys_sem_signal(m->sem) +#define TCPIP_NETIFAPI_ACK(m) sys_sem_signal(&m->sem) #endif /* LWIP_TCPIP_CORE_LOCKING */ /** Function prototype for the init_done function passed to tcpip_init */ diff --git a/src/include/lwip/timers.h b/src/include/lwip/timers.h index 9c6e4a6c..c680b24c 100644 --- a/src/include/lwip/timers.h +++ b/src/include/lwip/timers.h @@ -81,7 +81,7 @@ void sys_untimeout(sys_timeout_handler h, void *arg); void sys_check_timeouts(void); void sys_restart_timeouts(void); #else /* NO_SYS */ -void sys_timeouts_mbox_fetch(sys_mbox_t mbox, void **msg); +void sys_timeouts_mbox_fetch(sys_mbox_t *mbox, void **msg); #endif /* NO_SYS */