summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--nuttx/fs/aio/aio_cancel.c49
-rw-r--r--nuttx/fs/aio/aio_fsync.c35
-rw-r--r--nuttx/fs/aio/aio_read.c33
-rw-r--r--nuttx/fs/aio/aio_signal.c19
-rw-r--r--nuttx/fs/aio/aio_write.c33
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;