Slightly rework the fix for bug #51990: allocate select_cb only if we actually need to wait

This commit is contained in:
goldsimon 2017-09-12 21:37:48 +02:00
parent 72a00ca79c
commit 92b6f83eb2

View File

@ -1844,7 +1844,6 @@ lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
int nready; int nready;
fd_set lreadset, lwriteset, lexceptset; fd_set lreadset, lwriteset, lexceptset;
u32_t msectimeout; u32_t msectimeout;
API_SELECT_CB_VAR_DECLARE(select_cb);
int i; int i;
int maxfdp2; int maxfdp2;
#if LWIP_NETCONN_SEM_PER_THREAD #if LWIP_NETCONN_SEM_PER_THREAD
@ -1856,8 +1855,6 @@ lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
SYS_ARCH_DECL_PROTECT(lev); SYS_ARCH_DECL_PROTECT(lev);
LWIP_SOCKET_SELECT_DECL_PROTECT(lev2); LWIP_SOCKET_SELECT_DECL_PROTECT(lev2);
API_SELECT_CB_VAR_ALLOC(select_cb, set_errno(ENOMEM); return -1);
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select(%d, %p, %p, %p, tvsec=%"S32_F" tvusec=%"S32_F")\n", LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select(%d, %p, %p, %p, tvsec=%"S32_F" tvusec=%"S32_F")\n",
maxfdp1, (void *)readset, (void *) writeset, (void *) exceptset, maxfdp1, (void *)readset, (void *) writeset, (void *) exceptset,
timeout ? (s32_t)timeout->tv_sec : (s32_t)-1, timeout ? (s32_t)timeout->tv_sec : (s32_t)-1,
@ -1865,7 +1862,6 @@ lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
if ((maxfdp1 < 0) || (maxfdp1 > (FD_SETSIZE + LWIP_SOCKET_OFFSET))) { if ((maxfdp1 < 0) || (maxfdp1 > (FD_SETSIZE + LWIP_SOCKET_OFFSET))) {
set_errno(EINVAL); set_errno(EINVAL);
API_SELECT_CB_VAR_FREE(select_cb);
return -1; return -1;
} }
@ -1876,25 +1872,27 @@ lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
nready = lwip_selscan(maxfdp1, readset, writeset, exceptset, &lreadset, &lwriteset, &lexceptset); nready = lwip_selscan(maxfdp1, readset, writeset, exceptset, &lreadset, &lwriteset, &lexceptset);
if (nready < 0) { if (nready < 0) {
/* one of the sockets in one of the fd_sets was invalid */
set_errno(EBADF); set_errno(EBADF);
lwip_select_dec_sockets_used(maxfdp1, &used_sockets); lwip_select_dec_sockets_used(maxfdp1, &used_sockets);
API_SELECT_CB_VAR_FREE(select_cb);
return -1; return -1;
} } else if (nready > 0) {
/* one or more sockets are set, no need to wait */
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: nready=%d\n", nready));
} else {
/* 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 (timeout && timeout->tv_sec == 0 && timeout->tv_usec == 0) { if (timeout && timeout->tv_sec == 0 && timeout->tv_usec == 0) {
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: no timeout, returning 0\n")); LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: no timeout, returning 0\n"));
/* This is OK as the local fdsets are empty and nready is zero, /* This is OK as the local fdsets are empty and nready is zero,
or we would have returned earlier. */ or we would have returned earlier. */
goto return_copy_fdsets; } else {
}
/* None ready: add our semaphore to list: /* None ready: add our semaphore to list:
We don't actually need any dynamic memory. Our entry on the We don't actually need any dynamic memory. Our entry on the
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 (unless we're running in MPU compatible
mode). */
API_SELECT_CB_VAR_DECLARE(select_cb);
API_SELECT_CB_VAR_ALLOC(select_cb, set_errno(ENOMEM); return -1);
API_SELECT_CB_VAR_REF(select_cb).next = NULL; API_SELECT_CB_VAR_REF(select_cb).next = NULL;
API_SELECT_CB_VAR_REF(select_cb).prev = NULL; API_SELECT_CB_VAR_REF(select_cb).prev = NULL;
@ -2040,6 +2038,7 @@ lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
#else /* LWIP_NETCONN_SEM_PER_THREAD */ #else /* LWIP_NETCONN_SEM_PER_THREAD */
sys_sem_free(&API_SELECT_CB_VAR_REF(select_cb).sem); sys_sem_free(&API_SELECT_CB_VAR_REF(select_cb).sem);
#endif /* LWIP_NETCONN_SEM_PER_THREAD */ #endif /* LWIP_NETCONN_SEM_PER_THREAD */
API_SELECT_CB_VAR_FREE(select_cb);
if (nready < 0) { if (nready < 0) {
/* This happens when a socket got closed while waiting */ /* This happens when a socket got closed while waiting */
@ -2053,15 +2052,14 @@ lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: timeout expired\n")); LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: timeout expired\n"));
/* This is OK as the local fdsets are empty and nready is zero, /* This is OK as the local fdsets are empty and nready is zero,
or we would have returned earlier. */ or we would have returned earlier. */
goto return_copy_fdsets; } else {
} /* See what's set now after waiting */
/* See what's set */
nready = lwip_selscan(maxfdp1, readset, writeset, exceptset, &lreadset, &lwriteset, &lexceptset); nready = lwip_selscan(maxfdp1, readset, writeset, exceptset, &lreadset, &lwriteset, &lexceptset);
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: nready=%d\n", nready));
}
}
} }
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_select: nready=%d\n", nready));
return_copy_fdsets:
lwip_select_dec_sockets_used(maxfdp1, &used_sockets); lwip_select_dec_sockets_used(maxfdp1, &used_sockets);
set_errno(0); set_errno(0);
if (readset) { if (readset) {
@ -2073,7 +2071,6 @@ return_copy_fdsets:
if (exceptset) { if (exceptset) {
*exceptset = lexceptset; *exceptset = lexceptset;
} }
API_SELECT_CB_VAR_FREE(select_cb);
return nready; return nready;
} }