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 */
static struct lwip_sock sockets[NUM_SOCKETS];
#if LWIP_SOCKET_SELECT
#if LWIP_SOCKET_SELECT || LWIP_SOCKET_POLL
#if LWIP_TCPIP_CORE_LOCKING
/* protect the select_cb_list using core lock */
#define LWIP_SOCKET_SELECT_DECL_PROTECT(lev)
@ -279,7 +279,7 @@ static volatile int select_cb_ctr;
#endif /* LWIP_TCPIP_CORE_LOCKING */
/** The global list of tasks waiting for select */
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 { \
const int sockerr = (e); \
@ -287,7 +287,7 @@ static struct lwip_select_cb *select_cb_list;
} while (0)
/* 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);
#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);
@ -1692,7 +1692,7 @@ lwip_writev(int s, const struct iovec *iov, int iovcnt)
return lwip_sendmsg(s, &msg, 0);
}
#if LWIP_SOCKET_SELECT
#if LWIP_SOCKET_SELECT || LWIP_SOCKET_POLL
/* Add select_cb to select_cb_list. */
static void
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
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
* 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
mode). */
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).writeset = writeset;
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
API_SELECT_CB_VAR_REF(select_cb).sem = LWIP_NETCONN_THREAD_SEM_GET();
#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;
}
#endif /* LWIP_SOCKET_SELECT */
#if LWIP_SOCKET_POLL
/** Options for the lwip_pollscan function. */
enum lwip_pollscan_opts
{
@ -2260,7 +2255,6 @@ lwip_poll(struct pollfd *fds, nfds_t nfds, int timeout)
u32_t waitres = 0;
int nready;
u32_t msectimeout;
struct lwip_select_cb select_cb;
#if LWIP_NETCONN_SEM_PER_THREAD
int waited = 0;
#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 (!nready) {
API_SELECT_CB_VAR_DECLARE(select_cb);
if (timeout == 0) {
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_poll: no timeout, returning 0\n"));
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:
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
to use local variables. */
select_cb.next = NULL;
select_cb.prev = NULL;
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;
API_SELECT_CB_VAR_REF(select_cb).poll_fds = fds;
API_SELECT_CB_VAR_REF(select_cb).poll_nfds = nfds;
#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 */
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 */
set_errno(ENOMEM);
set_errno(EAGAIN);
lwip_poll_dec_sockets_used(fds, nfds);
API_SELECT_CB_VAR_FREE(select_cb);
return -1;
}
#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.
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);
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
waited = 1;
#endif
@ -2337,16 +2330,17 @@ lwip_poll(struct pollfd *fds, nfds_t nfds, int timeout)
and check which events occurred while we waited. */
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 (select_cb.sem_signalled && (!waited || (waitres == SYS_ARCH_TIMEOUT))) {
/* 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 */
sys_sem_free(&select_cb.sem);
sys_sem_free(&API_SELECT_CB_VAR_REF(select_cb).sem);
#endif /* LWIP_NETCONN_SEM_PER_THREAD */
API_SELECT_CB_VAR_FREE(select_cb);
if (nready < 0) {
/* 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;
}
#endif /* LWIP_SOCKET_POLL */
#if LWIP_SOCKET_SELECT || LWIP_SOCKET_POLL
/**
* Callback registered in the netconn layer for each socket-netconn.
* Processes recvevent (data available) and wakes up tasks waiting for select.
@ -2528,9 +2522,16 @@ again:
int do_signal = 0;
#if LWIP_SOCKET_POLL
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);
} else
}
#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);
/* Test this select call for our socket */
@ -2550,6 +2551,7 @@ again:
}
}
}
#endif /* LWIP_SOCKET_SELECT */
if (do_signal) {
scb->sem_signalled = 1;
/* For !LWIP_TCPIP_CORE_LOCKING, we don't call SYS_ARCH_UNPROTECT() before signaling
@ -2575,7 +2577,7 @@ again:
SYS_ARCH_UNPROTECT(lev);
#endif
}
#endif /* LWIP_SOCKET_SELECT */
#endif /* LWIP_SOCKET_SELECT || LWIP_SOCKET_POLL */
/**
* 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
LWIP_MEMPOOL(SOCKET_SETGETSOCKOPT_DATA, MEMP_NUM_SOCKET_SETGETSOCKOPT_DATA, sizeof(struct lwip_setgetsockopt_data), "SOCKET_SETGETSOCKOPT_DATA")
#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")
#endif /* LWIP_SOCKET && LWIP_SOCKET_SELECT */
#endif /* LWIP_SOCKET && (LWIP_SOCKET_SELECT || LWIP_SOCKET_POLL) */
#if LWIP_NETIF_API
LWIP_MEMPOOL(NETIFAPI_MSG, MEMP_NUM_NETIFAPI_MSG, sizeof(struct netifapi_msg), "NETIFAPI_MSG")
#endif

View File

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