sockets: adapt poll to LWIP_MPU_COMPATIBLE; make LWIP_SOCKET_POLL and LWIP_SOCKET_SELECT independent options

This commit is contained in:
goldsimon 2017-09-21 22:18:55 +02:00
parent 1152fd02c0
commit 68d75a58df
3 changed files with 45 additions and 41 deletions

View File

@ -262,7 +262,7 @@ static void lwip_socket_drop_registered_mld6_memberships(int s);
/** The global array of available sockets */ /** The global array of available sockets */
static struct lwip_sock sockets[NUM_SOCKETS]; static struct lwip_sock sockets[NUM_SOCKETS];
#if LWIP_SOCKET_SELECT #if LWIP_SOCKET_SELECT || LWIP_SOCKET_POLL
#if LWIP_TCPIP_CORE_LOCKING #if LWIP_TCPIP_CORE_LOCKING
/* protect the select_cb_list using core lock */ /* protect the select_cb_list using core lock */
#define LWIP_SOCKET_SELECT_DECL_PROTECT(lev) #define LWIP_SOCKET_SELECT_DECL_PROTECT(lev)
@ -279,7 +279,7 @@ static volatile int select_cb_ctr;
#endif /* LWIP_TCPIP_CORE_LOCKING */ #endif /* LWIP_TCPIP_CORE_LOCKING */
/** The global list of tasks waiting for select */ /** The global list of tasks waiting for select */
static struct lwip_select_cb *select_cb_list; static struct lwip_select_cb *select_cb_list;
#endif /* LWIP_SOCKET_SELECT */ #endif /* LWIP_SOCKET_SELECT || LWIP_SOCKET_POLL */
#define sock_set_errno(sk, e) do { \ #define sock_set_errno(sk, e) do { \
const int sockerr = (e); \ const int sockerr = (e); \
@ -287,7 +287,7 @@ static struct lwip_select_cb *select_cb_list;
} while (0) } while (0)
/* Forward declaration of some functions */ /* Forward declaration of some functions */
#if LWIP_SOCKET_SELECT #if LWIP_SOCKET_SELECT || LWIP_SOCKET_POLL
static void event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len); static void event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len);
#define DEFAULT_SOCKET_EVENTCB event_callback #define DEFAULT_SOCKET_EVENTCB event_callback
static void select_check_waiters(int s, int has_recvevent, int has_sendevent, int has_errevent, struct lwip_sock *sock); static void select_check_waiters(int s, int has_recvevent, int has_sendevent, int has_errevent, struct lwip_sock *sock);
@ -1692,7 +1692,7 @@ lwip_writev(int s, const struct iovec *iov, int iovcnt)
return lwip_sendmsg(s, &msg, 0); return lwip_sendmsg(s, &msg, 0);
} }
#if LWIP_SOCKET_SELECT #if LWIP_SOCKET_SELECT || LWIP_SOCKET_POLL
/* Add select_cb to select_cb_list. */ /* Add select_cb to select_cb_list. */
static void static void
lwip_link_select_cb(struct lwip_select_cb *select_cb) lwip_link_select_cb(struct lwip_select_cb *select_cb)
@ -1741,8 +1741,9 @@ lwip_unlink_select_cb(struct lwip_select_cb *select_cb)
#endif #endif
LWIP_SOCKET_SELECT_UNPROTECT(lev); LWIP_SOCKET_SELECT_UNPROTECT(lev);
} }
#endif /* LWIP_SOCKET_SELECT || LWIP_SOCKET_POLL */
#if LWIP_SOCKET_SELECT
/** /**
* Go through the readset and writeset lists and see which socket of the sockets * Go through the readset and writeset lists and see which socket of the sockets
* set in the sets has events. On return, readset, writeset and exceptset have * set in the sets has events. On return, readset, writeset and exceptset have
@ -1941,18 +1942,12 @@ lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
to use local variables (unless we're running in MPU compatible to use local variables (unless we're running in MPU compatible
mode). */ mode). */
API_SELECT_CB_VAR_DECLARE(select_cb); API_SELECT_CB_VAR_DECLARE(select_cb);
API_SELECT_CB_VAR_ALLOC(select_cb, set_errno(ENOMEM); return -1); API_SELECT_CB_VAR_ALLOC(select_cb, set_errno(ENOMEM); lwip_select_dec_sockets_used(maxfdp1, &used_sockets); return -1);
memset(&API_SELECT_CB_VAR_REF(select_cb), 0, sizeof(struct lwip_select_cb));
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).readset = readset; API_SELECT_CB_VAR_REF(select_cb).readset = readset;
API_SELECT_CB_VAR_REF(select_cb).writeset = writeset; API_SELECT_CB_VAR_REF(select_cb).writeset = writeset;
API_SELECT_CB_VAR_REF(select_cb).exceptset = exceptset; API_SELECT_CB_VAR_REF(select_cb).exceptset = exceptset;
#if LWIP_SOCKET_POLL
API_SELECT_CB_VAR_REF(select_cb).poll_fds = NULL;
API_SELECT_CB_VAR_REF(select_cb).poll_nfds = 0;
#endif
API_SELECT_CB_VAR_REF(select_cb).sem_signalled = 0;
#if LWIP_NETCONN_SEM_PER_THREAD #if LWIP_NETCONN_SEM_PER_THREAD
API_SELECT_CB_VAR_REF(select_cb).sem = LWIP_NETCONN_THREAD_SEM_GET(); API_SELECT_CB_VAR_REF(select_cb).sem = LWIP_NETCONN_THREAD_SEM_GET();
#else /* LWIP_NETCONN_SEM_PER_THREAD */ #else /* LWIP_NETCONN_SEM_PER_THREAD */
@ -2095,9 +2090,9 @@ lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,
} }
return nready; return nready;
} }
#endif /* LWIP_SOCKET_SELECT */
#if LWIP_SOCKET_POLL #if LWIP_SOCKET_POLL
/** Options for the lwip_pollscan function. */ /** Options for the lwip_pollscan function. */
enum lwip_pollscan_opts enum lwip_pollscan_opts
{ {
@ -2260,7 +2255,6 @@ lwip_poll(struct pollfd *fds, nfds_t nfds, int timeout)
u32_t waitres = 0; u32_t waitres = 0;
int nready; int nready;
u32_t msectimeout; u32_t msectimeout;
struct lwip_select_cb select_cb;
#if LWIP_NETCONN_SEM_PER_THREAD #if LWIP_NETCONN_SEM_PER_THREAD
int waited = 0; int waited = 0;
#endif #endif
@ -2281,36 +2275,35 @@ lwip_poll(struct pollfd *fds, nfds_t nfds, int timeout)
/* 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) {
API_SELECT_CB_VAR_DECLARE(select_cb);
if (timeout == 0) { if (timeout == 0) {
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_poll: no timeout, returning 0\n")); LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_poll: no timeout, returning 0\n"));
goto return_success; goto return_success;
} }
API_SELECT_CB_VAR_ALLOC(select_cb, set_errno(EAGAIN); lwip_poll_dec_sockets_used(fds, nfds); return -1);
memset(&API_SELECT_CB_VAR_REF(select_cb), 0, sizeof(struct lwip_select_cb));
/* 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. */
select_cb.next = NULL; API_SELECT_CB_VAR_REF(select_cb).poll_fds = fds;
select_cb.prev = NULL; API_SELECT_CB_VAR_REF(select_cb).poll_nfds = nfds;
select_cb.readset = NULL;
select_cb.writeset = NULL;
select_cb.exceptset = NULL;
select_cb.poll_fds = fds;
select_cb.poll_nfds = nfds;
select_cb.sem_signalled = 0;
#if LWIP_NETCONN_SEM_PER_THREAD #if LWIP_NETCONN_SEM_PER_THREAD
select_cb.sem = LWIP_NETCONN_THREAD_SEM_GET(); API_SELECT_CB_VAR_REF(select_cb).sem = LWIP_NETCONN_THREAD_SEM_GET();
#else /* LWIP_NETCONN_SEM_PER_THREAD */ #else /* LWIP_NETCONN_SEM_PER_THREAD */
if (sys_sem_new(&select_cb.sem, 0) != ERR_OK) { if (sys_sem_new(&API_SELECT_CB_VAR_REF(select_cb).sem, 0) != ERR_OK) {
/* failed to create semaphore */ /* failed to create semaphore */
set_errno(ENOMEM); set_errno(EAGAIN);
lwip_poll_dec_sockets_used(fds, nfds); lwip_poll_dec_sockets_used(fds, nfds);
API_SELECT_CB_VAR_FREE(select_cb);
return -1; return -1;
} }
#endif /* LWIP_NETCONN_SEM_PER_THREAD */ #endif /* LWIP_NETCONN_SEM_PER_THREAD */
lwip_link_select_cb(&select_cb); lwip_link_select_cb(&API_SELECT_CB_VAR_REF(select_cb));
/* Increase select_waiting for each socket we are interested in. /* Increase select_waiting for each socket we are interested in.
Also, check for events again: there could have been events between Also, check for events again: there could have been events between
@ -2327,7 +2320,7 @@ lwip_poll(struct pollfd *fds, nfds_t nfds, int timeout)
LWIP_ASSERT("timeout > 0", timeout > 0); LWIP_ASSERT("timeout > 0", timeout > 0);
msectimeout = timeout; msectimeout = timeout;
} }
waitres = sys_arch_sem_wait(SELECT_SEM_PTR(select_cb.sem), msectimeout); waitres = sys_arch_sem_wait(SELECT_SEM_PTR(API_SELECT_CB_VAR_REF(select_cb).sem), msectimeout);
#if LWIP_NETCONN_SEM_PER_THREAD #if LWIP_NETCONN_SEM_PER_THREAD
waited = 1; waited = 1;
#endif #endif
@ -2337,16 +2330,17 @@ lwip_poll(struct pollfd *fds, nfds_t nfds, int timeout)
and check which events occurred while we waited. */ and check which events occurred while we waited. */
nready = lwip_pollscan(fds, nfds, LWIP_POLLSCAN_DEC_WAIT); nready = lwip_pollscan(fds, nfds, LWIP_POLLSCAN_DEC_WAIT);
lwip_unlink_select_cb(&select_cb); lwip_unlink_select_cb(&API_SELECT_CB_VAR_REF(select_cb));
#if LWIP_NETCONN_SEM_PER_THREAD #if LWIP_NETCONN_SEM_PER_THREAD
if (select_cb.sem_signalled && (!waited || (waitres == SYS_ARCH_TIMEOUT))) { if (select_cb.sem_signalled && (!waited || (waitres == SYS_ARCH_TIMEOUT))) {
/* don't leave the thread-local semaphore signalled */ /* don't leave the thread-local semaphore signalled */
sys_arch_sem_wait(select_cb.sem, 1); sys_arch_sem_wait(API_SELECT_CB_VAR_REF(select_cb).sem, 1);
} }
#else /* LWIP_NETCONN_SEM_PER_THREAD */ #else /* LWIP_NETCONN_SEM_PER_THREAD */
sys_sem_free(&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 */
@ -2396,9 +2390,9 @@ lwip_poll_should_wake(const struct lwip_select_cb *scb, int fd, struct lwip_sock
} }
return 0; return 0;
} }
#endif /* LWIP_SOCKET_POLL */ #endif /* LWIP_SOCKET_POLL */
#if LWIP_SOCKET_SELECT || LWIP_SOCKET_POLL
/** /**
* Callback registered in the netconn layer for each socket-netconn. * Callback registered in the netconn layer for each socket-netconn.
* Processes recvevent (data available) and wakes up tasks waiting for select. * Processes recvevent (data available) and wakes up tasks waiting for select.
@ -2528,9 +2522,16 @@ again:
int do_signal = 0; int do_signal = 0;
#if LWIP_SOCKET_POLL #if LWIP_SOCKET_POLL
if (scb->poll_fds != NULL) { if (scb->poll_fds != NULL) {
LWIP_UNUSED_ARG(has_recvevent);
LWIP_UNUSED_ARG(has_sendevent);
LWIP_UNUSED_ARG(has_errevent);
do_signal = lwip_poll_should_wake(scb, s, sock); do_signal = lwip_poll_should_wake(scb, s, sock);
} else }
#endif /* LWIP_SOCKET_POLL */ #endif /* LWIP_SOCKET_POLL */
#if LWIP_SOCKET_SELECT && LWIP_SOCKET_POLL
else
#endif /* LWIP_SOCKET_SELECT && LWIP_SOCKET_POLL */
#if LWIP_SOCKET_SELECT
{ {
LWIP_UNUSED_ARG(sock); LWIP_UNUSED_ARG(sock);
/* Test this select call for our socket */ /* Test this select call for our socket */
@ -2550,6 +2551,7 @@ again:
} }
} }
} }
#endif /* LWIP_SOCKET_SELECT */
if (do_signal) { if (do_signal) {
scb->sem_signalled = 1; scb->sem_signalled = 1;
/* For !LWIP_TCPIP_CORE_LOCKING, we don't call SYS_ARCH_UNPROTECT() before signaling /* For !LWIP_TCPIP_CORE_LOCKING, we don't call SYS_ARCH_UNPROTECT() before signaling
@ -2575,7 +2577,7 @@ again:
SYS_ARCH_UNPROTECT(lev); SYS_ARCH_UNPROTECT(lev);
#endif #endif
} }
#endif /* LWIP_SOCKET_SELECT */ #endif /* LWIP_SOCKET_SELECT || LWIP_SOCKET_POLL */
/** /**
* Close one end of a full-duplex connection. * Close one end of a full-duplex connection.

View File

@ -78,9 +78,9 @@ LWIP_MEMPOOL(DNS_API_MSG, MEMP_NUM_DNS_API_MSG, sizeof(struct dns_api_msg
#if LWIP_SOCKET && !LWIP_TCPIP_CORE_LOCKING #if LWIP_SOCKET && !LWIP_TCPIP_CORE_LOCKING
LWIP_MEMPOOL(SOCKET_SETGETSOCKOPT_DATA, MEMP_NUM_SOCKET_SETGETSOCKOPT_DATA, sizeof(struct lwip_setgetsockopt_data), "SOCKET_SETGETSOCKOPT_DATA") LWIP_MEMPOOL(SOCKET_SETGETSOCKOPT_DATA, MEMP_NUM_SOCKET_SETGETSOCKOPT_DATA, sizeof(struct lwip_setgetsockopt_data), "SOCKET_SETGETSOCKOPT_DATA")
#endif #endif
#if LWIP_SOCKET && LWIP_SOCKET_SELECT #if LWIP_SOCKET && (LWIP_SOCKET_SELECT || LWIP_SOCKET_POLL)
LWIP_MEMPOOL(SELECT_CB, MEMP_NUM_SELECT_CB, sizeof(struct lwip_select_cb), "SELECT_CB") LWIP_MEMPOOL(SELECT_CB, MEMP_NUM_SELECT_CB, sizeof(struct lwip_select_cb), "SELECT_CB")
#endif /* LWIP_SOCKET && LWIP_SOCKET_SELECT */ #endif /* LWIP_SOCKET && (LWIP_SOCKET_SELECT || LWIP_SOCKET_POLL) */
#if LWIP_NETIF_API #if LWIP_NETIF_API
LWIP_MEMPOOL(NETIFAPI_MSG, MEMP_NUM_NETIFAPI_MSG, sizeof(struct netifapi_msg), "NETIFAPI_MSG") LWIP_MEMPOOL(NETIFAPI_MSG, MEMP_NUM_NETIFAPI_MSG, sizeof(struct netifapi_msg), "NETIFAPI_MSG")
#endif #endif

View File

@ -69,7 +69,7 @@ struct lwip_sock {
struct netconn *conn; struct netconn *conn;
/** data that was left from the previous read */ /** data that was left from the previous read */
union lwip_sock_lastdata lastdata; union lwip_sock_lastdata lastdata;
#if LWIP_SOCKET_SELECT #if LWIP_SOCKET_SELECT || LWIP_SOCKET_POLL
/** number of times data was received, set by event_callback(), /** number of times data was received, set by event_callback(),
tested by the receive and select functions */ tested by the receive and select functions */
s16_t rcvevent; s16_t rcvevent;
@ -80,7 +80,7 @@ struct lwip_sock {
u16_t errevent; u16_t errevent;
/** counter of how many threads are waiting for this socket using select */ /** counter of how many threads are waiting for this socket using select */
SELWAIT_T select_waiting; SELWAIT_T select_waiting;
#endif /* LWIP_SOCKET_SELECT */ #endif /* LWIP_SOCKET_SELECT || LWIP_SOCKET_POLL */
#if LWIP_NETCONN_FULLDUPLEX #if LWIP_NETCONN_FULLDUPLEX
/* counter of how many threads are using a struct lwip_sock (not the 'int') */ /* counter of how many threads are using a struct lwip_sock (not the 'int') */
u8_t fd_used; u8_t fd_used;
@ -133,7 +133,7 @@ struct lwip_setgetsockopt_data {
struct lwip_sock* lwip_socket_dbg_get_socket(int fd); struct lwip_sock* lwip_socket_dbg_get_socket(int fd);
#if LWIP_SOCKET_SELECT #if LWIP_SOCKET_SELECT || LWIP_SOCKET_POLL
#if LWIP_NETCONN_SEM_PER_THREAD #if LWIP_NETCONN_SEM_PER_THREAD
#define SELECT_SEM_T sys_sem_t* #define SELECT_SEM_T sys_sem_t*
@ -149,24 +149,26 @@ struct lwip_select_cb {
struct lwip_select_cb *next; struct lwip_select_cb *next;
/** Pointer to the previous waiting task */ /** Pointer to the previous waiting task */
struct lwip_select_cb *prev; struct lwip_select_cb *prev;
#if LWIP_SOCKET_SELECT
/** readset passed to select */ /** readset passed to select */
fd_set *readset; fd_set *readset;
/** writeset passed to select */ /** writeset passed to select */
fd_set *writeset; fd_set *writeset;
/** unimplemented: exceptset passed to select */ /** unimplemented: exceptset passed to select */
fd_set *exceptset; fd_set *exceptset;
#endif /* LWIP_SOCKET_SELECT */
#if LWIP_SOCKET_POLL #if LWIP_SOCKET_POLL
/** fds passed to poll; NULL if select */ /** fds passed to poll; NULL if select */
struct pollfd *poll_fds; struct pollfd *poll_fds;
/** nfds passed to poll; 0 if select */ /** nfds passed to poll; 0 if select */
nfds_t poll_nfds; nfds_t poll_nfds;
#endif #endif /* LWIP_SOCKET_POLL */
/** don't signal the same semaphore twice: set to 1 when signalled */ /** don't signal the same semaphore twice: set to 1 when signalled */
int sem_signalled; int sem_signalled;
/** semaphore to wake up a task waiting for select */ /** semaphore to wake up a task waiting for select */
SELECT_SEM_T sem; SELECT_SEM_T sem;
}; };
#endif /* LWIP_SOCKET_SELECT */ #endif /* LWIP_SOCKET_SELECT || LWIP_SOCKET_POLL */
#endif /* LWIP_SOCKET */ #endif /* LWIP_SOCKET */