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)

This commit is contained in:
goldsimon 2010-02-12 13:49:21 +00:00
parent 2d1631792a
commit 0030d1ade5
11 changed files with 232 additions and 151 deletions

View File

@ -19,6 +19,13 @@ HISTORY
++ New features: ++ 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) 2010-02-09: Simon Goldschmidt (Simon Kallweit)
* timers.c/.h: Added function sys_restart_timeouts() from patch #7085 * timers.c/.h: Added function sys_restart_timeouts() from patch #7085
(Restart system timeout handling) (Restart system timeout handling)

View File

@ -77,11 +77,11 @@ netconn_new_with_proto_and_callback(enum netconn_type t, u8_t proto, netconn_cal
msg.msg.conn = conn; msg.msg.conn = conn;
if (TCPIP_APIMSG(&msg) != ERR_OK) { if (TCPIP_APIMSG(&msg) != ERR_OK) {
LWIP_ASSERT("freeing conn without freeing pcb", conn->pcb.tcp == NULL); 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 op_completed", sys_sem_valid(&conn->op_completed));
LWIP_ASSERT("conn has no recvmbox", conn->recvmbox != SYS_MBOX_NULL); LWIP_ASSERT("conn has no recvmbox", sys_mbox_valid(&conn->recvmbox));
LWIP_ASSERT("conn->acceptmbox shouldn't exist", conn->acceptmbox == SYS_MBOX_NULL); LWIP_ASSERT("conn->acceptmbox shouldn't exist", !sys_mbox_valid(&conn->acceptmbox));
sys_sem_free(conn->op_completed); sys_sem_free(&conn->op_completed);
sys_mbox_free(conn->recvmbox); sys_mbox_free(&conn->recvmbox);
memp_free(MEMP_NETCONN, conn); memp_free(MEMP_NETCONN, conn);
return NULL; 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;); LWIP_ERROR("netconn_accept: invalid pointer", (new_conn != NULL), return ERR_ARG;);
*new_conn = NULL; *new_conn = NULL;
LWIP_ERROR("netconn_accept: invalid conn", (conn != NULL), return ERR_ARG;); 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; err = conn->last_err;
if (ERR_IS_FATAL(err)) { if (ERR_IS_FATAL(err)) {
@ -287,12 +287,12 @@ netconn_accept(struct netconn *conn, struct netconn **new_conn)
} }
#if LWIP_SO_RCVTIMEO #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); NETCONN_SET_SAFE_ERR(conn, ERR_TIMEOUT);
return ERR_TIMEOUT; return ERR_TIMEOUT;
} }
#else #else
sys_arch_mbox_fetch(conn->acceptmbox, (void **)&newconn, 0); sys_arch_mbox_fetch(&conn->acceptmbox, (void **)&newconn, 0);
#endif /* LWIP_SO_RCVTIMEO*/ #endif /* LWIP_SO_RCVTIMEO*/
/* Register event with callback */ /* Register event with callback */
API_EVENT(conn, NETCONN_EVT_RCVMINUS, 0); 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;); LWIP_ERROR("netconn_recv: invalid pointer", (new_buf != NULL), return ERR_ARG;);
*new_buf = NULL; *new_buf = NULL;
LWIP_ERROR("netconn_recv: invalid conn", (conn != NULL), return ERR_ARG;); 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; err = conn->last_err;
if (ERR_IS_FATAL(err)) { if (ERR_IS_FATAL(err)) {
/* don't recv on fatal errors: this might block the application task /* don't recv on fatal errors: this might block the application task
waiting on recvmbox forever! */ 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; return err;
} }
@ -355,13 +357,13 @@ netconn_recv(struct netconn *conn, struct netbuf **new_buf)
} }
#if LWIP_SO_RCVTIMEO #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); memp_free(MEMP_NETBUF, buf);
NETCONN_SET_SAFE_ERR(conn, ERR_TIMEOUT); NETCONN_SET_SAFE_ERR(conn, ERR_TIMEOUT);
return ERR_TIMEOUT; return ERR_TIMEOUT;
} }
#else #else
sys_arch_mbox_fetch(conn->recvmbox, (void **)&p, 0); sys_arch_mbox_fetch(&conn->recvmbox, (void **)&p, 0);
#endif /* LWIP_SO_RCVTIMEO*/ #endif /* LWIP_SO_RCVTIMEO*/
if (p != NULL) { if (p != NULL) {
@ -406,12 +408,12 @@ netconn_recv(struct netconn *conn, struct netbuf **new_buf)
} else { } else {
#if (LWIP_UDP || LWIP_RAW) #if (LWIP_UDP || LWIP_RAW)
#if LWIP_SO_RCVTIMEO #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); NETCONN_SET_SAFE_ERR(conn, ERR_TIMEOUT);
return ERR_TIMEOUT; return ERR_TIMEOUT;
} }
#else #else
sys_arch_mbox_fetch(conn->recvmbox, (void **)&buf, 0); sys_arch_mbox_fetch(&conn->recvmbox, (void **)&buf, 0);
#endif /* LWIP_SO_RCVTIMEO*/ #endif /* LWIP_SO_RCVTIMEO*/
LWIP_ASSERT("buf != NULL", buf != NULL); LWIP_ASSERT("buf != NULL", buf != NULL);

View File

@ -90,7 +90,7 @@ recv_raw(void *arg, struct raw_pcb *pcb, struct pbuf *p,
#if LWIP_SO_RCVBUF #if LWIP_SO_RCVBUF
SYS_ARCH_GET(conn->recv_avail, recv_avail); 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)) { ((recv_avail + (int)(p->tot_len)) <= conn->recv_bufsize)) {
#else /* LWIP_SO_RCVBUF */ #else /* LWIP_SO_RCVBUF */
if ((conn != NULL) && (conn->recvmbox != SYS_MBOX_NULL)) { 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; buf->port = pcb->protocol;
len = q->tot_len; 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); netbuf_delete(buf);
return 0; return 0;
} else { } else {
@ -159,7 +159,7 @@ recv_udp(void *arg, struct udp_pcb *pcb, struct pbuf *p,
#if LWIP_SO_RCVBUF #if LWIP_SO_RCVBUF
SYS_ARCH_GET(conn->recv_avail, recv_avail); 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)) { ((recv_avail + (int)(p->tot_len)) > conn->recv_bufsize)) {
#else /* LWIP_SO_RCVBUF */ #else /* LWIP_SO_RCVBUF */
if ((conn == NULL) || (conn->recvmbox == SYS_MBOX_NULL)) { 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; 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); netbuf_delete(buf);
return; return;
} else { } else {
@ -222,7 +222,7 @@ recv_tcp(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
if (conn == NULL) { if (conn == NULL) {
return ERR_VAL; return ERR_VAL;
} }
if (conn->recvmbox == SYS_MBOX_NULL) { if (!sys_mbox_valid(&conn->recvmbox)) {
/* recvmbox already deleted */ /* recvmbox already deleted */
if (p != NULL) { if (p != NULL) {
tcp_recved(pcb, p->tot_len); 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; 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! */ /* don't deallocate p: it is presented to us later again from tcp_fasttmr! */
return ERR_MEM; return ERR_MEM;
} else { } else {
@ -354,14 +354,14 @@ err_tcp(void *arg, err_t err)
API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0); API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0);
/* pass NULL-message to recvmbox to wake up pending recv */ /* 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 */ /* 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 */ /* 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 */ /* 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) || 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->err = err;
conn->current_msg = NULL; conn->current_msg = NULL;
/* wake up the waiting task */ /* wake up the waiting task */
sys_sem_signal(conn->op_completed); sys_sem_signal(&conn->op_completed);
} }
} else { } else {
LWIP_ASSERT("conn->current_msg == NULL", conn->current_msg == NULL); 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 */ #endif /* API_MSG_DEBUG */
conn = (struct netconn *)arg; 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")); LWIP_DEBUGF(API_MSG_DEBUG, ("accept_function: acceptmbox already deleted\n"));
return ERR_VAL; return ERR_VAL;
} }
@ -439,13 +439,13 @@ accept_function(void *arg, struct tcp_pcb *newpcb, err_t err)
to the application thread */ to the application thread */
newconn->last_err = err; 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(), /* When returning != ERR_OK, the pcb is aborted in tcp_process(),
so do nothing here! */ so do nothing here! */
newconn->pcb.tcp = NULL; newconn->pcb.tcp = NULL;
/* no need to drain since we know the recvmbox is empty. */ /* no need to drain since we know the recvmbox is empty. */
sys_mbox_free(newconn->recvmbox); sys_mbox_free(&newconn->recvmbox);
newconn->recvmbox = SYS_MBOX_NULL; sys_mbox_set_invalid(&newconn->recvmbox);
netconn_free(newconn); netconn_free(newconn);
return ERR_MEM; return ERR_MEM;
} else { } else {
@ -587,20 +587,20 @@ netconn_alloc(enum netconn_type t, netconn_callback callback)
} }
#endif #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); memp_free(MEMP_NETCONN, conn);
return NULL; return NULL;
} }
if ((conn->recvmbox = sys_mbox_new(size)) == SYS_MBOX_NULL) { if (sys_mbox_new(&conn->recvmbox, size) != ERR_OK) {
sys_sem_free(conn->op_completed); sys_sem_free(&conn->op_completed);
memp_free(MEMP_NETCONN, conn); memp_free(MEMP_NETCONN, conn);
return NULL; return NULL;
} }
conn->acceptmbox = SYS_MBOX_NULL; sys_mbox_set_invalid(&conn->acceptmbox);
conn->state = NETCONN_NONE; conn->state = NETCONN_NONE;
/* initialize socket to -1 since 0 is a valid socket */
#if LWIP_SOCKET #if LWIP_SOCKET
/* initialize socket to -1 since 0 is a valid socket */
conn->socket = -1; conn->socket = -1;
#endif /* LWIP_SOCKET */ #endif /* LWIP_SOCKET */
conn->callback = callback; conn->callback = callback;
@ -608,9 +608,6 @@ netconn_alloc(enum netconn_type t, netconn_callback callback)
#if LWIP_TCP #if LWIP_TCP
conn->current_msg = NULL; conn->current_msg = NULL;
conn->write_offset = 0; conn->write_offset = 0;
#if LWIP_TCPIP_CORE_LOCKING
conn->write_delayed = 0;
#endif /* LWIP_TCPIP_CORE_LOCKING */
#endif /* LWIP_TCP */ #endif /* LWIP_TCP */
#if LWIP_SO_RCVTIMEO #if LWIP_SO_RCVTIMEO
conn->recv_timeout = 0; 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("PCB must be deallocated outside this function", conn->pcb.tcp == NULL);
LWIP_ASSERT("recvmbox must be deallocated before calling this function", 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", 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); sys_sem_free(&conn->op_completed);
conn->op_completed = SYS_SEM_NULL; sys_sem_set_invalid(&conn->op_completed);
memp_free(MEMP_NETCONN, conn); memp_free(MEMP_NETCONN, conn);
} }
@ -656,13 +653,12 @@ netconn_drain(struct netconn *conn)
{ {
void *mem; void *mem;
struct pbuf *p; 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. */ /* Delete and drain the recvmbox. */
mbox = conn->recvmbox; if (sys_mbox_valid(&conn->recvmbox)) {
conn->recvmbox = SYS_MBOX_NULL; while (sys_mbox_tryfetch(&conn->recvmbox, &mem) != SYS_MBOX_EMPTY) {
if (mbox != SYS_MBOX_NULL) {
while (sys_mbox_tryfetch(mbox, &mem) != SYS_MBOX_EMPTY) {
if (conn->type == NETCONN_TCP) { if (conn->type == NETCONN_TCP) {
if(mem != NULL) { if(mem != NULL) {
p = (struct pbuf*)mem; p = (struct pbuf*)mem;
@ -676,14 +672,13 @@ netconn_drain(struct netconn *conn)
netbuf_delete((struct netbuf *)mem); 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. */ /* Delete and drain the acceptmbox. */
mbox = conn->acceptmbox; if (sys_mbox_valid(&conn->acceptmbox)) {
conn->acceptmbox = SYS_MBOX_NULL; while (sys_mbox_tryfetch(&conn->acceptmbox, &mem) != SYS_MBOX_EMPTY) {
if (mbox != SYS_MBOX_NULL) {
while (sys_mbox_tryfetch(mbox, &mem) != SYS_MBOX_EMPTY) {
/* Only tcp pcbs have an acceptmbox, so no need to check conn->type */ /* Only tcp pcbs have an acceptmbox, so no need to check conn->type */
/* pcb might be set to NULL already by err_tcp() */ /* pcb might be set to NULL already by err_tcp() */
if (conn->pcb.tcp != NULL) { if (conn->pcb.tcp != NULL) {
@ -691,7 +686,8 @@ netconn_drain(struct netconn *conn)
} }
netconn_delete((struct netconn *)mem); 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_RCVPLUS, 0);
API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0); API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0);
/* wake up the application task */ /* wake up the application task */
sys_sem_signal(conn->op_completed); sys_sem_signal(&conn->op_completed);
} else { } else {
/* Closing failed, restore some of the callbacks */ /* Closing failed, restore some of the callbacks */
/* Closing of listen pcb will never fail! */ /* 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_RCVPLUS, 0);
API_EVENT(msg->conn, NETCONN_EVT_SENDPLUS, 0); API_EVENT(msg->conn, NETCONN_EVT_SENDPLUS, 0);
} }
if (msg->conn->op_completed != SYS_SEM_NULL) { if (sys_sem_valid(&msg->conn->op_completed)) {
sys_sem_signal(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); API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0);
if (was_blocking) { if (was_blocking) {
sys_sem_signal(conn->op_completed); sys_sem_signal(&conn->op_completed);
} }
return ERR_OK; return ERR_OK;
} }
@ -962,7 +958,7 @@ do_connect(struct api_msg_msg *msg)
break; 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; msg->err = ERR_MEM;
} else { } else {
/* delete the recvmbox and allocate the acceptmbox */ /* 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? */ /** @todo: should we drain the recvmbox here? */
sys_mbox_free(msg->conn->recvmbox); sys_mbox_free(&msg->conn->recvmbox);
msg->conn->recvmbox = SYS_MBOX_NULL; sys_mbox_set_invalid(&msg->conn->recvmbox);
} }
msg->err = ERR_OK; msg->err = ERR_OK;
if (msg->conn->acceptmbox == SYS_MBOX_NULL) { if (!sys_mbox_valid(&msg->conn->acceptmbox)) {
if ((msg->conn->acceptmbox = sys_mbox_new(DEFAULT_ACCEPTMBOX_SIZE)) == SYS_MBOX_NULL) { msg->err = sys_mbox_new(&msg->conn->acceptmbox, DEFAULT_ACCEPTMBOX_SIZE);
msg->err = ERR_MEM;
}
} }
if (msg->err == ERR_OK) { if (msg->err == ERR_OK) {
msg->conn->state = NETCONN_LISTEN; msg->conn->state = NETCONN_LISTEN;
@ -1150,7 +1144,7 @@ do_writemore(struct netconn *conn)
if (diff > 0xffffUL) { /* max_u16_t */ if (diff > 0xffffUL) { /* max_u16_t */
len = 0xffff; len = 0xffff;
#if LWIP_TCPIP_CORE_LOCKING #if LWIP_TCPIP_CORE_LOCKING
conn->write_delayed = 1; conn->flags |= NETCONN_FLAG_WRITE_DELAYED;
#endif #endif
} else { } else {
len = (u16_t)diff; len = (u16_t)diff;
@ -1160,7 +1154,7 @@ do_writemore(struct netconn *conn)
/* don't try to write more than sendbuf */ /* don't try to write more than sendbuf */
len = available; len = available;
#if LWIP_TCPIP_CORE_LOCKING #if LWIP_TCPIP_CORE_LOCKING
conn->write_delayed = 1; conn->flags |= NETCONN_FLAG_WRITE_DELAYED;
#endif #endif
} }
@ -1193,7 +1187,7 @@ do_writemore(struct netconn *conn)
tcp_output(conn->pcb.tcp); tcp_output(conn->pcb.tcp);
#if LWIP_TCPIP_CORE_LOCKING #if LWIP_TCPIP_CORE_LOCKING
conn->write_delayed = 1; conn->flags |= NETCONN_FLAG_WRITE_DELAYED;
#endif #endif
} else { } else {
/* On errors != ERR_MEM, we don't try writing any more but return /* 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->current_msg = NULL;
conn->state = NETCONN_NONE; conn->state = NETCONN_NONE;
#if LWIP_TCPIP_CORE_LOCKING #if LWIP_TCPIP_CORE_LOCKING
if (conn->write_delayed != 0) if ((conn->flags & NETCONN_FLAG_WRITE_DELAYED) != 0)
#endif #endif
{ {
sys_sem_signal(conn->op_completed); sys_sem_signal(&conn->op_completed);
} }
} }
#if LWIP_TCPIP_CORE_LOCKING #if LWIP_TCPIP_CORE_LOCKING
@ -1247,11 +1241,11 @@ do_write(struct api_msg_msg *msg)
msg->conn->current_msg = msg; msg->conn->current_msg = msg;
msg->conn->write_offset = 0; msg->conn->write_offset = 0;
#if LWIP_TCPIP_CORE_LOCKING #if LWIP_TCPIP_CORE_LOCKING
msg->conn->write_delayed = 0; msg->conn->flags &= ~NETCONN_FLAG_WRITE_DELAYED;
if (do_writemore(msg->conn) != ERR_OK) { if (do_writemore(msg->conn) != ERR_OK) {
LWIP_ASSERT("state!", msg->conn->state == NETCONN_WRITE); LWIP_ASSERT("state!", msg->conn->state == NETCONN_WRITE);
UNLOCK_TCPIP_CORE(); UNLOCK_TCPIP_CORE();
sys_arch_sem_wait(msg->conn->op_completed, 0); sys_arch_sem_wait(&msg->conn->op_completed, 0);
LOCK_TCPIP_CORE(); LOCK_TCPIP_CORE();
LWIP_ASSERT("state!", msg->conn->state == NETCONN_NONE); LWIP_ASSERT("state!", msg->conn->state == NETCONN_NONE);
} }
@ -1355,7 +1349,7 @@ do_close(struct api_msg_msg *msg)
{ {
msg->err = ERR_VAL; msg->err = ERR_VAL;
} }
sys_sem_signal(msg->conn->op_completed); sys_sem_signal(&msg->conn->op_completed);
} }
#if LWIP_IGMP #if LWIP_IGMP

View File

@ -118,7 +118,7 @@ static struct lwip_socket sockets[NUM_SOCKETS];
static struct lwip_select_cb *select_cb_list; static struct lwip_select_cb *select_cb_list;
/** Semaphore protecting 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 /** Table to quickly map an lwIP error (err_t) to a socket error
* by using -err as an index */ * by using -err as an index */
@ -172,7 +172,9 @@ static void lwip_setsockopt_internal(void *arg);
void void
lwip_socket_init(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; u32_t msectimeout;
struct lwip_select_cb select_cb; struct lwip_select_cb select_cb;
struct lwip_select_cb *p_selcb; struct lwip_select_cb *p_selcb;
err_t err;
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select(%d, %p, %p, %p, tvsec=%ld tvusec=%ld)\n", LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select(%d, %p, %p, %p, tvsec=%ld tvusec=%ld)\n",
maxfdp1, (void *)readset, (void *) writeset, (void *) exceptset, 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; select_cb.sem_signalled = 0;
/* Protect ourselves searching through the list */ /* Protect ourselves searching through the list */
sys_sem_wait(selectsem); sys_mutex_lock(&select_lock);
if (readset) if (readset)
lreadset = *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 we don't have any current events, then suspend if we are supposed to */
if (!nready) { if (!nready) {
if (timeout && timeout->tv_sec == 0 && timeout->tv_usec == 0) { if (timeout && timeout->tv_sec == 0 && timeout->tv_usec == 0) {
sys_sem_signal(selectsem); sys_mutex_unlock(&select_lock);
if (readset) if (readset)
FD_ZERO(readset); FD_ZERO(readset);
if (writeset) 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 * list is only valid while we are in this function, so it's ok
* to use local variables */ * 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 */ /* Note that we are still protected */
/* Put this select_cb on top of list */ /* Put this select_cb on top of list */
select_cb.next = select_cb_list; select_cb.next = select_cb_list;
select_cb_list = &select_cb; select_cb_list = &select_cb;
/* Now we can safely unprotect */ /* Now we can safely unprotect */
sys_sem_signal(selectsem); sys_mutex_unlock(&select_lock);
/* Now just wait to be woken */ /* Now just wait to be woken */
if (timeout == 0) if (timeout == 0)
@ -1017,23 +1026,24 @@ lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
msectimeout = 1; 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 */ /* Take us off the list */
sys_sem_wait(selectsem); sys_mutex_lock(&select_lock);
if (select_cb_list == &select_cb) if (select_cb_list == &select_cb) {
select_cb_list = select_cb.next; select_cb_list = select_cb.next;
else } else {
for (p_selcb = select_cb_list; p_selcb; p_selcb = p_selcb->next) { for (p_selcb = select_cb_list; p_selcb; p_selcb = p_selcb->next) {
if (p_selcb->next == &select_cb) { if (p_selcb->next == &select_cb) {
p_selcb->next = select_cb.next; p_selcb->next = select_cb.next;
break; 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) { if (waitres == SYS_ARCH_TIMEOUT) {
/* Timeout */ /* Timeout */
if (readset) if (readset)
@ -1064,8 +1074,9 @@ lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
/* See what's set */ /* See what's set */
nready = lwip_selscan(maxfdp1, &lreadset, &lwriteset, &lexceptset); nready = lwip_selscan(maxfdp1, &lreadset, &lwriteset, &lexceptset);
} else } else {
sys_sem_signal(selectsem); sys_mutex_unlock(&select_lock);
}
if (readset) if (readset)
*readset = lreadset; *readset = lreadset;
@ -1123,7 +1134,7 @@ event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len)
return; return;
} }
sys_sem_wait(selectsem); sys_mutex_lock(&select_lock);
/* Set event as required */ /* Set event as required */
switch (evt) { switch (evt) {
case NETCONN_EVT_RCVPLUS: 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); LWIP_ASSERT("unknown event", 0);
break; break;
} }
sys_sem_signal(selectsem); sys_mutex_unlock(&select_lock);
/* Now decide if anyone is waiting for this socket */ /* Now decide if anyone is waiting for this socket */
/* NOTE: This code is written this way to protect the select link list /* 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 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 multiple times ONLY IF a select was actually waiting. We go through
the list the number of waiting select calls + 1. This list is the list the number of waiting select calls + 1. This list is
expected to be small. */ expected to be small. */
while (1) { while (1) {
sys_sem_wait(selectsem); sys_mutex_lock(&select_lock);
for (scb = select_cb_list; scb; scb = scb->next) { for (scb = select_cb_list; scb; scb = scb->next) {
if (scb->sem_signalled == 0) { if (scb->sem_signalled == 0) {
/* Test this select call for our socket */ /* 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) { if (scb) {
scb->sem_signalled = 1; scb->sem_signalled = 1;
sys_sem_signal(scb->sem); sys_sem_signal(&scb->sem);
sys_sem_signal(selectsem); sys_mutex_unlock(&select_lock);
} else { } else {
sys_sem_signal(selectsem); sys_mutex_unlock(&select_lock);
break; break;
} }
} }
@ -1415,7 +1426,7 @@ lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
data.optlen = optlen; data.optlen = optlen;
data.err = err; data.err = err;
tcpip_callback(lwip_getsockopt_internal, &data); 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 */ /* maybe lwip_getsockopt_internal has changed err */
err = data.err; err = data.err;
@ -1600,7 +1611,7 @@ lwip_getsockopt_internal(void *arg)
break; break;
#endif /* LWIP_UDP */ #endif /* LWIP_UDP */
} /* switch (level) */ } /* switch (level) */
sys_sem_signal(sock->conn->op_completed); sys_sem_signal(&sock->conn->op_completed);
} }
int int
@ -1790,7 +1801,7 @@ lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t opt
data.optlen = &optlen; data.optlen = &optlen;
data.err = err; data.err = err;
tcpip_callback(lwip_setsockopt_internal, &data); 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 */ /* maybe lwip_setsockopt_internal has changed err */
err = data.err; err = data.err;
@ -1978,7 +1989,7 @@ lwip_setsockopt_internal(void *arg)
break; break;
#endif /* LWIP_UDP */ #endif /* LWIP_UDP */
} /* switch (level) */ } /* switch (level) */
sys_sem_signal(sock->conn->op_completed); sys_sem_signal(&sock->conn->op_completed);
} }
int int
@ -2000,8 +2011,9 @@ lwip_ioctl(int s, long cmd, void *argp)
} }
SYS_ARCH_GET(sock->conn->recv_avail, recv_avail); SYS_ARCH_GET(sock->conn->recv_avail, recv_avail);
if (recv_avail < 0) if (recv_avail < 0) {
recv_avail = 0; recv_avail = 0;
}
*((u16_t*)argp) = (u16_t)recv_avail; *((u16_t*)argp) = (u16_t)recv_avail;
/* Check if there is data left from the last recv operation. /maq 041215 */ /* Check if there is data left from the last recv operation. /maq 041215 */

View File

@ -52,11 +52,11 @@
/* global variables */ /* global variables */
static tcpip_init_done_fn tcpip_init_done; static tcpip_init_done_fn tcpip_init_done;
static void *tcpip_init_done_arg; static void *tcpip_init_done_arg;
static sys_mbox_t mbox = SYS_MBOX_NULL; static sys_mbox_t mbox;
#if LWIP_TCPIP_CORE_LOCKING #if LWIP_TCPIP_CORE_LOCKING
/** The global semaphore to lock the stack. */ /** The global semaphore to lock the stack. */
sys_sem_t lock_tcpip_core; sys_mutex_t lock_tcpip_core;
#endif /* LWIP_TCPIP_CORE_LOCKING */ #endif /* LWIP_TCPIP_CORE_LOCKING */
@ -84,7 +84,7 @@ tcpip_thread(void *arg)
while (1) { /* MAIN Loop */ while (1) { /* MAIN Loop */
UNLOCK_TCPIP_CORE(); UNLOCK_TCPIP_CORE();
/* wait for a message, timeouts are processed while waiting */ /* 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(); LOCK_TCPIP_CORE();
switch (msg->type) { switch (msg->type) {
#if LWIP_NETCONN #if LWIP_NETCONN
@ -148,7 +148,7 @@ tcpip_input(struct pbuf *p, struct netif *inp)
{ {
struct tcpip_msg *msg; struct tcpip_msg *msg;
if (mbox != SYS_MBOX_NULL) { if (sys_mbox_valid(&mbox)) {
msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_INPKT); msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_INPKT);
if (msg == NULL) { if (msg == NULL) {
return ERR_MEM; return ERR_MEM;
@ -157,7 +157,7 @@ tcpip_input(struct pbuf *p, struct netif *inp)
msg->type = TCPIP_MSG_INPKT; msg->type = TCPIP_MSG_INPKT;
msg->msg.inp.p = p; msg->msg.inp.p = p;
msg->msg.inp.netif = inp; 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); memp_free(MEMP_TCPIP_MSG_INPKT, msg);
return ERR_MEM; return ERR_MEM;
} }
@ -182,7 +182,7 @@ tcpip_callback_with_block(tcpip_callback_fn function, void *ctx, u8_t block)
{ {
struct tcpip_msg *msg; struct tcpip_msg *msg;
if (mbox != SYS_MBOX_NULL) { if (sys_mbox_valid(&mbox)) {
msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API); msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API);
if (msg == NULL) { if (msg == NULL) {
return ERR_MEM; 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.function = function;
msg->msg.cb.ctx = ctx; msg->msg.cb.ctx = ctx;
if (block) { if (block) {
sys_mbox_post(mbox, msg); sys_mbox_post(&mbox, msg);
} else { } else {
if (sys_mbox_trypost(mbox, msg) != ERR_OK) { if (sys_mbox_trypost(&mbox, msg) != ERR_OK) {
memp_free(MEMP_TCPIP_MSG_API, msg); memp_free(MEMP_TCPIP_MSG_API, msg);
return ERR_MEM; return ERR_MEM;
} }
@ -217,7 +217,7 @@ tcpip_timeout(u32_t msecs, sys_timeout_handler h, void *arg)
{ {
struct tcpip_msg *msg; struct tcpip_msg *msg;
if (mbox != SYS_MBOX_NULL) { if (sys_mbox_valid(&mbox)) {
msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API); msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API);
if (msg == NULL) { if (msg == NULL) {
return ERR_MEM; 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.msecs = msecs;
msg->msg.tmo.h = h; msg->msg.tmo.h = h;
msg->msg.tmo.arg = arg; msg->msg.tmo.arg = arg;
sys_mbox_post(mbox, msg); sys_mbox_post(&mbox, msg);
return ERR_OK; return ERR_OK;
} }
return ERR_VAL; return ERR_VAL;
@ -246,7 +246,7 @@ tcpip_untimeout(sys_timeout_handler h, void *arg)
{ {
struct tcpip_msg *msg; struct tcpip_msg *msg;
if (mbox != SYS_MBOX_NULL) { if (sys_mbox_valid(&mbox)) {
msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API); msg = (struct tcpip_msg *)memp_malloc(MEMP_TCPIP_MSG_API);
if (msg == NULL) { if (msg == NULL) {
return ERR_MEM; return ERR_MEM;
@ -255,7 +255,7 @@ tcpip_untimeout(sys_timeout_handler h, void *arg)
msg->type = TCPIP_MSG_UNTIMEOUT; msg->type = TCPIP_MSG_UNTIMEOUT;
msg->msg.tmo.h = h; msg->msg.tmo.h = h;
msg->msg.tmo.arg = arg; msg->msg.tmo.arg = arg;
sys_mbox_post(mbox, msg); sys_mbox_post(&mbox, msg);
return ERR_OK; return ERR_OK;
} }
return ERR_VAL; return ERR_VAL;
@ -279,11 +279,11 @@ tcpip_apimsg(struct api_msg *apimsg)
apimsg->msg.err = ERR_VAL; apimsg->msg.err = ERR_VAL;
#endif #endif
if (mbox != SYS_MBOX_NULL) { if (sys_mbox_valid(&mbox)) {
msg.type = TCPIP_MSG_API; msg.type = TCPIP_MSG_API;
msg.msg.apimsg = apimsg; msg.msg.apimsg = apimsg;
sys_mbox_post(mbox, &msg); sys_mbox_post(&mbox, &msg);
sys_arch_sem_wait(apimsg->msg.conn->op_completed, 0); sys_arch_sem_wait(&apimsg->msg.conn->op_completed, 0);
return apimsg->msg.err; return apimsg->msg.err;
} }
return ERR_VAL; return ERR_VAL;
@ -329,18 +329,18 @@ tcpip_netifapi(struct netifapi_msg* netifapimsg)
{ {
struct tcpip_msg msg; struct tcpip_msg msg;
if (mbox != SYS_MBOX_NULL) { if (sys_mbox_valid(&mbox)) {
netifapimsg->msg.sem = sys_sem_new(0); err_t err = sys_sem_new(&netifapimsg->msg.sem, 0);
if (netifapimsg->msg.sem == SYS_SEM_NULL) { if (err != ERR_OK) {
netifapimsg->msg.err = ERR_MEM; netifapimsg->msg.err = err;
return netifapimsg->msg.err; return err;
} }
msg.type = TCPIP_MSG_NETIFAPI; msg.type = TCPIP_MSG_NETIFAPI;
msg.msg.netifapimsg = netifapimsg; msg.msg.netifapimsg = netifapimsg;
sys_mbox_post(mbox, &msg); sys_mbox_post(&mbox, &msg);
sys_sem_wait(netifapimsg->msg.sem); sys_sem_wait(&netifapimsg->msg.sem);
sys_sem_free(netifapimsg->msg.sem); sys_sem_free(&netifapimsg->msg.sem);
return netifapimsg->msg.err; return netifapimsg->msg.err;
} }
return ERR_VAL; return ERR_VAL;
@ -380,9 +380,13 @@ tcpip_init(tcpip_init_done_fn initfunc, void *arg)
tcpip_init_done = initfunc; tcpip_init_done = initfunc;
tcpip_init_done_arg = arg; 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 #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 */ #endif /* LWIP_TCPIP_CORE_LOCKING */
sys_thread_new(TCPIP_THREAD_NAME, tcpip_thread, NULL, TCPIP_THREAD_STACKSIZE, TCPIP_THREAD_PRIO); sys_thread_new(TCPIP_THREAD_NAME, tcpip_thread, NULL, TCPIP_THREAD_STACKSIZE, TCPIP_THREAD_PRIO);

View File

@ -189,7 +189,7 @@ static struct mem *ram_end;
static struct mem *lfree; static struct mem *lfree;
/** concurrent access protection */ /** concurrent access protection */
static sys_sem_t mem_sem; static sys_mutex_t mem_mutex;
#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT #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 */ /* Protect the heap only by using a semaphore */
#define LWIP_MEM_FREE_DECL_PROTECT() #define LWIP_MEM_FREE_DECL_PROTECT()
#define LWIP_MEM_FREE_PROTECT() sys_arch_sem_wait(mem_sem, 0) #define LWIP_MEM_FREE_PROTECT() sys_mutex_lock(&mem_mutex)
#define LWIP_MEM_FREE_UNPROTECT() sys_sem_signal(mem_sem) #define LWIP_MEM_FREE_UNPROTECT() sys_mutex_unlock(&mem_mutex)
/* mem_malloc is protected using semaphore AND LWIP_MEM_ALLOC_PROTECT */ /* mem_malloc is protected using semaphore AND LWIP_MEM_ALLOC_PROTECT */
#define LWIP_MEM_ALLOC_DECL_PROTECT() #define LWIP_MEM_ALLOC_DECL_PROTECT()
#define LWIP_MEM_ALLOC_PROTECT() #define LWIP_MEM_ALLOC_PROTECT()
@ -287,7 +287,9 @@ mem_init(void)
ram_end->next = MEM_SIZE_ALIGNED; ram_end->next = MEM_SIZE_ALIGNED;
ram_end->prev = 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 */ /* initialize the lowest-free pointer to the start of the heap */
lfree = (struct mem *)ram; lfree = (struct mem *)ram;
@ -514,7 +516,7 @@ mem_malloc(mem_size_t size)
} }
/* protect the heap from concurrent access */ /* protect the heap from concurrent access */
sys_arch_sem_wait(mem_sem, 0); sys_mutex_lock(&mem_mutex);
LWIP_MEM_ALLOC_PROTECT(); LWIP_MEM_ALLOC_PROTECT();
#if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT #if LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT
/* run as long as a mem_free disturbed mem_malloc */ /* 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_ASSERT("mem_malloc: !lfree->used", ((lfree == ram_end) || (!lfree->used)));
} }
LWIP_MEM_ALLOC_UNPROTECT(); LWIP_MEM_ALLOC_UNPROTECT();
sys_sem_signal(mem_sem); sys_mutex_unlock(&mem_mutex);
LWIP_ASSERT("mem_malloc: allocated memory not above ram_end.", LWIP_ASSERT("mem_malloc: allocated memory not above ram_end.",
(mem_ptr_t)mem + SIZEOF_STRUCT_MEM + size <= (mem_ptr_t)ram_end); (mem_ptr_t)mem + SIZEOF_STRUCT_MEM + size <= (mem_ptr_t)ram_end);
LWIP_ASSERT("mem_malloc: allocated memory properly aligned.", 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)); LWIP_DEBUGF(MEM_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("mem_malloc: could not allocate %"S16_F" bytes\n", (s16_t)size));
MEM_STATS_INC(err); MEM_STATS_INC(err);
LWIP_MEM_ALLOC_UNPROTECT(); LWIP_MEM_ALLOC_UNPROTECT();
sys_sem_signal(mem_sem); sys_mutex_unlock(&mem_mutex);
return NULL; return NULL;
} }

View File

@ -54,9 +54,12 @@ void
sys_msleep(u32_t ms) sys_msleep(u32_t ms)
{ {
if (ms > 0) { if (ms > 0) {
sys_sem_t delaysem = sys_sem_new(0); sys_sem_t delaysem;
sys_arch_sem_wait(delaysem, ms); err_t err = sys_sem_new(&delaysem, 0);
sys_sem_free(delaysem); if (err == ERR_OK) {
sys_arch_sem_wait(&delaysem, ms);
sys_sem_free(&delaysem);
}
} }
} }

View File

@ -423,7 +423,7 @@ sys_restart_timeouts(void)
* @param msg the place to store the message * @param msg the place to store the message
*/ */
void 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; u32_t time_needed;
struct sys_timeo *tmptimeout; struct sys_timeo *tmptimeout;

View File

@ -80,26 +80,74 @@ typedef void (*lwip_thread_fn)(void *arg);
/* Function prototypes for functions to be implemented by platform ports /* Function prototypes for functions to be implemented by platform ports
(in sys_arch.c) */ (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: */ /* Semaphore functions: */
/** Create a new semaphore /** Create a new semaphore
* @param sem pointer to the semaphore to create
* @param count initial count of the semaphore * @param count initial count of the semaphore
* @return a new semaphore */ * @return ERR_OK if successful, another err_t otherwise */
sys_sem_t sys_sem_new(u8_t count); err_t sys_sem_new(sys_sem_t *sem, u8_t count);
/** Signals a semaphore /** Signals a semaphore
* @param sem the semaphore to signal */ * @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 /** Wait for a semaphore for the specified timeout
* @param sem the semaphore to wait for * @param sem the semaphore to wait for
* @param timeout timeout in miliseconds to wait (0 = wait forever) * @param timeout timeout in miliseconds to wait (0 = wait forever)
* @return time (in miliseconds) waited for the semaphore * @return time (in miliseconds) waited for the semaphore
* or SYS_ARCH_TIMEOUT on timeout */ * 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 /** Delete a semaphore
* @param sem semaphore to delete */ * @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 */ /** Wait for a semaphore - forever/no timeout */
#define sys_sem_wait(sem) sys_arch_sem_wait(sem, 0) #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. */ /* Time functions. */
#ifndef sys_msleep #ifndef sys_msleep
@ -109,18 +157,19 @@ void sys_msleep(u32_t ms); /* only has a (close to) 1 jiffy resolution. */
/* Mailbox functions. */ /* Mailbox functions. */
/** Create a new mbox of specified size /** Create a new mbox of specified size
* @param mbox pointer to the mbox to create
* @param size (miminum) number of messages in this mbox * @param size (miminum) number of messages in this mbox
* @return a new mbox */ * @return ERR_OK if successful, another err_t otherwise */
sys_mbox_t sys_mbox_new(int size); err_t sys_mbox_new(sys_mbox_t *mbox, int size);
/** Post a message to an mbox - may not fail /** Post a message to an mbox - may not fail
* -> blocks if full, only used from tasks not from ISR * -> blocks if full, only used from tasks not from ISR
* @param mbox mbox to posts the message * @param mbox mbox to posts the message
* @param msg message to post (ATTENTION: can be NULL) */ * @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 /** Try to post a message to an mbox - may fail if full or ISR
* @param mbox mbox to posts the message * @param mbox mbox to posts the message
* @param msg message to post (ATTENTION: can be NULL) */ * @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 /** Wait for a new message to arrive in the mbox
* @param mbox mbox to get a message from * @param mbox mbox to get a message from
* @param msg pointer where the message is stored * @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 * @return time (in miliseconds) waited for a message, may be 0 if not waited
or SYS_ARCH_TIMEOUT on timeout or SYS_ARCH_TIMEOUT on timeout
* The returned time has to be accurate to prevent timer jitter! */ * 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() */ /* Allow port to override with a macro, e.g. special timout for sys_arch_mbox_fetch() */
#ifndef sys_arch_mbox_tryfetch #ifndef sys_arch_mbox_tryfetch
/** Wait for a new message to arrive in the mbox /** 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 * @param timeout maximum time (in miliseconds) to wait for a message
* @return 0 (miliseconds) if a message has been received * @return 0 (miliseconds) if a message has been received
* or SYS_MBOX_EMPTY if the mailbox is empty */ * 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 #endif
/** For now, we map straight to sys_arch implementation. */ /** For now, we map straight to sys_arch implementation. */
#define sys_mbox_tryfetch(mbox, msg) sys_arch_mbox_tryfetch(mbox, msg) #define sys_mbox_tryfetch(mbox, msg) sys_arch_mbox_tryfetch(mbox, msg)
/** Delete an mbox /** Delete an mbox
* @param mbox mbox to delete */ * @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) #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: /** The only thread function:
* Creates a new thread * Creates a new thread

View File

@ -50,9 +50,9 @@ extern "C" {
#if LWIP_TCPIP_CORE_LOCKING #if LWIP_TCPIP_CORE_LOCKING
/** The global semaphore to lock the stack. */ /** The global semaphore to lock the stack. */
extern sys_sem_t lock_tcpip_core; extern sys_mutex_t lock_tcpip_core;
#define LOCK_TCPIP_CORE() sys_sem_wait(lock_tcpip_core) #define LOCK_TCPIP_CORE() sys_mutex_lock(&lock_tcpip_core)
#define UNLOCK_TCPIP_CORE() sys_sem_signal(lock_tcpip_core) #define UNLOCK_TCPIP_CORE() sys_mutex_unlock(&lock_tcpip_core)
#define TCPIP_APIMSG(m) tcpip_apimsg_lock(m) #define TCPIP_APIMSG(m) tcpip_apimsg_lock(m)
#define TCPIP_APIMSG_ACK(m) #define TCPIP_APIMSG_ACK(m)
#define TCPIP_NETIFAPI(m) tcpip_netifapi_lock(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 LOCK_TCPIP_CORE()
#define UNLOCK_TCPIP_CORE() #define UNLOCK_TCPIP_CORE()
#define TCPIP_APIMSG(m) tcpip_apimsg(m) #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(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 */ #endif /* LWIP_TCPIP_CORE_LOCKING */
/** Function prototype for the init_done function passed to tcpip_init */ /** Function prototype for the init_done function passed to tcpip_init */

View File

@ -81,7 +81,7 @@ void sys_untimeout(sys_timeout_handler h, void *arg);
void sys_check_timeouts(void); void sys_check_timeouts(void);
void sys_restart_timeouts(void); void sys_restart_timeouts(void);
#else /* NO_SYS */ #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 */ #endif /* NO_SYS */