summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGregory Nutt <gnutt@nuttx.org>2014-10-11 08:15:23 -0600
committerGregory Nutt <gnutt@nuttx.org>2014-10-11 08:15:23 -0600
commitea06ccf99b5d9fb74f1c57f9a6cbc42758f55442 (patch)
treef710f98791aeeb1a227a85b6d85c60a7b4edcb44
parent4be643e96853f9c88983cbfcf63bccb24f43b7fe (diff)
downloadnuttx-ea06ccf99b5d9fb74f1c57f9a6cbc42758f55442.tar.gz
nuttx-ea06ccf99b5d9fb74f1c57f9a6cbc42758f55442.tar.bz2
nuttx-ea06ccf99b5d9fb74f1c57f9a6cbc42758f55442.zip
AIO now also supports socket transfers
-rw-r--r--nuttx/TODO20
-rw-r--r--nuttx/fs/aio/aio.h37
-rw-r--r--nuttx/fs/aio/aio_fsync.c4
-rw-r--r--nuttx/fs/aio/aio_read.c45
-rw-r--r--nuttx/fs/aio/aio_write.c85
-rw-r--r--nuttx/fs/aio/aioc_contain.c48
-rw-r--r--nuttx/include/aio.h2
-rw-r--r--nuttx/include/nuttx/net/net.h9
-rw-r--r--nuttx/net/socket/net_sockets.c2
9 files changed, 175 insertions, 77 deletions
diff --git a/nuttx/TODO b/nuttx/TODO
index 0cd977eff..c4872109c 100644
--- a/nuttx/TODO
+++ b/nuttx/TODO
@@ -1,4 +1,4 @@
-NuttX TODO List (Last updated October 10, 2014)
+NuttX TODO List (Last updated October 11, 2014)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
This file summarizes known NuttX bugs, limitations, inconsistencies with
@@ -18,7 +18,7 @@ nuttx/
(13) Network (net/, drivers/net)
(4) USB (drivers/usbdev, drivers/usbhost)
(10) Libraries (libc/, )
- (12) File system/Generic drivers (fs/, drivers/)
+ (11) File system/Generic drivers (fs/, drivers/)
(6) Graphics subystem (graphics/)
(1) Pascal add-on (pcode/)
(1) Documentation (Documentation/)
@@ -1163,22 +1163,6 @@ o File system / Generic drivers (fs/, drivers/)
Status: Open
Priority: Medium
- Title: ASYNCHRONOUS I/O DOES NOT WORK WITH SOCKETS
- Description: The current asynchronous I/O logic will only work with
- file descriptions. If given a socket descriptor, the
- AIO interfaces will fail with EBADF. The existing logic
- should be extended to handle socket descriptors.
-
- This should be an easy fix: There could have to be a
- tagged union of a struct file and struct socket in the
- AIO container and the worker logic would have to select
- the correct low-level, internal interface. There would
- be no lseek'ing on sockets.
-
- Status: Open
- Priority: Pretty high because this limits the usefulness of the
- AIO implementation.
-
o Graphics subsystem (graphics/)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/nuttx/fs/aio/aio.h b/nuttx/fs/aio/aio.h
index 0f811e9ea..f74269a19 100644
--- a/nuttx/fs/aio/aio.h
+++ b/nuttx/fs/aio/aio.h
@@ -48,6 +48,7 @@
#include <queue.h>
#include <nuttx/wqueue.h>
+#include <nuttx/net/net.h>
#ifdef CONFIG_FS_AIO
@@ -62,6 +63,21 @@
# define CONFIG_FS_NAIOC 8
#endif
+#undef AIO_HAVE_FILEP
+#undef AIO_HAVE_PSOCK
+
+#if CONFIG_NFILE_DESCRIPTORS > 0
+# define AIO_HAVE_FILEP
+#endif
+
+#if defined(CONFIG_NET_TCP) && CONFIG_NSOCKET_DESCRIPTORS > 0
+# define AIO_HAVE_PSOCK
+#endif
+
+#if !defined(AIO_HAVE_FILEP) && !defined(AIO_HAVE_PSOCK)
+# error AIO needs file and/or socket descriptors
+#endif
+
/****************************************************************************
* Public Types
****************************************************************************/
@@ -73,13 +89,22 @@
struct file;
struct aio_container_s
{
- dq_entry_t aioc_link; /* Supports a doubly linked list */
- FAR struct aiocb *aioc_aiocbp; /* The contained AIO control block */
- FAR struct file *aioc_filep; /* File structure to use with the I/O */
- struct work_s aioc_work; /* Used to defer I/O to the work thread */
- pid_t aioc_pid; /* ID of the waiting task */
+ dq_entry_t aioc_link; /* Supports a doubly linked list */
+ FAR struct aiocb *aioc_aiocbp; /* The contained AIO control block */
+ union
+ {
+#ifdef AIO_HAVE_FILEP
+ FAR struct file *aioc_filep; /* File structure to use with the I/O */
+#endif
+#ifdef AIO_HAVE_PSOCK
+ FAR struct socket *aioc_psock; /* Socket structure to use with the I/O */
+#endif
+ FAR void *ptr; /* Generic pointer to FAR data */
+ } u;
+ struct work_s aioc_work; /* Used to defer I/O to the work thread */
+ pid_t aioc_pid; /* ID of the waiting task */
#ifdef CONFIG_PRIORITY_INHERITANCE
- uint8_t aioc_prio; /* Priority of the waiting task */
+ uint8_t aioc_prio; /* Priority of the waiting task */
#endif
};
diff --git a/nuttx/fs/aio/aio_fsync.c b/nuttx/fs/aio/aio_fsync.c
index cfb2522e6..ad816264b 100644
--- a/nuttx/fs/aio/aio_fsync.c
+++ b/nuttx/fs/aio/aio_fsync.c
@@ -110,9 +110,9 @@ static void aio_fsync_worker(FAR void *arg)
#endif
aiocbp = aioc_decant(aioc);
- /* Perform the fsync using aioc_filep */
+ /* Perform the fsync using u.aioc_filep */
- ret = file_fsync(aioc->aioc_filep);
+ ret = file_fsync(aioc->u.aioc_filep);
if (ret < 0)
{
int errcode = get_errno();
diff --git a/nuttx/fs/aio/aio_read.c b/nuttx/fs/aio/aio_read.c
index 3a3c5f234..c020c4ced 100644
--- a/nuttx/fs/aio/aio_read.c
+++ b/nuttx/fs/aio/aio_read.c
@@ -46,6 +46,8 @@
#include <errno.h>
#include <debug.h>
+#include <nuttx/net/net.h>
+
#include "aio/aio.h"
#ifdef CONFIG_FS_AIO
@@ -108,16 +110,39 @@ static void aio_read_worker(FAR void *arg)
#endif
aiocbp = aioc_decant(aioc);
- /* Perform the read using:
- *
- * aioc_filep - File structure pointer
- * aio_buf - Location of buffer
- * aio_nbytes - Length of transfer
- * aio_offset - File offset
- */
-
- nread = file_pread(aioc->aioc_filep, (FAR void *)aiocbp->aio_buf,
- aiocbp->aio_nbytes, aiocbp->aio_offset);
+#if defined(AIO_HAVE_FILEP) && defined(AIO_HAVE_PSOCK)
+ if (aioc->fildes >= CONFIG_NFILE_DESCRIPTORS)
+#endif
+#ifdef AIO_HAVE_FILEP
+ {
+ /* Perform the file read using:
+ *
+ * u.aioc_filep - File structure pointer
+ * aio_buf - Location of buffer
+ * aio_nbytes - Length of transfer
+ * aio_offset - File offset
+ */
+
+ nread = file_pread(aioc->u.aioc_filep, (FAR void *)aiocbp->aio_buf,
+ aiocbp->aio_nbytes, aiocbp->aio_offset);
+ }
+#endif
+#if defined(AIO_HAVE_FILEP) && defined(AIO_HAVE_PSOCK)
+ else
+#endif
+#ifdef AIO_HAVE_PSOCK
+ {
+ /* Perform the socket receive using:
+ *
+ * u.aioc_psock - Socket structure pointer
+ * aio_buf - Location of buffer
+ * aio_nbytes - Length of transfer
+ */
+
+ nread = psock_recv(aioc->u.aioc_psock, (FAR void *)aiocbp->aio_buf,
+ aiocbp->aio_nbytes, 0);
+ }
+#endif
/* Set the result of the read */
diff --git a/nuttx/fs/aio/aio_write.c b/nuttx/fs/aio/aio_write.c
index 497f8010d..a3cf99cab 100644
--- a/nuttx/fs/aio/aio_write.c
+++ b/nuttx/fs/aio/aio_write.c
@@ -76,6 +76,7 @@
* Name: file_fcntl
****************************************************************************/
+#ifdef AIO_HAVE_FILEP
static inline int file_fcntl(FAR struct file *filep, int cmd, ...)
{
va_list ap;
@@ -86,6 +87,7 @@ static inline int file_fcntl(FAR struct file *filep, int cmd, ...)
va_end(ap);
return ret;
}
+#endif
/****************************************************************************
* Name: aio_write_worker
@@ -126,23 +128,28 @@ static void aio_write_worker(FAR void *arg)
#endif
aiocbp = aioc_decant(aioc);
- /* Call fcntl(F_GETFL) to get the file open mode. */
-
- oflags = file_fcntl(aioc->aioc_filep, F_GETFL);
- if (oflags < 0)
- {
- int errcode = get_errno();
- fdbg("ERROR: fcntl failed: %d\n", errcode);
- aiocbp->aio_result = -errcode;
- }
- else
+#if defined(AIO_HAVE_FILEP) && defined(AIO_HAVE_PSOCK)
+ if (aioc->fildes >= CONFIG_NFILE_DESCRIPTORS)
+#endif
+#ifdef AIO_HAVE_FILEP
{
+ /* Call fcntl(F_GETFL) to get the file open mode. */
+
+ oflags = file_fcntl(aioc->u.aioc_filep, F_GETFL);
+ if (oflags < 0)
+ {
+ int errcode = get_errno();
+ fdbg("ERROR: fcntl failed: %d\n", errcode);
+ aiocbp->aio_result = -errcode;
+ goto errout:
+ }
+
/* Perform the write using:
*
- * aioc_filep - File descriptor
- * aio_buf - Location of buffer
- * aio_nbytes - Length of transfer
- * aio_offset - File offset
+ * u.aioc_filep - File structure pointer
+ * aio_buf - Location of buffer
+ * aio_nbytes - Length of transfer
+ * aio_offset - File offset
*/
/* Check if O_APPEND is set in the file open flags */
@@ -151,32 +158,54 @@ static void aio_write_worker(FAR void *arg)
{
/* Append to the current file position */
- nwritten = file_write(aioc->aioc_filep,
+ nwritten = file_write(aioc->u.aioc_filep,
(FAR const void *)aiocbp->aio_buf,
aiocbp->aio_nbytes);
}
else
{
- nwritten = file_pwrite(aioc->aioc_filep,
+ nwritten = file_pwrite(aioc->u.aioc_filep,
(FAR const void *)aiocbp->aio_buf,
aiocbp->aio_nbytes,
aiocbp->aio_offset);
}
+ }
+#endif
+#if defined(AIO_HAVE_FILEP) && defined(AIO_HAVE_PSOCK)
+ else
+#endif
+#ifdef AIO_HAVE_PSOCK
+ {
+ /* Perform the send using:
+ *
+ * u.aioc_psock - Socket structure pointer
+ * aio_buf - Location of buffer
+ * aio_nbytes - Length of transfer
+ */
- /* Set the result of the write */
+ nwritten = psock_send(aioc->u.aioc_psock,
+ (FAR const void *)aiocbp->aio_buf,
+ aiocbp->aio_nbytes, 0);
+ }
+#endif
- if (nwritten < 0)
- {
- int errcode = get_errno();
- fdbg("ERROR: write/pwrite failed: %d\n", errcode);
- DEBUGASSERT(errcode > 0);
- aiocbp->aio_result = -errcode;
- }
- else
- {
- aiocbp->aio_result = nwritten;
- }
+ /* Check the result of the write */
+
+ if (nwritten < 0)
+ {
+ int errcode = get_errno();
+ fdbg("ERROR: write/pwrite failed: %d\n", errcode);
+ DEBUGASSERT(errcode > 0);
+ aiocbp->aio_result = -errcode;
}
+ else
+ {
+ aiocbp->aio_result = nwritten;
+ }
+
+#ifdef AIO_HAVE_FILEP
+errout:
+#endif
/* Signal the client */
diff --git a/nuttx/fs/aio/aioc_contain.c b/nuttx/fs/aio/aioc_contain.c
index 98fcf7821..50b2f9d43 100644
--- a/nuttx/fs/aio/aioc_contain.c
+++ b/nuttx/fs/aio/aioc_contain.c
@@ -42,6 +42,7 @@
#include <sched.h>
#include <nuttx/fs/fs.h>
+#include <nuttx/net/net.h>
#include "aio/aio.h"
@@ -90,20 +91,53 @@
FAR struct aio_container_s *aio_contain(FAR struct aiocb *aiocbp)
{
FAR struct aio_container_s *aioc;
- FAR struct file *filep;
+ union
+ {
+#ifdef AIO_HAVE_FILEP
+ FAR struct file *filep;
+#endif
+#ifdef AIO_HAVE_FILEP
+ FAR struct socket *psock;
+#endif
+ FAR void *ptr;
+ } u;
#ifdef CONFIG_PRIORITY_INHERITANCE
struct sched_param param;
#endif
- /* Get the file structure corresponding to the file descriptor. */
+#if defined(AIO_HAVE_FILEP) && defined(AIO_HAVE_PSOCK)
+ if (aioc->fildes >= CONFIG_NFILE_DESCRIPTORS)
+#endif
+#ifdef AIO_HAVE_FILEP
+ {
+ /* Get the file structure corresponding to the file descriptor. */
+
+ u.filep = fs_getfilep(aiocbp->aio_fildes);
+ if (!u.filep)
+ {
+ /* The errno value has already been set */
- filep = fs_getfilep(aiocbp->aio_fildes);
- if (!filep)
+ return NULL;
+ }
+ }
+#endif
+#if defined(AIO_HAVE_FILEP) && defined(AIO_HAVE_PSOCK)
+ else
+#endif
+#ifdef AIO_HAVE_PSOCK
{
- /* The errno value has already been set */
+ /* Get the socket structure corresponding to the socket descriptor */
- return NULL;
+ u.psock = sockfd_socket(aiocbp->aio_fildes);
+ if (!u.psock)
+ {
+ /* Does not set the errno. EBADF is the most likely explanation. */
+
+ set_errno(EBADF);
+ return NULL;
+ }
}
+#endif
/* Allocate the AIO control block container, waiting for one to become
* available if necessary. This should never fail.
@@ -116,7 +150,7 @@ FAR struct aio_container_s *aio_contain(FAR struct aiocb *aiocbp)
memset(aioc, 0, sizeof(struct aio_container_s));
aioc->aioc_aiocbp = aiocbp;
- aioc->aioc_filep = filep;
+ aioc->u.aioc_filep = u.ptr;
aioc->aioc_pid = getpid();
#ifdef CONFIG_PRIORITY_INHERITANCE
diff --git a/nuttx/include/aio.h b/nuttx/include/aio.h
index b323e01b3..183caec06 100644
--- a/nuttx/include/aio.h
+++ b/nuttx/include/aio.h
@@ -125,7 +125,7 @@ struct aiocb
FAR volatile void *aio_buf; /* Location of buffer */
off_t aio_offset; /* File offset */
size_t aio_nbytes; /* Length of transfer */
-#if CONFIG_NFILE_DESCRIPTORS > 127
+#if (CONFIG_NFILE_DESCRIPTORS + CONFIG_NSOCKET_DESCRIPTORS) > 127
int16_t aio_fildes; /* File descriptor (should be int) */
#else
int8_t aio_fildes; /* File descriptor (should be int) */
diff --git a/nuttx/include/nuttx/net/net.h b/nuttx/include/nuttx/net/net.h
index f2cf839b3..23558b427 100644
--- a/nuttx/include/nuttx/net/net.h
+++ b/nuttx/include/nuttx/net/net.h
@@ -302,16 +302,17 @@ void net_initlist(FAR struct socketlist *list);
void net_releaselist(FAR struct socketlist *list);
/****************************************************************************
- * Name: sockfd_release
+ * Name: sockfd_socket
*
* Description:
- * Free the socket by its socket descriptor.
+ * Given a socket descriptor, return the underlying socket structure.
*
* Input Parameters:
- * sockfd - Socket descriptor identifies the socket to be released.
+ * sockfd - The socket descriptor index o use.
*
* Returned Value:
- * None
+ * On success, a reference to the socket structure associated with the
+ * the socket descriptor is returned. NULL is returned on any failure.
*
****************************************************************************/
diff --git a/nuttx/net/socket/net_sockets.c b/nuttx/net/socket/net_sockets.c
index 632d15aa5..a98d67fc1 100644
--- a/nuttx/net/socket/net_sockets.c
+++ b/nuttx/net/socket/net_sockets.c
@@ -94,7 +94,7 @@ static void _net_semtake(FAR struct socketlist *list)
****************************************************************************/
/****************************************************************************
- * Name:
+ * Name: net_initlist
*
* Description:
* Initialize a list of sockets for a new task