net: sockets: Implement poll() operation.

poll() allows to (efficiently) wait for available data on sockets,
and is essential operation for working with non-blocking sockets.

This is initial, very basic implementation, effectively supporting
just POLLIN operation. (POLLOUT implementation is dummy - it's
assumed that socket is always writable, as there's currently no
reasonable way to test that.)

Signed-off-by: Paul Sokolovsky <paul.sokolovsky@linaro.org>
This commit is contained in:
Paul Sokolovsky 2017-07-18 11:57:51 +03:00 committed by Jukka Rissanen
commit 2c2e8b26b4
3 changed files with 98 additions and 0 deletions

View file

@ -15,6 +15,16 @@
extern "C" {
#endif
struct zsock_pollfd {
int fd;
short events;
short revents;
};
/* Values are compatible with Linux */
#define ZSOCK_POLLIN 1
#define ZSOCK_POLLOUT 4
int zsock_socket(int family, int type, int proto);
int zsock_close(int sock);
int zsock_bind(int sock, const struct sockaddr *addr, socklen_t addrlen);
@ -24,6 +34,7 @@ int zsock_accept(int sock, struct sockaddr *addr, socklen_t *addrlen);
ssize_t zsock_send(int sock, const void *buf, size_t len, int flags);
ssize_t zsock_recv(int sock, void *buf, size_t max_len, int flags);
int zsock_fcntl(int sock, int cmd, int flags);
int zsock_poll(struct zsock_pollfd *fds, int nfds, int timeout);
#if defined(CONFIG_NET_SOCKETS_POSIX_NAMES)
#define socket zsock_socket
@ -36,6 +47,11 @@ int zsock_fcntl(int sock, int cmd, int flags);
#define recv zsock_recv
#define fcntl zsock_fcntl
#define poll zsock_poll
#define pollfd zsock_pollfd
#define POLLIN ZSOCK_POLLIN
#define POLLOUT ZSOCK_POLLOUT
#define inet_ntop net_addr_ntop
#define inet_pton net_addr_pton
#endif

View file

@ -25,6 +25,13 @@ config NET_SOCKETS_POSIX_NAMES
attention, as in POSIX it closes any file descriptor, while with this
option enaled, it will still apply only to sockets.
config NET_SOCKETS_POLL_MAX
int
prompt "Max number of supported poll() entries"
default 3
help
Maximum number of entries supported for poll() call.
config NET_DEBUG_SOCKETS
bool "Debug BSD Sockets like API calls"
default n

View file

@ -13,6 +13,7 @@
#include <sys/fcntl.h>
/* Zephyr headers */
#include <kernel.h>
#include <net/net_context.h>
#include <net/net_pkt.h>
#include <net/socket.h>
@ -23,6 +24,8 @@
#define SET_ERRNO(x) \
{ int _err = x; if (_err < 0) { errno = -_err; return -1; } }
static struct k_poll_event poll_events[CONFIG_NET_SOCKETS_POLL_MAX];
static inline void sock_set_flag(struct net_context *ctx, u32_t mask,
u32_t flag)
{
@ -375,3 +378,75 @@ int zsock_fcntl(int sock, int cmd, int flags)
return -1;
}
}
int zsock_poll(struct zsock_pollfd *fds, int nfds, int timeout)
{
int i;
int ret = 0;
struct zsock_pollfd *pfd;
struct k_poll_event *pev;
struct k_poll_event *pev_end = poll_events + ARRAY_SIZE(poll_events);
if (timeout < 0) {
timeout = K_FOREVER;
}
pev = poll_events;
for (pfd = fds, i = nfds; i--; pfd++) {
/* Per POSIX, negative fd's are just ignored */
if (pfd->fd < 0) {
continue;
}
if (pfd->events & POLLIN) {
struct net_context *ctx = INT_TO_POINTER(pfd->fd);
if (pev == pev_end) {
errno = ENOMEM;
return -1;
}
pev->obj = &ctx->recv_q;
pev->type = K_POLL_TYPE_FIFO_DATA_AVAILABLE;
pev->mode = K_POLL_MODE_NOTIFY_ONLY;
pev->state = K_POLL_STATE_NOT_READY;
pev++;
}
}
ret = k_poll(poll_events, pev - poll_events, timeout);
if (ret != 0 && ret != -EAGAIN) {
errno = -ret;
return -1;
}
ret = 0;
pev = poll_events;
for (pfd = fds, i = nfds; i--; pfd++) {
pfd->revents = 0;
if (pfd->fd < 0) {
continue;
}
/* For now, assume that socket is always writable */
if (pfd->events & POLLOUT) {
pfd->revents |= POLLOUT;
}
if (pfd->events & POLLIN) {
if (pev->state != K_POLL_STATE_NOT_READY) {
pfd->revents |= POLLIN;
}
pev++;
}
if (pfd->revents != 0) {
ret++;
}
}
return ret;
}