From 5736cf10afe2fbc6e26fd240d18ec9b4f4ef7189 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Fri, 30 Jan 2015 07:25:01 -0600 Subject: [PATCH] Networking: Separate TCP poll logic out of net/sockets/net_poll.c and move it into the new net/tcp/tcp_netpoll.c. --- net/socket/net_poll.c | 321 +------------------------- net/tcp/Make.defs | 8 +- net/tcp/tcp.h | 41 ++++ net/tcp/{tcp_poll.c => tcp_devpoll.c} | 4 +- 4 files changed, 52 insertions(+), 322 deletions(-) rename net/tcp/{tcp_poll.c => tcp_devpoll.c} (98%) diff --git a/net/socket/net_poll.c b/net/socket/net_poll.c index 8dfa41f94b..e534e9d022 100644 --- a/net/socket/net_poll.c +++ b/net/socket/net_poll.c @@ -38,28 +38,16 @@ ****************************************************************************/ #include -#if defined(CONFIG_NET) && !defined(CONFIG_DISABLE_POLL) -#include -#include -#include -#include -#include #include -#include -#include -#include -#include -#include -#include - -#include #include "tcp/tcp.h" #include "udp/udp.h" #include "local/local.h" #include "socket/socket.h" +#if defined(CONFIG_NET) && !defined(CONFIG_DISABLE_POLL) + /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ @@ -75,257 +63,10 @@ #ifdef HAVE_NET_POLL -/**************************************************************************** - * Private Types - ****************************************************************************/ -/* This is an allocated container that holds the poll-related information */ - -struct net_poll_s -{ - FAR struct socket *psock; /* Needed to handle loss of connection */ - struct pollfd *fds; /* Needed to handle poll events */ - FAR struct devif_callback_s *cb; /* Needed to teardown the poll */ -}; - /**************************************************************************** * Private Functions ****************************************************************************/ -/**************************************************************************** - * Function: tcp_poll_interrupt - * - * Description: - * This function is called from the interrupt level to perform the actual - * TCP receive operation via by the device interface layer. - * - * Parameters: - * dev The structure of the network driver that caused the interrupt - * conn The connection structure associated with the socket - * flags Set of events describing why the callback was invoked - * - * Returned Value: - * None - * - * Assumptions: - * Running at the interrupt level - * - ****************************************************************************/ - -#ifdef HAVE_TCP_POLL -static uint16_t tcp_poll_interrupt(FAR struct net_driver_s *dev, FAR void *conn, - FAR void *pvpriv, uint16_t flags) -{ - FAR struct net_poll_s *info = (FAR struct net_poll_s *)pvpriv; - - nllvdbg("flags: %04x\n", flags); - - DEBUGASSERT(!info || (info->psock && info->fds)); - - /* 'priv' might be null in some race conditions (?) */ - - if (info) - { - pollevent_t eventset = 0; - - /* Check for data or connection availability events. */ - - if ((flags & (TCP_NEWDATA | TCP_BACKLOG)) != 0) - { - eventset |= POLLIN & info->fds->events; - } - - /* A poll is a sign that we are free to send data. */ - - if ((flags & TCP_POLL) != 0) - { - eventset |= (POLLOUT & info->fds->events); - } - - /* Check for a loss of connection events. */ - - if ((flags & (TCP_CLOSE | TCP_ABORT | TCP_TIMEDOUT)) != 0) - { - /* Marki that the connection has been lost */ - - net_lostconnection(info->psock, flags); - eventset |= (POLLERR | POLLHUP); - } - - /* Awaken the caller of poll() is requested event occurred. */ - - if (eventset) - { - info->fds->revents |= eventset; - sem_post(info->fds->sem); - } - } - - return flags; -} -#endif /* HAVE_TCP_POLL */ - -/**************************************************************************** - * Function: tcp_pollsetup - * - * Description: - * Setup to monitor events on one TCP/IP socket - * - * Input Parameters: - * psock - The TCP/IP socket of interest - * fds - The structure describing the events to be monitored, OR NULL if - * this is a request to stop monitoring events. - * - * Returned Value: - * 0: Success; Negated errno on failure - * - ****************************************************************************/ - -#ifdef HAVE_TCP_POLL -static inline int tcp_pollsetup(FAR struct socket *psock, - FAR struct pollfd *fds) -{ - FAR struct tcp_conn_s *conn = psock->s_conn; - FAR struct net_poll_s *info; - FAR struct devif_callback_s *cb; - net_lock_t flags; - int ret; - - /* Sanity check */ - -#ifdef CONFIG_DEBUG - if (!conn || !fds) - { - return -EINVAL; - } -#endif - - /* Allocate a container to hold the poll information */ - - info = (FAR struct net_poll_s *)kmm_malloc(sizeof(struct net_poll_s)); - if (!info) - { - return -ENOMEM; - } - - /* Some of the following must be atomic */ - - flags = net_lock(); - - /* Allocate a TCP/IP callback structure */ - - cb = tcp_callback_alloc(conn); - if (!cb) - { - ret = -EBUSY; - goto errout_with_lock; - } - - /* Initialize the poll info container */ - - info->psock = psock; - info->fds = fds; - info->cb = cb; - - /* Initialize the callback structure. Save the reference to the info - * structure as callback private data so that it will be available during - * callback processing. - */ - - cb->flags = (TCP_NEWDATA | TCP_BACKLOG | TCP_POLL | TCP_CLOSE | - TCP_ABORT | TCP_TIMEDOUT); - cb->priv = (FAR void *)info; - cb->event = tcp_poll_interrupt; - - /* Save the reference in the poll info structure as fds private as well - * for use durring poll teardown as well. - */ - - fds->priv = (FAR void *)info; - -#ifdef CONFIG_NET_TCPBACKLOG - /* Check for read data or backlogged connection availability now */ - - if (!IOB_QEMPTY(&conn->readahead) || tcp_backlogavailable(conn)) -#else - /* Check for read data availability now */ - - if (!IOB_QEMPTY(&conn->readahead)) -#endif - { - /* Normal data may be read without blocking. */ - - fds->revents |= (POLLRDNORM & fds->events); - } - - /* Check for a loss of connection events. We need to be careful here. - * There are four possibilities: - * - * 1) The socket is connected and we are waiting for data availability - * events. - * - * __SS_ISCONNECTED(f) == true - * __SS_ISLISTENING(f) == false - * __SS_ISCLOSED(f) == false - * - * Action: Wait for data availability events - * - * 2) This is a listener socket that was never connected and we are - * waiting for connection events. - * - * __SS_ISCONNECTED(f) == false - * __SS_ISLISTENING(f) == true - * __SS_ISCLOSED(f) == false - * - * Action: Wait for connection events - * - * 3) This socket was previously connected, but the peer has gracefully - * closed the connection. - * - * __SS_ISCONNECTED(f) == false - * __SS_ISLISTENING(f) == false - * __SS_ISCLOSED(f) == true - * - * Action: Return with POLLHUP|POLLERR events - * - * 4) This socket was previously connected, but we lost the connection - * due to some exceptional event. - * - * __SS_ISCONNECTED(f) == false - * __SS_ISLISTENING(f) == false - * __SS_ISCLOSED(f) == false - * - * Action: Return with POLLHUP|POLLERR events - */ - - if (!_SS_ISCONNECTED(psock->s_flags) && !_SS_ISLISTENING(psock->s_flags)) - { - /* We were previously connected but lost the connection either due - * to a graceful shutdown by the remote peer or because of some - * exceptional event. - */ - - fds->revents |= (POLLERR | POLLHUP); - } - - /* Check if any requested events are already in effect */ - - if (fds->revents != 0) - { - /* Yes.. then signal the poll logic */ - - sem_post(fds->sem); - } - - net_unlock(flags); - return OK; - -errout_with_lock: - kmm_free(info); - net_unlock(flags); - return ret; -} -#endif /* HAVE_TCP_POLL */ - /**************************************************************************** * Function: net_pollsetup * @@ -394,64 +135,6 @@ static inline int net_pollsetup(FAR struct socket *psock, return -ENOSYS; } -/**************************************************************************** - * Function: tcp_pollteardown - * - * Description: - * Teardown monitoring of events on an TCP/IP socket - * - * Input Parameters: - * psock - The TCP/IP socket of interest - * fds - The structure describing the events to be monitored, OR NULL if - * this is a request to stop monitoring events. - * - * Returned Value: - * 0: Success; Negated errno on failure - * - ****************************************************************************/ - -#ifdef HAVE_TCP_POLL -static inline int tcp_pollteardown(FAR struct socket *psock, - FAR struct pollfd *fds) -{ - FAR struct tcp_conn_s *conn = psock->s_conn; - FAR struct net_poll_s *info; - net_lock_t flags; - - /* Sanity check */ - -#ifdef CONFIG_DEBUG - if (!conn || !fds->priv) - { - return -EINVAL; - } -#endif - - /* Recover the socket descriptor poll state info from the poll structure */ - - info = (FAR struct net_poll_s *)fds->priv; - DEBUGASSERT(info && info->fds && info->cb); - if (info) - { - /* Release the callback */ - - flags = net_lock(); - tcp_callback_free(conn, info->cb); - net_unlock(flags); - - /* Release the poll/select data slot */ - - info->fds->priv = NULL; - - /* Then free the poll info container */ - - kmm_free(info); - } - - return OK; -} -#endif /* HAVE_TCP_POLL */ - /**************************************************************************** * Function: net_pollteardown * diff --git a/net/tcp/Make.defs b/net/tcp/Make.defs index 41a03469ec..6daf335320 100644 --- a/net/tcp/Make.defs +++ b/net/tcp/Make.defs @@ -47,9 +47,15 @@ else SOCK_CSRCS += tcp_send_unbuffered.c endif +ifneq ($(CONFIG_DISABLE_POLL),y) +ifeq ($(CONFIG_NET_TCP_READAHEAD),y) +NET_CSRCS += tcp_netpoll.c +endif +endif + # Transport layer -NET_CSRCS += tcp_conn.c tcp_seqno.c tcp_poll.c tcp_timer.c tcp_send.c +NET_CSRCS += tcp_conn.c tcp_seqno.c tcp_devpoll.c tcp_timer.c tcp_send.c NET_CSRCS += tcp_input.c tcp_appsend.c tcp_listen.c tcp_callback.c NET_CSRCS += tcp_backlog.c tcp_ipselect.c diff --git a/net/tcp/tcp.h b/net/tcp/tcp.h index 72fc3b96b5..6fa263d4b7 100644 --- a/net/tcp/tcp.h +++ b/net/tcp/tcp.h @@ -275,6 +275,7 @@ extern "C" struct sockaddr; /* Forward reference */ struct socket; /* Forward reference */ +struct pollfd; /* Forward reference */ /**************************************************************************** * Name: tcp_initialize @@ -1063,6 +1064,46 @@ void tcp_wrbuffer_dump(FAR const char *msg, FAR struct tcp_wrbuffer_s *wrb, #endif #endif /* CONFIG_NET_TCP_WRITE_BUFFERS */ +/**************************************************************************** + * Function: tcp_pollsetup + * + * Description: + * Setup to monitor events on one TCP/IP socket + * + * Input Parameters: + * psock - The TCP/IP socket of interest + * fds - The structure describing the events to be monitored, OR NULL if + * this is a request to stop monitoring events. + * + * Returned Value: + * 0: Success; Negated errno on failure + * + ****************************************************************************/ + +#ifdef HAVE_TCP_POLL +int tcp_pollsetup(FAR struct socket *psock, FAR struct pollfd *fds); +#endif + +/**************************************************************************** + * Function: tcp_pollteardown + * + * Description: + * Teardown monitoring of events on an TCP/IP socket + * + * Input Parameters: + * psock - The TCP/IP socket of interest + * fds - The structure describing the events to be monitored, OR NULL if + * this is a request to stop monitoring events. + * + * Returned Value: + * 0: Success; Negated errno on failure + * + ****************************************************************************/ + +#ifdef HAVE_TCP_POLL +int tcp_pollteardown(FAR struct socket *psock, FAR struct pollfd *fds); +#endif + #undef EXTERN #ifdef __cplusplus } diff --git a/net/tcp/tcp_poll.c b/net/tcp/tcp_devpoll.c similarity index 98% rename from net/tcp/tcp_poll.c rename to net/tcp/tcp_devpoll.c index e5e99cabef..32bf535ee9 100644 --- a/net/tcp/tcp_poll.c +++ b/net/tcp/tcp_devpoll.c @@ -1,6 +1,6 @@ /**************************************************************************** - * net/tcp/tcp_poll.c - * Poll for the availability of TCP TX data + * net/tcp/tcp_devpoll.c + * Driver poll for the availability of TCP TX data * * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. * Author: Gregory Nutt