summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGregory Nutt <gnutt@nuttx.org>2014-10-06 15:06:01 -0600
committerGregory Nutt <gnutt@nuttx.org>2014-10-06 15:06:01 -0600
commitf4555180b5847b4ee4b93c8d06f6741980a26128 (patch)
tree806ae4b955570f4da08809b0598a71e9f770b4e2
parentd934f6b74cb95d96ee4065f75c0110ab0bb12e92 (diff)
downloadnuttx-f4555180b5847b4ee4b93c8d06f6741980a26128.tar.gz
nuttx-f4555180b5847b4ee4b93c8d06f6741980a26128.tar.bz2
nuttx-f4555180b5847b4ee4b93c8d06f6741980a26128.zip
Add test for aio_cancel() and fix some bugs found by the test
-rw-r--r--apps/examples/ostest/aio.c104
-rw-r--r--nuttx/fs/aio/aio_cancel.c29
2 files changed, 123 insertions, 10 deletions
diff --git a/apps/examples/ostest/aio.c b/apps/examples/ostest/aio.c
index 29c00afc5..ad781325f 100644
--- a/apps/examples/ostest/aio.c
+++ b/apps/examples/ostest/aio.c
@@ -78,11 +78,14 @@ static char g_rdbuffer[AIO_RDBUFFER_SIZE];
static struct aiocb g_aiocbs[AIO_NCTRLBLKS-1];
-static struct aiocb *g_aiocb[AIO_NCTRLBLKS] =
+static struct aiocb *g_aiocb[AIO_NCTRLBLKS];
+
+static struct aiocb * const g_aiocb_init[AIO_NCTRLBLKS] =
{
&g_aiocbs[0], &g_aiocbs[1], &g_aiocbs[2], NULL, &g_aiocbs[3]
};
+
static FAR void * const g_buffers[AIO_NCTRLBLKS] =
{
(FAR void *)g_wrbuffer1,
@@ -127,7 +130,9 @@ static void init_aiocb(bool signal)
for (i = 0; i < AIO_NCTRLBLKS; i++)
{
- aiocbp = g_aiocb[i];
+ aiocbp = g_aiocb_init[i];
+ g_aiocb[i] = aiocbp;
+
if (aiocbp)
{
aiocbp->aio_sigevent.sigev_notify = signal ? SIGEV_SIGNAL : SIGEV_NONE;
@@ -173,6 +178,12 @@ static int check_done(void)
printf(" NOT finished\n");
return -EINPROGRESS;
}
+ else if (aiocbp->aio_result == -ECANCELED)
+ {
+ /* No.. return -EINPROGRESS */
+
+ printf(" Cancelled\n");
+ }
/* Check for an I/O error */
@@ -231,6 +242,13 @@ static int remove_done(void)
printf(" NOT finished\n");
ret = -EINPROGRESS;
}
+ else if (aiocbp->aio_result == -ECANCELED)
+ {
+ /* No.. return -EINPROGRESS */
+
+ printf(" Cancelled\n");
+ g_aiocb[i] = NULL;
+ }
/* Check for an I/O error */
@@ -326,7 +344,7 @@ void aio_test(void)
/* Case 3: Use aio_suspend() until complete */
- printf("AIO test case 2: Use aio_suspend for transfer complete\n");
+ printf("AIO test case 3: Use aio_suspend for transfer complete\n");
g_fildes = open(AIO_FILEPATH, O_RDWR|O_CREAT|O_TRUNC);
if (g_fildes < 0)
{
@@ -364,8 +382,88 @@ void aio_test(void)
/* Case 4: Use individual signals */
+
+ printf("AIO test case 4: Use individual signals for transfer complete\n");
+ /* REVISIT: Not yet implemented */
+
+ /* Case 5: Use list complete signal */
+
+ printf("AIO test case 5: Use list complete signal for transfer complete\n");
/* REVISIT: Not yet implemented */
+ /* Case 6: Cancel I/O by AIO control block */
+
+ printf("AIO test case 6: Cancel I/O by AIO control block\n");
+ g_fildes = open(AIO_FILEPATH, O_RDWR|O_CREAT|O_TRUNC);
+ if (g_fildes < 0)
+ {
+ printf("aio_test: ERROR: Failed to open %s: %d\n", AIO_FILEPATH, errno);
+ return;
+ }
+
+ init_aiocb(false);
+ ret = lio_listio(LIO_NOWAIT, g_aiocb, AIO_NCTRLBLKS, NULL);
+ if (ret < 0)
+ {
+ printf("aio_test: ERROR: lio_listio failed: %d\n", errno);
+ return;
+ }
+
+ ret = aio_cancel(g_fildes, g_aiocb[2]);
+ if (ret < 0)
+ {
+ printf("aio_test: ERROR: aio_cancel failed: %d\n", errno);
+ return;
+ }
+
+ printf(" aio_cancel return %d\n");
+
+ do
+ {
+ sleep(1);
+ ret = check_done();
+ }
+ while (ret < 0);
+
+ close(g_fildes);
+ g_fildes = -1;
+
+ /* Case 6: Cancel I/O by file descriptor */
+
+ printf("AIO test case 6:Cancel I/O by file descriptor\n");
+ g_fildes = open(AIO_FILEPATH, O_RDWR|O_CREAT|O_TRUNC);
+ if (g_fildes < 0)
+ {
+ printf("aio_test: ERROR: Failed to open %s: %d\n", AIO_FILEPATH, errno);
+ return;
+ }
+
+ init_aiocb(false);
+ ret = lio_listio(LIO_NOWAIT, g_aiocb, AIO_NCTRLBLKS, NULL);
+ if (ret < 0)
+ {
+ printf("aio_test: ERROR: lio_listio failed: %d\n", errno);
+ return;
+ }
+
+ ret = aio_cancel(g_fildes, NULL);
+ if (ret < 0)
+ {
+ printf("aio_test: ERROR: aio_cancel failed: %d\n", errno);
+ return;
+ }
+
+ printf(" aio_cancel return %d\n");
+
+ do
+ {
+ sleep(1);
+ ret = check_done();
+ }
+ while (ret < 0);
+
+ close(g_fildes);
+ g_fildes = -1;
}
diff --git a/nuttx/fs/aio/aio_cancel.c b/nuttx/fs/aio/aio_cancel.c
index 11bf950f7..21efe913e 100644
--- a/nuttx/fs/aio/aio_cancel.c
+++ b/nuttx/fs/aio/aio_cancel.c
@@ -160,11 +160,19 @@ int aio_cancel(int fildes, FAR struct aiocb *aiocbp)
*/
status = work_cancel(LPWORK, &aioc->aioc_work);
+ if (status >= 0)
+ {
+ aiocbp->aio_result = -ECANCELED;
+ ret = AIO_CANCELED;
+ }
+ else
+ {
+ ret = AIO_NOTCANCELED;
+ }
/* Remove the container from the list of pending transfers */
(void)aioc_decant(aioc);
- ret = status >= 0 ? AIO_CANCELED : AIO_NOTCANCELED;
}
}
}
@@ -201,14 +209,21 @@ int aio_cancel(int fildes, FAR struct aiocb *aiocbp)
/* Remove the container from the list of pending transfers */
- next = (FAR struct aio_container_s *)aioc->aioc_link.flink;
- (void)aioc_decant(aioc);
-
- /* Keep track of the return status */
+ next = (FAR struct aio_container_s *)aioc->aioc_link.flink;
+ aiocbp = aioc_decant(aioc);
+ DEBUGASSERT(aiocbp);
- if (ret != AIO_NOTCANCELED)
+ if (status >= 0)
+ {
+ aiocbp->aio_result = -ECANCELED;
+ if (ret != AIO_NOTCANCELED)
+ {
+ ret = AIO_CANCELED;
+ }
+ }
+ else
{
- ret = status >= 0 ? AIO_CANCELED : AIO_NOTCANCELED;
+ ret = AIO_NOTCANCELED;
}
}
}