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:
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)

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;
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);

View File

@ -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

View File

@ -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 */

View File

@ -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);

View File

@ -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;
}

View File

@ -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);
}
}
}

View File

@ -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;

View File

@ -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

View File

@ -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 */

View File

@ -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 */