sys.h, api_lib.c, api_msg.c, sockets.c: fix bug #21698: "netconn->recv_avail is not protected" by using new macros for interlocked access to modify/test netconn->recv_avail.

This commit is contained in:
goldsimon 2007-12-21 14:59:10 +00:00
parent 1cb470662b
commit 48e62e25e9
5 changed files with 64 additions and 9 deletions

View File

@ -526,8 +526,13 @@ HISTORY
++ Bug fixes: ++ Bug fixes:
2007-12-21 Simon Goldschmidt
* sys.h, api_lib.c, api_msg.c, sockets.c: fix bug #21698: "netconn->recv_avail
is not protected" by using new macros for interlocked access to modify/test
netconn->recv_avail.
2007-12-20 Kieran Mansley (based on patch from Oleg Tyshev) 2007-12-20 Kieran Mansley (based on patch from Oleg Tyshev)
* tcp_in.c: fix bug# 21535 (nrtx not reset correctly in SYN_SENT stat)e * tcp_in.c: fix bug# 21535 (nrtx not reset correctly in SYN_SENT state)
2007-12-20 Kieran Mansley (based on patch from Per-Henrik Lundbolm) 2007-12-20 Kieran Mansley (based on patch from Per-Henrik Lundbolm)
* tcp.c, tcp_in.c, tcp_out.c, tcp.h: fix bug #20199 (better handling * tcp.c, tcp_in.c, tcp_out.c, tcp.h: fix bug #20199 (better handling

View File

@ -358,7 +358,7 @@ netconn_recv(struct netconn *conn)
if (p != NULL) { if (p != NULL) {
len = p->tot_len; len = p->tot_len;
conn->recv_avail -= len; SYS_ARCH_DEC(conn->recv_avail, len);
} else { } else {
len = 0; len = 0;
} }
@ -401,7 +401,7 @@ netconn_recv(struct netconn *conn)
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*/
if (buf!=NULL) { if (buf!=NULL) {
conn->recv_avail -= buf->p->tot_len; SYS_ARCH_DEC(conn->recv_avail, buf->p->tot_len);
/* Register event with callback */ /* Register event with callback */
API_EVENT(conn, NETCONN_EVT_RCVMINUS, buf->p->tot_len); API_EVENT(conn, NETCONN_EVT_RCVMINUS, buf->p->tot_len);
} }

View File

@ -72,12 +72,16 @@ recv_raw(void *arg, struct raw_pcb *pcb, struct pbuf *p,
{ {
struct netbuf *buf; struct netbuf *buf;
struct netconn *conn; struct netconn *conn;
#if LWIP_SO_RCVBUF
int recv_avail;
#endif /* LWIP_SO_RCVBUF */
conn = arg; conn = arg;
#if LWIP_SO_RCVBUF #if LWIP_SO_RCVBUF
SYS_ARCH_GET(conn->recv_avail, recv_avail);
if ((conn != NULL) && (conn->recvmbox != SYS_MBOX_NULL) && if ((conn != NULL) && (conn->recvmbox != SYS_MBOX_NULL) &&
(((int)(conn->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)) {
#endif /* LWIP_SO_RCVBUF */ #endif /* LWIP_SO_RCVBUF */
@ -91,7 +95,7 @@ recv_raw(void *arg, struct raw_pcb *pcb, struct pbuf *p,
buf->addr = addr; buf->addr = addr;
buf->port = pcb->protocol; buf->port = pcb->protocol;
conn->recv_avail += p->tot_len; SYS_ARCH_INC(conn->recv_avail, p->tot_len);
/* Register event with callback */ /* Register event with callback */
API_EVENT(conn, NETCONN_EVT_RCVPLUS, p->tot_len); API_EVENT(conn, NETCONN_EVT_RCVPLUS, p->tot_len);
sys_mbox_post(conn->recvmbox, buf); sys_mbox_post(conn->recvmbox, buf);
@ -114,6 +118,9 @@ recv_udp(void *arg, struct udp_pcb *pcb, struct pbuf *p,
{ {
struct netbuf *buf; struct netbuf *buf;
struct netconn *conn; struct netconn *conn;
#if LWIP_SO_RCVBUF
int recv_avail;
#endif /* LWIP_SO_RCVBUF */
LWIP_UNUSED_ARG(pcb); /* only used for asserts... */ LWIP_UNUSED_ARG(pcb); /* only used for asserts... */
LWIP_ASSERT("recv_udp must have a pcb argument", pcb != NULL); LWIP_ASSERT("recv_udp must have a pcb argument", pcb != NULL);
@ -122,8 +129,9 @@ recv_udp(void *arg, struct udp_pcb *pcb, struct pbuf *p,
LWIP_ASSERT("recv_udp: recv for wrong pcb!", conn->pcb.udp == pcb); LWIP_ASSERT("recv_udp: recv for wrong pcb!", conn->pcb.udp == pcb);
#if LWIP_SO_RCVBUF #if LWIP_SO_RCVBUF
SYS_ARCH_GET(conn->recv_avail, recv_avail);
if ((conn == NULL) || (conn->recvmbox == SYS_MBOX_NULL) || if ((conn == NULL) || (conn->recvmbox == SYS_MBOX_NULL) ||
(((int)(conn->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)) {
#endif /* LWIP_SO_RCVBUF */ #endif /* LWIP_SO_RCVBUF */
@ -142,7 +150,7 @@ recv_udp(void *arg, struct udp_pcb *pcb, struct pbuf *p,
buf->port = port; buf->port = port;
} }
conn->recv_avail += p->tot_len; SYS_ARCH_INC(conn->recv_avail, p->tot_len);
/* Register event with callback */ /* Register event with callback */
API_EVENT(conn, NETCONN_EVT_RCVPLUS, p->tot_len); API_EVENT(conn, NETCONN_EVT_RCVPLUS, p->tot_len);
sys_mbox_post(conn->recvmbox, buf); sys_mbox_post(conn->recvmbox, buf);
@ -176,7 +184,7 @@ recv_tcp(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
conn->err = err; conn->err = err;
if (p != NULL) { if (p != NULL) {
len = p->tot_len; len = p->tot_len;
conn->recv_avail += len; SYS_ARCH_INC(conn->recv_avail, len);
} else { } else {
len = 0; len = 0;
} }

View File

@ -1872,7 +1872,7 @@ lwip_ioctl(int s, long cmd, void *argp)
return -1; return -1;
} }
*((u16_t*)argp) = sock->conn->recv_avail; SYS_ARCH_GET(sock->conn->recv_avail, *((u16_t*)argp));
/* 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 */
if (sock->lastdata) { if (sock->lastdata) {

View File

@ -193,6 +193,48 @@ void sys_arch_unprotect(sys_prot_t pval);
#endif /* SYS_ARCH_PROTECT */ #endif /* SYS_ARCH_PROTECT */
/*
* Macros to set/get and increase/decrease variables in a thread-safe way.
* Use these for accessing variable that are used from more than one thread.
*/
#ifndef SYS_ARCH_INC
#define SYS_ARCH_INC(var, val) do { \
SYS_ARCH_DECL_PROTECT(old_level); \
SYS_ARCH_PROTECT(old_level); \
var += val; \
SYS_ARCH_UNPROTECT(old_level); \
} while(0)
#endif /* SYS_ARCH_INC */
#ifndef SYS_ARCH_DEC
#define SYS_ARCH_DEC(var, val) do { \
SYS_ARCH_DECL_PROTECT(old_level); \
SYS_ARCH_PROTECT(old_level); \
var -= val; \
SYS_ARCH_UNPROTECT(old_level); \
} while(0)
#endif /* SYS_ARCH_DEC */
#ifndef SYS_ARCH_GET
#define SYS_ARCH_GET(var, ret) do { \
SYS_ARCH_DECL_PROTECT(old_level); \
SYS_ARCH_PROTECT(old_level); \
ret = var; \
SYS_ARCH_UNPROTECT(old_level); \
} while(0)
#endif /* SYS_ARCH_GET */
#ifndef SYS_ARCH_SET
#define SYS_ARCH_SET(var, val) do { \
SYS_ARCH_DECL_PROTECT(old_level); \
SYS_ARCH_PROTECT(old_level); \
var = val; \
SYS_ARCH_UNPROTECT(old_level); \
} while(0)
#endif /* SYS_ARCH_SET */
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif