AIO now also supports socket transfers

This commit is contained in:
Gregory Nutt 2014-10-11 08:15:23 -06:00
parent 0218f01f12
commit ae3cc327c7
9 changed files with 177 additions and 79 deletions

20
TODO
View File

@ -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/)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@ -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
};

View File

@ -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();

View File

@ -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
*/
#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->aioc_filep, (FAR void *)aiocbp->aio_buf,
aiocbp->aio_nbytes, aiocbp->aio_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 */

View File

@ -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. */
#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:
}
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
{
/* 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);
}
/* Set 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;
}
}
#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
*/
nwritten = psock_send(aioc->u.aioc_psock,
(FAR const void *)aiocbp->aio_buf,
aiocbp->aio_nbytes, 0);
}
#endif
/* 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 */

View File

@ -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. */
filep = fs_getfilep(aiocbp->aio_fildes);
if (!filep)
#if defined(AIO_HAVE_FILEP) && defined(AIO_HAVE_PSOCK)
if (aioc->fildes >= CONFIG_NFILE_DESCRIPTORS)
#endif
#ifdef AIO_HAVE_FILEP
{
/* The errno value has already been set */
/* Get the file structure corresponding to the file descriptor. */
return NULL;
u.filep = fs_getfilep(aiocbp->aio_fildes);
if (!u.filep)
{
/* The errno value has already been set */
return NULL;
}
}
#endif
#if defined(AIO_HAVE_FILEP) && defined(AIO_HAVE_PSOCK)
else
#endif
#ifdef AIO_HAVE_PSOCK
{
/* Get the socket structure corresponding to the socket descriptor */
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

View File

@ -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) */

View File

@ -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.
*
****************************************************************************/

View File

@ -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