Modify logic to use AIO control block container

This commit is contained in:
Gregory Nutt 2014-10-06 08:10:32 -06:00
parent 52ce95b8b8
commit a5b4a4161b
5 changed files with 115 additions and 52 deletions

View File

@ -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.
*/
/* No.. Find the container for this AIO control block */
status = work_cancel(LPWORK, &aiocbp->aio_work);
ret = status >= 0 ? AIO_CANCELED : AIO_NOTCANCELED;
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
{

View File

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

View File

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

View File

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

View File

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