diff options
-rw-r--r-- | nuttx/fs/aio/aio_cancel.c | 49 | ||||
-rw-r--r-- | nuttx/fs/aio/aio_fsync.c | 35 | ||||
-rw-r--r-- | nuttx/fs/aio/aio_read.c | 33 | ||||
-rw-r--r-- | nuttx/fs/aio/aio_signal.c | 19 | ||||
-rw-r--r-- | nuttx/fs/aio/aio_write.c | 33 |
5 files changed, 116 insertions, 53 deletions
diff --git a/nuttx/fs/aio/aio_cancel.c b/nuttx/fs/aio/aio_cancel.c index ec49c3ecf..99c9d07f8 100644 --- a/nuttx/fs/aio/aio_cancel.c +++ b/nuttx/fs/aio/aio_cancel.c @@ -1,5 +1,5 @@ /**************************************************************************** - * libc/aio/aio_cancel.c + * fs/aio/aio_cancel.c * * Copyright (C) 2014 Gregory Nutt. All rights reserved. * Author: Gregory Nutt <gnutt@nuttx.org> @@ -60,11 +60,11 @@ ****************************************************************************/ /**************************************************************************** - * Private Variables + * Private Data ****************************************************************************/ /**************************************************************************** - * Public Variables + * Public Data ****************************************************************************/ /**************************************************************************** @@ -95,7 +95,7 @@ * will not be modified by aio_cancel(). * * Input Parameters: - * fildes - Not used in this implmentation + * fildes - Not used in this implementation * aiocbp - Points to the asynchronous I/O control block for a particular * request to be cancelled. * @@ -122,6 +122,7 @@ int aio_cancel(int fildes, FAR struct aiocb *aiocbp) { + FAR struct aio_container_s *aioc; int status; int ret; @@ -143,15 +144,37 @@ int aio_cancel(int fildes, FAR struct aiocb *aiocbp) if (aiocbp->aio_result == -EINPROGRESS) { - /* No ... attempt to cancel the I/O. There are two possibilities: (1) - * the work has already been started and is no longer queued, or (2) - * the work has not been started and is still in the work queue. Only - * the second case can be cancelled. work_cancel() will return - * -ENOENT in the first case. - */ - - status = work_cancel(LPWORK, &aiocbp->aio_work); - ret = status >= 0 ? AIO_CANCELED : AIO_NOTCANCELED; + /* No.. Find the container for this AIO control block */ + + aio_lock(); + for (aioc = (FAR struct aio_container_s *)g_aio_pending.head; + aioc && aioc->aioc_aiocbp != aiocbp; + aioc = (FAR struct aio_container_s *)aioc->aioc_link.flink); + aio_unlock(); + + /* Did we find the container? */ + + if (!aioc) + { + /* No.. the aio_result says that that the transfer is pending, + * but there is no container in the pending I/O list. I am + * confused. + */ + + ret = AIO_ALLDONE; + } + else + { + /* Yes... attempt to cancel the I/O. There are two possibilities: + * (1) the work has already been started and is no longer queued, + * or (2) the work has not been started and is still in the work + * queue. Only the second case can be cancelled. work_cancel() + * will return -ENOENT in the first case. + */ + + status = work_cancel(LPWORK, &aioc->aioc_work); + ret = status >= 0 ? AIO_CANCELED : AIO_NOTCANCELED; + } } else { diff --git a/nuttx/fs/aio/aio_fsync.c b/nuttx/fs/aio/aio_fsync.c index 86f208815..3df22bec6 100644 --- a/nuttx/fs/aio/aio_fsync.c +++ b/nuttx/fs/aio/aio_fsync.c @@ -1,5 +1,5 @@ /**************************************************************************** - * libc/aio/aio_fsync.c + * fs/aio/aio_fsync.c * * Copyright (C) 2014 Gregory Nutt. All rights reserved. * Author: Gregory Nutt <gnutt@nuttx.org> @@ -54,18 +54,17 @@ /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ -/* Configuration ************************************************************/ /**************************************************************************** * Private Types ****************************************************************************/ /**************************************************************************** - * Private Variables + * Private Data ****************************************************************************/ /**************************************************************************** - * Public Variables + * Public Data ****************************************************************************/ /**************************************************************************** @@ -90,10 +89,20 @@ static void aio_fsync_worker(FAR void *arg) { - FAR struct aiocb *aiocbp = (FAR struct aiocb *)arg; - DEBUGASSERT(arg); + FAR struct aio_container_s *aioc = (FAR struct aio_container_s *)arg; + FAR struct aiocb *aiocbp; + pid_t pid; int ret; + /* Get the information from the container, decant the AIO control block, + * and free the container before starting any I/O. That will minimize + * the delays by any other threads waiting for a pre-allocated container. + */ + + DEBUGASSERT(aioc && aioc->aioc_aiocbp); + pid = aioc->aioc_pid; + aiocbp = aioc_decant(aioc); + /* Perform the fsync using aio_fildes */ ret = fsync(aiocbp->aio_fildes); @@ -111,7 +120,7 @@ static void aio_fsync_worker(FAR void *arg) /* Signal the client */ - (void)aio_signal(aiocbp); + (void)aio_signal(pid, aiocbp); } /**************************************************************************** @@ -169,7 +178,7 @@ static void aio_fsync_worker(FAR void *arg) * aiocbp - A pointer to an instance of struct aiocb * * Returned Value: - * The aio_fsync() function will return the value 0 if the I/O operation is + * The aio_fsync() function will return the value 0 if the I/O operation is * successfully queued; otherwise, the function will return the value -1 and * set errno to indicate the error. * @@ -198,6 +207,7 @@ static void aio_fsync_worker(FAR void *arg) int aio_fsync(int op, FAR struct aiocb *aiocbp) { + FAR struct aio_container_s *aioc; int ret; DEBUGASSERT(op == O_SYNC /* || op == O_DSYNC */); @@ -208,13 +218,16 @@ int aio_fsync(int op, FAR struct aiocb *aiocbp) aiocbp->aio_result = -EINPROGRESS; aiocbp->aio_priv = NULL; - /* Save the ID of the calling, client thread */ + /* Create a container for the AIO control block. This will not fail but + * may cause us to block if there are insufficient resources to satisfy + * the request. + */ - aiocbp->aio_pid = getpid(); + aioc = aio_contain(aiocbp); /* Defer the work to the worker thread */ - ret = work_queue(LPWORK, &aiocbp->aio_work, aio_fsync_worker, aiocbp, 0); + ret = work_queue(LPWORK, &aioc->aioc_work, aio_fsync_worker, aioc, 0); if (ret < 0) { aiocbp->aio_result = ret; diff --git a/nuttx/fs/aio/aio_read.c b/nuttx/fs/aio/aio_read.c index 002a646d2..c627a0d87 100644 --- a/nuttx/fs/aio/aio_read.c +++ b/nuttx/fs/aio/aio_read.c @@ -1,5 +1,5 @@ /**************************************************************************** - * libc/aio/aio_read.c + * fs/aio/aio_read.c * * Copyright (C) 2014 Gregory Nutt. All rights reserved. * Author: Gregory Nutt <gnutt@nuttx.org> @@ -55,18 +55,17 @@ /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ -/* Configuration ************************************************************/ /**************************************************************************** * Private Types ****************************************************************************/ /**************************************************************************** - * Private Variables + * Private Data ****************************************************************************/ /**************************************************************************** - * Public Variables + * Public Data ****************************************************************************/ /**************************************************************************** @@ -91,10 +90,20 @@ static void aio_read_worker(FAR void *arg) { - FAR struct aiocb *aiocbp = (FAR struct aiocb *)arg; - DEBUGASSERT(arg); + FAR struct aio_container_s *aioc = (FAR struct aio_container_s *)arg; + FAR struct aiocb *aiocbp; + pid_t pid; ssize_t nread; + /* Get the information from the container, decant the AIO control block, + * and free the container before starting any I/O. That will minimize + * the delays by any other threads waiting for a pre-allocated container. + */ + + DEBUGASSERT(aioc && aioc->aioc_aiocbp); + pid = aioc->aioc_pid; + aiocbp = aioc_decant(aioc); + /* Perform the read using: * * aio_fildes - File descriptor @@ -122,7 +131,7 @@ static void aio_read_worker(FAR void *arg) /* Signal the client */ - (void)aio_signal(aiocbp); + (void)aio_signal(pid, aiocbp); } /**************************************************************************** @@ -247,6 +256,7 @@ static void aio_read_worker(FAR void *arg) int aio_read(FAR struct aiocb *aiocbp) { + FAR struct aio_container_s *aioc; int ret; DEBUGASSERT(aiocbp); @@ -256,13 +266,16 @@ int aio_read(FAR struct aiocb *aiocbp) aiocbp->aio_result = -EINPROGRESS; aiocbp->aio_priv = NULL; - /* Save the ID of the calling, client thread */ + /* Create a container for the AIO control block. This will not fail but + * may cause us to block if there are insufficient resources to satisfy + * the request. + */ - aiocbp->aio_pid = getpid(); + aioc = aio_contain(aiocbp); /* Defer the work to the worker thread */ - ret = work_queue(LPWORK, &aiocbp->aio_work, aio_read_worker, aiocbp, 0); + ret = work_queue(LPWORK, &aioc->aioc_work, aio_read_worker, aioc, 0); if (ret < 0) { aiocbp->aio_result = ret; diff --git a/nuttx/fs/aio/aio_signal.c b/nuttx/fs/aio/aio_signal.c index aeec14f91..3e46f95da 100644 --- a/nuttx/fs/aio/aio_signal.c +++ b/nuttx/fs/aio/aio_signal.c @@ -1,5 +1,5 @@ /**************************************************************************** - * libc/aio/aio_signal.c + * fs/aio/aio_signal.c * * Copyright (C) 2014 Gregory Nutt. All rights reserved. * Author: Gregory Nutt <gnutt@nuttx.org> @@ -39,6 +39,7 @@ #include <nuttx/config.h> +#include <sys/types.h> #include <sched.h> #include <signal.h> #include <aio.h> @@ -53,18 +54,17 @@ /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ -/* Configuration ************************************************************/ /**************************************************************************** * Private Types ****************************************************************************/ /**************************************************************************** - * Private Variables + * Private Data ****************************************************************************/ /**************************************************************************** - * Public Variables + * Public Data ****************************************************************************/ /**************************************************************************** @@ -81,6 +81,7 @@ * Signal the client that an I/O has completed. * * Input Parameters: + * pid - ID of the task to signal * aiocbp - Pointer to the asynchronous I/O state structure that includes * information about how to signal the client * @@ -93,14 +94,14 @@ * ****************************************************************************/ -int aio_signal(FAR struct aiocb *aiocbp) +int aio_signal(pid_t pid, FAR struct aiocb *aiocbp) { int errcode; int status; int ret; DEBUGASSERT(aiocbp); - + ret = OK; /* Assume success */ /* Signal the client */ @@ -108,10 +109,10 @@ int aio_signal(FAR struct aiocb *aiocbp) if (aiocbp->aio_sigevent.sigev_notify == SIGEV_SIGNAL) { #ifdef CONFIG_CAN_PASS_STRUCTS - status = sigqueue(aiocbp->aio_pid, aiocbp->aio_sigevent.sigev_signo, + status = sigqueue(pid, aiocbp->aio_sigevent.sigev_signo, aiocbp->aio_sigevent.sigev_value); #else - status = sigqueue(aiocbp->aio_pid, aiocbp->aio_sigevent.sigev_sign, + status = sigqueue(pid, aiocbp->aio_sigevent.sigev_sign, aiocbp->aio_sigevent.sigev_value.sival_ptr); #endif if (ret < 0) @@ -126,7 +127,7 @@ int aio_signal(FAR struct aiocb *aiocbp) * on sig_suspend(); */ - status = kill(aiocbp->aio_pid, SIGPOLL); + status = kill(pid, SIGPOLL); if (status && ret == OK) { errcode = get_errno(); diff --git a/nuttx/fs/aio/aio_write.c b/nuttx/fs/aio/aio_write.c index 35613add1..2b1233e25 100644 --- a/nuttx/fs/aio/aio_write.c +++ b/nuttx/fs/aio/aio_write.c @@ -1,5 +1,5 @@ /**************************************************************************** - * libc/aio/aio_write.c + * fs/aio/aio_write.c * * Copyright (C) 2014 Gregory Nutt. All rights reserved. * Author: Gregory Nutt <gnutt@nuttx.org> @@ -56,18 +56,17 @@ /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ -/* Configuration ************************************************************/ /**************************************************************************** * Private Types ****************************************************************************/ /**************************************************************************** - * Private Variables + * Private Data ****************************************************************************/ /**************************************************************************** - * Public Variables + * Public Data ****************************************************************************/ /**************************************************************************** @@ -92,11 +91,21 @@ static void aio_write_worker(FAR void *arg) { - FAR struct aiocb *aiocbp = (FAR struct aiocb *)arg; - DEBUGASSERT(arg); + FAR struct aio_container_s *aioc = (FAR struct aio_container_s *)arg; + FAR struct aiocb *aiocbp; + pid_t pid; ssize_t nwritten; int oflags; + /* Get the information from the container, decant the AIO control block, + * and free the container before starting any I/O. That will minimize + * the delays by any other threads waiting for a pre-allocated container. + */ + + DEBUGASSERT(aioc && aioc->aioc_aiocbp); + pid = aioc->aioc_pid; + aiocbp = aioc_decant(aioc); + /* Call fcntl(F_GETFL) to get the file open mode. */ oflags = fcntl(aiocbp->aio_fildes, F_GETFL); @@ -151,7 +160,7 @@ static void aio_write_worker(FAR void *arg) /* Signal the client */ - (void)aio_signal(aiocbp); + (void)aio_signal(pid, aiocbp); } /**************************************************************************** @@ -278,6 +287,7 @@ static void aio_write_worker(FAR void *arg) int aio_write(FAR struct aiocb *aiocbp) { + FAR struct aio_container_s *aioc; int ret; DEBUGASSERT(aiocbp); @@ -287,13 +297,16 @@ int aio_write(FAR struct aiocb *aiocbp) aiocbp->aio_result = -EINPROGRESS; aiocbp->aio_priv = NULL; - /* Save the ID of the calling, client thread */ + /* Create a container for the AIO control block. This will not fail but + * may cause us to block if there are insufficient resources to satisfy + * the request. + */ - aiocbp->aio_pid = getpid(); + aioc = aio_contain(aiocbp); /* Defer the work to the worker thread */ - ret = work_queue(LPWORK, &aiocbp->aio_work, aio_write_worker, aiocbp, 0); + ret = work_queue(LPWORK, &aioc->aioc_work, aio_write_worker, aioc, 0); if (ret < 0) { aiocbp->aio_result = ret; |