|
|
|
|
@ -338,19 +338,26 @@ sock_inc_used(struct lwip_sock *sock)
|
|
|
|
|
SYS_ARCH_UNPROTECT(lev); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* Like sock_inc_used(), but called under SYS_ARCH_PROTECT lock. */ |
|
|
|
|
static void |
|
|
|
|
sock_inc_used_locked(struct lwip_sock *sock) |
|
|
|
|
{ |
|
|
|
|
LWIP_ASSERT("sock != NULL", sock != NULL); |
|
|
|
|
|
|
|
|
|
++sock->fd_used; |
|
|
|
|
LWIP_ASSERT("sock->fd_used != 0", sock->fd_used != 0); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* In full-duplex mode,sock->fd_used != 0 prevents a socket descriptor from being
|
|
|
|
|
* released (and possibly reused) when used from more than one thread |
|
|
|
|
* (e.g. read-while-write or close-while-write, etc) |
|
|
|
|
* This function is called at the end of functions using (try)get_socket*(). |
|
|
|
|
*/ |
|
|
|
|
static void |
|
|
|
|
done_socket(struct lwip_sock *sock) |
|
|
|
|
done_socket_locked(struct lwip_sock *sock) |
|
|
|
|
{ |
|
|
|
|
SYS_ARCH_DECL_PROTECT(lev); |
|
|
|
|
|
|
|
|
|
LWIP_ASSERT("sock != NULL", sock != NULL); |
|
|
|
|
|
|
|
|
|
SYS_ARCH_PROTECT(lev); |
|
|
|
|
LWIP_ASSERT("sock->fd_used > 0", sock->fd_used > 0); |
|
|
|
|
if (--sock->fd_used == 0) { |
|
|
|
|
if (sock->fd_free_pending) { |
|
|
|
|
@ -359,11 +366,21 @@ done_socket(struct lwip_sock *sock)
|
|
|
|
|
free_socket(sock, sock->fd_free_pending & LWIP_SOCK_FD_FREE_TCP); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void |
|
|
|
|
done_socket(struct lwip_sock *sock) |
|
|
|
|
{ |
|
|
|
|
SYS_ARCH_DECL_PROTECT(lev); |
|
|
|
|
SYS_ARCH_PROTECT(lev); |
|
|
|
|
done_socket_locked(sock); |
|
|
|
|
SYS_ARCH_UNPROTECT(lev); |
|
|
|
|
} |
|
|
|
|
#else /* LWIP_NETCONN_FULLDUPLEX */ |
|
|
|
|
#define sock_inc_used(sock) |
|
|
|
|
#define sock_inc_used_locked(sock) |
|
|
|
|
#define done_socket(sock) |
|
|
|
|
#define done_socket_locked(sock) |
|
|
|
|
#endif /* LWIP_NETCONN_FULLDUPLEX */ |
|
|
|
|
|
|
|
|
|
/* Translate a socket 'int' into a pointer (only fails if the index is invalid) */ |
|
|
|
|
@ -395,6 +412,17 @@ tryget_socket_unconn(int fd)
|
|
|
|
|
return ret; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* Like tryget_socket_unconn(), but called under SYS_ARCH_PROTECT lock. */ |
|
|
|
|
static struct lwip_sock * |
|
|
|
|
tryget_socket_unconn_locked(int fd) |
|
|
|
|
{ |
|
|
|
|
struct lwip_sock *ret = tryget_socket_unconn_nouse(fd); |
|
|
|
|
if (ret != NULL) { |
|
|
|
|
sock_inc_used_locked(ret); |
|
|
|
|
} |
|
|
|
|
return ret; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Same as get_socket but doesn't set errno |
|
|
|
|
* |
|
|
|
|
@ -1774,7 +1802,7 @@ lwip_selscan(int maxfdp1, fd_set *readset_in, fd_set *writeset_in, fd_set *excep
|
|
|
|
|
} |
|
|
|
|
/* First get the socket's status (protected)... */ |
|
|
|
|
SYS_ARCH_PROTECT(lev); |
|
|
|
|
sock = tryget_socket_unconn(i); |
|
|
|
|
sock = tryget_socket_unconn_locked(i); |
|
|
|
|
if (sock != NULL) { |
|
|
|
|
void *lastdata = sock->lastdata.pbuf; |
|
|
|
|
s16_t rcvevent = sock->rcvevent; |
|
|
|
|
@ -1833,7 +1861,7 @@ lwip_select_inc_sockets_used_set(int maxfdp, fd_set *fdset, fd_set *used_sockets
|
|
|
|
|
if (FD_ISSET(i, fdset) && !FD_ISSET(i, used_sockets)) { |
|
|
|
|
struct lwip_sock *sock; |
|
|
|
|
SYS_ARCH_PROTECT(lev); |
|
|
|
|
sock = tryget_socket_unconn(i); |
|
|
|
|
sock = tryget_socket_unconn_locked(i); |
|
|
|
|
if (sock != NULL) { |
|
|
|
|
/* leave the socket used until released by lwip_select_dec_sockets_used */ |
|
|
|
|
FD_SET(i, used_sockets); |
|
|
|
|
@ -1962,20 +1990,20 @@ lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
|
|
|
|
|
(exceptset && FD_ISSET(i, exceptset))) { |
|
|
|
|
struct lwip_sock *sock; |
|
|
|
|
SYS_ARCH_PROTECT(lev); |
|
|
|
|
sock = tryget_socket_unconn(i); |
|
|
|
|
sock = tryget_socket_unconn_locked(i); |
|
|
|
|
if (sock != NULL) { |
|
|
|
|
sock->select_waiting++; |
|
|
|
|
if (sock->select_waiting == 0) { |
|
|
|
|
/* overflow - too many threads waiting */ |
|
|
|
|
sock->select_waiting--; |
|
|
|
|
done_socket(sock); |
|
|
|
|
done_socket_locked(sock); |
|
|
|
|
nready = -1; |
|
|
|
|
maxfdp2 = i; |
|
|
|
|
SYS_ARCH_UNPROTECT(lev); |
|
|
|
|
set_errno(EBUSY); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
done_socket(sock); |
|
|
|
|
done_socket_locked(sock); |
|
|
|
|
} else { |
|
|
|
|
/* Not a valid socket */ |
|
|
|
|
nready = -1; |
|
|
|
|
@ -2021,14 +2049,14 @@ lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
|
|
|
|
|
(exceptset && FD_ISSET(i, exceptset))) { |
|
|
|
|
struct lwip_sock *sock; |
|
|
|
|
SYS_ARCH_PROTECT(lev); |
|
|
|
|
sock = tryget_socket_unconn(i); |
|
|
|
|
sock = tryget_socket_unconn_locked(i); |
|
|
|
|
if (sock != NULL) { |
|
|
|
|
/* for now, handle select_waiting==0... */ |
|
|
|
|
LWIP_ASSERT("sock->select_waiting > 0", sock->select_waiting > 0); |
|
|
|
|
if (sock->select_waiting > 0) { |
|
|
|
|
sock->select_waiting--; |
|
|
|
|
} |
|
|
|
|
done_socket(sock); |
|
|
|
|
done_socket_locked(sock); |
|
|
|
|
} else { |
|
|
|
|
/* Not a valid socket */ |
|
|
|
|
nready = -1; |
|
|
|
|
@ -2128,7 +2156,7 @@ lwip_pollscan(struct pollfd *fds, nfds_t nfds, enum lwip_pollscan_opts opts)
|
|
|
|
|
if (fds[fdi].fd >= 0 && (fds[fdi].revents & POLLNVAL) == 0) { |
|
|
|
|
/* First get the socket's status (protected)... */ |
|
|
|
|
SYS_ARCH_PROTECT(lev); |
|
|
|
|
sock = tryget_socket_unconn(fds[fdi].fd); |
|
|
|
|
sock = tryget_socket_unconn_locked(fds[fdi].fd); |
|
|
|
|
if (sock != NULL) { |
|
|
|
|
void* lastdata = sock->lastdata.pbuf; |
|
|
|
|
s16_t rcvevent = sock->rcvevent; |
|
|
|
|
@ -2140,19 +2168,19 @@ lwip_pollscan(struct pollfd *fds, nfds_t nfds, enum lwip_pollscan_opts opts)
|
|
|
|
|
if (sock->select_waiting == 0) { |
|
|
|
|
/* overflow - too many threads waiting */ |
|
|
|
|
sock->select_waiting--; |
|
|
|
|
done_socket(sock); |
|
|
|
|
done_socket_locked(sock); |
|
|
|
|
nready = -1; |
|
|
|
|
SYS_ARCH_UNPROTECT(lev); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
done_socket(sock); |
|
|
|
|
done_socket_locked(sock); |
|
|
|
|
} else if ((opts & LWIP_POLLSCAN_DEC_WAIT) != 0) { |
|
|
|
|
/* for now, handle select_waiting==0... */ |
|
|
|
|
LWIP_ASSERT("sock->select_waiting > 0", sock->select_waiting > 0); |
|
|
|
|
if (sock->select_waiting > 0) { |
|
|
|
|
sock->select_waiting--; |
|
|
|
|
} |
|
|
|
|
done_socket(sock); |
|
|
|
|
done_socket_locked(sock); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
SYS_ARCH_UNPROTECT(lev); |
|
|
|
|
@ -2204,15 +2232,12 @@ static void
|
|
|
|
|
lwip_poll_inc_sockets_used(struct pollfd *fds, nfds_t nfds) |
|
|
|
|
{ |
|
|
|
|
nfds_t fdi; |
|
|
|
|
SYS_ARCH_DECL_PROTECT(lev); |
|
|
|
|
|
|
|
|
|
if(fds) { |
|
|
|
|
/* Go through each struct pollfd in the array. */ |
|
|
|
|
for (fdi = 0; fdi < nfds; fdi++) { |
|
|
|
|
SYS_ARCH_PROTECT(lev); |
|
|
|
|
/* Increase the reference counter */ |
|
|
|
|
tryget_socket_unconn(fds[fdi].fd); |
|
|
|
|
SYS_ARCH_UNPROTECT(lev); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|